<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Nut on tsvinc</title>
		<link>https://tsvinc.dev/tags/nut/</link>
		<description>Recent content in Nut on tsvinc</description>
		<generator>Hugo</generator>
		<language>en-us</language>
		
		
		
		
			<lastBuildDate>Mon, 02 Nov 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://tsvinc.dev/tags/nut/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>The UPS said 2 minutes at 95 %</title>
				<link>https://tsvinc.dev/posts/ups-said-two-minutes-at-95/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/ups-said-two-minutes-at-95/</guid>
				<description>&lt;p&gt;My storage box and gaming PC run on a DJI Power 2000 power station used as a UPS, and a monitor on my router decides when they shut down. At 11:39:39 on 1 November, twenty-three minutes into a power cut, my alert channels got this from it:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ups dji2000-t2: LOW BATTERY, its hosts should shut down (runtime 2m0s &amp;lt;= 20m0s (ABC))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the same for the third tier, against its 8-minute limit. Two minutes of runtime left on the DJI. I could see the station&#39;s display at the time. It said about 95 %.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Three shutdowns, three causes</title>
				<link>https://tsvinc.dev/posts/three-shutdowns-three-causes/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/three-shutdowns-three-causes/</guid>
				<description>&lt;p&gt;My storage box sits on a DJI Power 2000 used as a UPS. Over two days, 1 and 2 November, it went down a few times. Some of those had an obvious reason and some had none, and every time I looked, the DJI showed about 95 %. I went in looking for one fault: something that turns a full battery into a dead machine.&lt;/p&gt;&#xA;&lt;p&gt;There were three, and only one of them was clearly the station.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The alert about the blackout needs the internet too</title>
				<link>https://tsvinc.dev/posts/ups-alerts-survive-the-outage/</link>
				<pubDate>Sat, 17 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/ups-alerts-survive-the-outage/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://tsvinc.dev/posts/nut-observer-fails-safe/&#34;&gt;Part 5&lt;/a&gt; left the observer able to shut machines down and unable to tell me anything, with one item still open: an alert for an observer that stops. The alerts looked like one function. Log the line, and if a notifier is configured, hand it over:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;alertf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;any&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Sprintf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;format&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Print&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;alerts&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;alerts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Send&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;msg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That function hasn&#39;t changed since. The file around it, &lt;code&gt;notify.go&lt;/code&gt;, is now 217 lines, and its tests are another 197. Most of it comes from one inconvenient fact: a message about a power cut leaves through an internet uplink, and the cut can take the uplink with it. I can keep the router running on battery. I can&#39;t vouch for anything upstream of it.&lt;/p&gt;</description>
			</item>
			<item>
				<title>A null battery reading cleared the low-battery alarm</title>
				<link>https://tsvinc.dev/posts/nut-observer-fails-safe/</link>
				<pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/nut-observer-fails-safe/</guid>
				<description>&lt;p&gt;Here is the first version of the observer handling a station at 12 % charge, on battery, followed by a reading where the bridge couldn&#39;t decode the charge:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;=== RUN   TestProbeNullSoCClearsLB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    probe_test.go:20: soc 12 -&amp;gt; &amp;#34;OB DISCHRG LB&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    probe_test.go:25: then soc null -&amp;gt; &amp;#34;OB DISCHRG&amp;#34;, battery.charge present=false&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;--- PASS: TestProbeNullSoCClearsLB (0.00s)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;OB DISCHRG LB&lt;/code&gt; is the line that makes every machine on that tier shut down. One reading later, it was gone. A &lt;code&gt;null&lt;/code&gt; in the bridge&#39;s JSON means &amp;quot;I couldn&#39;t read this field&amp;quot;, and the observer had treated it as &amp;quot;nothing to worry about&amp;quot;. With no charge in the latest reading, the low-battery check had nothing to compare against its threshold. &lt;code&gt;LB&lt;/code&gt; dropped and &lt;code&gt;battery.charge&lt;/code&gt; vanished from the replies. In a real outage the hosts would have been stood down while the battery kept draining.&lt;/p&gt;</description>
			</item>
			<item>
				<title>Twenty-five percent is a countdown</title>
				<link>https://tsvinc.dev/posts/ups-observer-speaks-nut/</link>
				<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/ups-observer-speaks-nut/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update, 2026-11-02:&lt;/strong&gt; The thresholds in this design (60, 35 and 15 % for the three tiers, with the first tier also acting after 5 minutes on battery) are no longer the deployed ones. Since 2026-11-02 all three tiers act at 15 % or 8 minutes of runtime, with no on-battery timer. Why is in &lt;a href=&#34;https://tsvinc.dev/posts/three-shutdowns-three-causes/&#34;&gt;Three shutdowns, three causes&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The NUT client&#39;s man page has a sentence that decided most of this design before any of it was drawn:&lt;/p&gt;</description>
			</item>
	</channel>
</rss>
