<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Ups on tsvinc</title>
		<link>https://tsvinc.dev/tags/ups/</link>
		<description>Recent content in Ups 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/ups/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Enable Wake-on-LAN on Fedora with a Realtek r8169 NIC</title>
				<link>https://tsvinc.dev/guides/wake-on-lan-fedora-r8169/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/guides/wake-on-lan-fedora-r8169/</guid>
				<description>&lt;p&gt;This sets magic-packet Wake-on-LAN on the wired NetworkManager connection of a Fedora-family host with a Realtek r8169 NIC, so the NIC stays awake after shutdown and the host powers on when a MikroTik router sends &lt;code&gt;/tool/wol&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;dl class=&#34;guide-scope&#34;&gt;&lt;div class=&#34;guide-scope-row&#34;&gt;&lt;dt&gt;Tested on&lt;/dt&gt;&lt;dd&gt;four Fedora-family hosts with Realtek r8169 NICs (the workstation and a mini PC on Fedora, the gaming PC on Bazzite, the storage box on Fedora), set with the script below; wake from power-off tested on two of them with a MikroTik router&#39;s &lt;code&gt;/tool/wol&lt;/code&gt;. The setting was re-checked on the workstation on 2026-11-02 (Fedora 44 NetworkManager 1.56.1, ethtool 7.1, kernel 7.2.13).&lt;/dd&gt;&lt;/div&gt;&lt;div class=&#34;guide-scope-row is-gap&#34;&gt;&lt;dt&gt;Not verified&lt;/dt&gt;&lt;dd&gt;OS, NetworkManager, ethtool and RouterOS versions of the first run &lt;code&gt;[UNVERIFIED: not recorded]&lt;/code&gt;; a wake test on the other two hosts; the rollback.&lt;/dd&gt;&lt;/div&gt;&lt;div class=&#34;guide-scope-row&#34;&gt;&lt;dt&gt;Needs&lt;/dt&gt;&lt;dd&gt;root on the host; Wake-on-LAN enabled in the BIOS/UEFI setup (check it there; I know of no way to read it from Linux); a wired link to the same LAN segment as the router; a RouterOS login that may run &lt;code&gt;/tool/wol&lt;/code&gt;.&lt;/dd&gt;&lt;/div&gt;&lt;div class=&#34;guide-scope-row&#34;&gt;&lt;dt&gt;Time&lt;/dt&gt;&lt;dd&gt;5 min per host, plus one power-off test.&lt;/dd&gt;&lt;/div&gt;&lt;div class=&#34;guide-scope-row&#34;&gt;&lt;dt&gt;Risk&lt;/dt&gt;&lt;dd&gt;the test powers the host off. After the change, anyone on the LAN segment who knows the NIC&#39;s MAC can power the host on: these NICs report &lt;code&gt;Supports Wake-on: pumbg&lt;/code&gt;, with no &lt;code&gt;s&lt;/code&gt;, so they cannot check a SecureOn password, and RouterOS&#39;s &lt;code&gt;/tool/wol&lt;/code&gt; cannot send one either. Reversible: see Undo.&lt;/dd&gt;&lt;/div&gt;&lt;/dl&gt;&#xA;&lt;h2 id=&#34;before-you-start&#34;&gt;Before you start&lt;a class=&#34;heading-anchor&#34; href=&#34;#before-you-start&#34; aria-label=&#34;Link to section: Before you start&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;Placeholders used below:&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;IF&amp;gt;&lt;/code&gt;: the wired interface name (mine: &lt;code&gt;enp1s0&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;CONN&amp;gt;&lt;/code&gt;: the NetworkManager connection on that interface (mine: &lt;code&gt;Wired connection 1&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;MAC&amp;gt;&lt;/code&gt;: the MAC address of &lt;code&gt;&amp;lt;IF&amp;gt;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;lt;BRIDGE&amp;gt;&lt;/code&gt;: the router interface that faces the host&#39;s LAN segment (mine: &lt;code&gt;bridge&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Check that the wired NIC uses &lt;code&gt;r8169&lt;/code&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-console&#34; data-lang=&#34;console&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gp&#34;&gt;$&lt;/span&gt; readlink -f /sys/class/net/enp1s0/device/driver&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;/sys/bus/pci/drivers/r8169&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Expected: a path ending in &lt;code&gt;r8169&lt;/code&gt;. The steps set generic NetworkManager and ethtool options, but r8169 is the only driver I ran them on.&lt;/li&gt;&#xA;&lt;li&gt;Find the active wired connection and its device:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gp&#34;&gt;$&lt;/span&gt; nmcli -t -f NAME,DEVICE,TYPE c show --active &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep 802-3-ethernet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;Wired connection 1:enp1s0:802-3-ethernet&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;Record the current values; Undo sets them back. In a root shell, run &lt;code&gt;nmcli -g 802-3-ethernet.wake-on-lan c show &#39;&amp;lt;CONN&amp;gt;&#39;&lt;/code&gt; and &lt;code&gt;ethtool &amp;lt;IF&amp;gt; | grep Wake-on&lt;/code&gt;. On all four of my hosts the first printed &lt;code&gt;default&lt;/code&gt;, and ethtool showed &lt;code&gt;Supports Wake-on: pumbg&lt;/code&gt; and &lt;code&gt;Wake-on: d&lt;/code&gt;, with Wake-on-LAN already on in the BIOS. &lt;code&gt;d&lt;/code&gt; means the NIC wakes on nothing; ethtool(8) lists the letters, and &lt;code&gt;g&lt;/code&gt; is the magic packet.&lt;/li&gt;&#xA;&lt;li&gt;Note the MAC for the router step: &lt;code&gt;cat /sys/class/net/&amp;lt;IF&amp;gt;/address&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;steps&#34;&gt;Steps&lt;a class=&#34;heading-anchor&#34; href=&#34;#steps&#34; aria-label=&#34;Link to section: Steps&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;Save the script as &lt;code&gt;enable-wol.sh&lt;/code&gt;.&lt;/strong&gt; It walks every active wired connection, sets &lt;code&gt;802-3-ethernet.wake-on-lan magic&lt;/code&gt; in NetworkManager (stored in the connection, applied on every activation) and &lt;code&gt;wol g&lt;/code&gt; with ethtool (applied now, no reconnect), then prints both values back.&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#!/bin/bash&#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;c1&#34;&gt;# Enable Wake-on-LAN (magic packet) on the wired NetworkManager connection. Run as root.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Persistent: NM applies it on every activation. Immediate: ethtool, no reconnect.&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;set&lt;/span&gt; -euo pipefail&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;E&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;command&lt;/span&gt; -v ethtool &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; /usr/sbin/ethtool&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nmcli -t -f NAME,DEVICE,TYPE c show --active &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;while&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;IFS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;read&lt;/span&gt; -r n dev t&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$t&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; 802-3-ethernet &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;continue&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  nmcli c modify &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; 802-3-ethernet.wake-on-lan magic&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$E&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; -s &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dev&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; wol g&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;hostname&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dev&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39;: nm=&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;nmcli -g 802-3-ethernet.wake-on-lan c show &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$n&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$E&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$dev&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep -E &lt;span class=&#34;s1&#34;&gt;&amp;#39;^\s*Wake-on:&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Run it as root.&lt;/strong&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo bash ./enable-wol.sh&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Expected: one line per wired connection, in the form &lt;code&gt;&amp;lt;hostname&amp;gt; &amp;lt;IF&amp;gt; &#39;&amp;lt;CONN&amp;gt;&#39;: nm=&amp;lt;VALUE&amp;gt; Wake-on: &amp;lt;LETTERS&amp;gt;&lt;/code&gt;, ending in &lt;code&gt;nm=magic Wake-on: g&lt;/code&gt;. All four hosts printed that ending. I did not keep the full lines, so none is shown here. The script runs with &lt;code&gt;set -euo pipefail&lt;/code&gt;: if a command fails, it stops there with a non-zero exit, without a line for that connection.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Power the host off.&lt;/strong&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-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl poweroff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Expected: the host shuts down. Leave its power cable in: Wake-on-LAN needs standby power at the NIC.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Send the magic packet from the router.&lt;/strong&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;/tool/wol mac=&amp;lt;MAC&amp;gt; interface=&amp;lt;BRIDGE&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Expected: the host powers on and boots. In my test I powered two hosts off at 22:45:53, sent the packet at 22:46:21, and they booted at 22:46:40 and 22:46:45, 19 s and 24 s after the packet. If it stays off: see Failure modes, row 1.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;verify&#34;&gt;Verify&lt;a class=&#34;heading-anchor&#34; href=&#34;#verify&#34; aria-label=&#34;Link to section: Verify&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;After the wake, in a root shell on the host, run &lt;code&gt;ethtool &amp;lt;IF&amp;gt; | grep Wake-on&lt;/code&gt;. Expected: &lt;code&gt;Wake-on: g&lt;/code&gt;. On my woken hosts &lt;code&gt;Wake-on: g&lt;/code&gt; was still set after boot. NetworkManager applies &lt;code&gt;magic&lt;/code&gt; on every activation of the connection; the ethtool call in the script only sets it right away, without a reconnect.&lt;/li&gt;&#xA;&lt;li&gt;The NetworkManager value can be read without root. On the workstation on 2026-11-02:&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-console&#34; data-lang=&#34;console&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gp&#34;&gt;$&lt;/span&gt; nmcli -g 802-3-ethernet.wake-on-lan c show &lt;span class=&#34;s2&#34;&gt;&amp;#34;Wired connection 1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;go&#34;&gt;magic&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;Expected: &lt;code&gt;magic&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;undo--rollback&#34;&gt;Undo / rollback&lt;a class=&#34;heading-anchor&#34; href=&#34;#undo--rollback&#34; aria-label=&#34;Link to section: Undo / rollback&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;In a root shell, set back the values you recorded in Before you start (mine: &lt;code&gt;default&lt;/code&gt; and &lt;code&gt;d&lt;/code&gt;). The script changed every active wired connection: repeat this for each &lt;code&gt;&amp;lt;CONN&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;IF&amp;gt;&lt;/code&gt; it printed.&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nmcli c modify &lt;span class=&#34;s1&#34;&gt;&amp;#39;&amp;lt;CONN&amp;gt;&amp;#39;&lt;/span&gt; 802-3-ethernet.wake-on-lan default&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ethtool -s &amp;lt;IF&amp;gt; wol d&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;code&gt;[UNVERIFIED: rollback not exercised]&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;failure-modes&#34;&gt;Failure modes&lt;a class=&#34;heading-anchor&#34; href=&#34;#failure-modes&#34; aria-label=&#34;Link to section: Failure modes&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;div class=&#34;table-wrap&#34; aria-label=&#34;Table: Symptom (exact message), Cause, Fix&#34;&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;th&gt;Symptom (exact message)&lt;/th&gt;&#xA;      &lt;th&gt;Cause&lt;/th&gt;&#xA;      &lt;th&gt;Fix&lt;/th&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;The host does not wake from power-off although the BIOS has Wake-on-LAN on; root &lt;code&gt;ethtool &amp;lt;IF&amp;gt;&lt;/code&gt; shows &lt;code&gt;Wake-on: d&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;td&gt;the connection had &lt;code&gt;802-3-ethernet.wake-on-lan default&lt;/code&gt;, and the NIC was powered down at shutdown&lt;/td&gt;&#xA;      &lt;td&gt;steps 1-2: set &lt;code&gt;magic&lt;/code&gt; on the connection&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;    &lt;tr&gt;&#xA;      &lt;td&gt;&lt;code&gt;netlink error: Operation not permitted&lt;/code&gt;, and no &lt;code&gt;Wake-on&lt;/code&gt; lines in the output&lt;/td&gt;&#xA;      &lt;td&gt;ethtool run as a normal user: reading Wake-on needs root&lt;/td&gt;&#xA;      &lt;td&gt;run &lt;code&gt;ethtool &amp;lt;IF&amp;gt;&lt;/code&gt; from a root shell&lt;/td&gt;&#xA;    &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;/div&gt;&lt;h2 id=&#34;field-notes&#34;&gt;Field notes&lt;a class=&#34;heading-anchor&#34; href=&#34;#field-notes&#34; aria-label=&#34;Link to section: Field notes&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;2026-11-02, the workstation, Fedora 44 (KDE Plasma Desktop Edition), kernel 7.2.13-200.fc44, NetworkManager 1.56.1, ethtool 7.1, r8169 on &lt;code&gt;enp1s0&lt;/code&gt;:&lt;/strong&gt; re-checked as a normal user. NetworkManager still had &lt;code&gt;magic&lt;/code&gt; on the wired connection. ethtool printed &lt;code&gt;netlink error: Operation not permitted&lt;/code&gt; and the rest of the link settings, with no Wake-on lines at all, so a user-level ethtool cannot show the NIC&#39;s Wake-on state. I did not re-read Wake-on as root this time.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;2026-10-20 &lt;code&gt;[UNVERIFIED: date from my project notes, not from the run&#39;s output]&lt;/code&gt;, four hosts (the workstation and a mini PC on Fedora, the gaming PC on Bazzite, the storage box on Fedora), all Realtek r8169, versions not recorded:&lt;/strong&gt; Wake-on-LAN was on in the BIOS of every host, and none of them stayed wakeable: ethtool showed &lt;code&gt;Supports Wake-on: pumbg&lt;/code&gt; with &lt;code&gt;Wake-on: d&lt;/code&gt;, and the wired NetworkManager connection had &lt;code&gt;802-3-ethernet.wake-on-lan default&lt;/code&gt;, so the NIC powered down at shutdown. I ran &lt;code&gt;enable-wol.sh&lt;/code&gt; on all four; each printed &lt;code&gt;nm=magic Wake-on: g&lt;/code&gt;. Then (same day or later, the test&#39;s date was not recorded) I powered two of them off at 22:45:53, sent &lt;code&gt;/tool/wol mac=&amp;lt;MAC&amp;gt; interface=bridge&lt;/code&gt; from the MikroTik router at 22:46:21, and they booted at 22:46:40 and 22:46:45. &lt;code&gt;Wake-on: g&lt;/code&gt; was still set after boot.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;notes&#34;&gt;Notes&lt;a class=&#34;heading-anchor&#34; href=&#34;#notes&#34; aria-label=&#34;Link to section: Notes&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Why I needed it:&lt;/strong&gt; the hosts run on power stations that keep their outlets live through an outage, so a host that &lt;code&gt;upsmon&lt;/code&gt; shut down never sees power disappear and never comes back by itself (&lt;a href=&#34;https://tsvinc.dev/posts/ups-observer-speaks-nut/&#34;&gt;the observer design post&lt;/a&gt;). That design has the observer send Wake-on-LAN after an outage; here I sent the packet from the router by hand. When a station&#39;s output did drop on 2026-11-02, the storage box came back by itself, probably through the BIOS power-on-after-AC-loss setting, which I have not checked (&lt;a href=&#34;https://tsvinc.dev/posts/three-shutdowns-three-causes/&#34;&gt;three shutdowns, three causes&lt;/a&gt;). The &lt;code&gt;upsmon&lt;/code&gt; side is in Run upsmon as a NUT secondary on Fedora and Fedora Atomic.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Only &lt;code&gt;g&lt;/code&gt;:&lt;/strong&gt; the NICs also support &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;u&lt;/code&gt;, &lt;code&gt;m&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; (wake on PHY activity, unicast, multicast, broadcast); each of those can wake the host on ordinary traffic. I enabled the magic packet only.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;default&lt;/code&gt; is not &amp;quot;off&amp;quot; by name:&lt;/strong&gt; per the nmcli settings reference, &lt;code&gt;default&lt;/code&gt; means &amp;quot;use global settings&amp;quot;, and &lt;code&gt;ignore&lt;/code&gt; stops NetworkManager from managing Wake-on-LAN at all. A global value in NetworkManager.conf (&lt;code&gt;ethernet.wake-on-lan&lt;/code&gt;) is another way to set it for every connection; I have not tried it.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ethtool path:&lt;/strong&gt; the script uses &lt;code&gt;ethtool&lt;/code&gt; from &lt;code&gt;PATH&lt;/code&gt; and falls back to &lt;code&gt;/usr/sbin/ethtool&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Router without &lt;code&gt;interface=&lt;/code&gt;:&lt;/strong&gt; per the MikroTik docs, RouterOS then sends the packet as an IP broadcast from the default gateway interface. I always gave the interface.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;sources&#34;&gt;Sources&lt;a class=&#34;heading-anchor&#34; href=&#34;#sources&#34; aria-label=&#34;Link to section: Sources&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://networkmanager.dev/docs/api/latest/nm-settings-nmcli.html&#34;&gt;nmcli settings reference, &lt;code&gt;802-3-ethernet.wake-on-lan&lt;/code&gt;&lt;/a&gt;: the flag values &lt;code&gt;magic&lt;/code&gt;, &lt;code&gt;default&lt;/code&gt; (use global settings) and &lt;code&gt;ignore&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://networkmanager.dev/docs/api/latest/NetworkManager.conf.html&#34;&gt;NetworkManager.conf&lt;/a&gt;: &lt;code&gt;ethernet.wake-on-lan&lt;/code&gt; as a global per-device default.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://man7.org/linux/man-pages/man8/ethtool.8.html&#34;&gt;ethtool(8)&lt;/a&gt;: the &lt;code&gt;wol&lt;/code&gt; letters &lt;code&gt;p u m b a g s f d&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://help.mikrotik.com/docs/spaces/ROS/pages/120782862/Wake+on+LAN&#34;&gt;MikroTik RouterOS: Wake on LAN&lt;/a&gt;: &lt;code&gt;/tool wol&lt;/code&gt; with &lt;code&gt;mac&lt;/code&gt; and &lt;code&gt;interface&lt;/code&gt;; no SecureOn support.&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
			</item>
			<item>
				<title>The DJI went silent for four hours</title>
				<link>https://tsvinc.dev/posts/dji-went-silent-four-hours/</link>
				<pubDate>Mon, 02 Nov 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/dji-went-silent-four-hours/</guid>
				<description>&lt;p&gt;&lt;a href=&#34;https://tsvinc.dev/posts/dji-power-2000-ups-over-bluetooth/&#34;&gt;Part 4&lt;/a&gt; ended on a rule for the observer, the Go service on my router that turns two power stations&#39; readings into NUT (Network UPS Tools) status for the machines they keep running: a DJI that stops answering for minutes is an alert in its own right, never a sign that the grid is fine. On 20 October the DJI Power 2000 stopped answering at about 13:10. It answered again a little before 18:00, after I power-cycled it. While the grid was up, nothing alerted me to the silence.&lt;/p&gt;</description>
			</item>
			<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>Pulling plugs on purpose</title>
				<link>https://tsvinc.dev/posts/pulling-plugs-on-purpose/</link>
				<pubDate>Sun, 18 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/pulling-plugs-on-purpose/</guid>
				<description>&lt;p&gt;A test that passes tells you the thing works. That is the reading everyone defaults to, and the first power-bank test of the ESP32 bridge was a clean example of why it&#39;s wrong.&lt;/p&gt;&#xA;&lt;p&gt;The bridge from &lt;a href=&#34;https://tsvinc.dev/posts/esp32-bluetti-ac180-bridge/&#34;&gt;the second UPS post&lt;/a&gt; runs off a USB power bank, which charges from the wall. The worry was simple: when the grid goes and the power bank stops charging, does it hold its output steady, or does the board reboot right at the start of the outage it is supposed to report? I cut the power bank&#39;s charging, and the board&#39;s uptime counter kept going, from 14160 seconds to 14180. No reboot.&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>The pin template was for a different plug</title>
				<link>https://tsvinc.dev/posts/tuya-plug-openbeken-grid-canary/</link>
				<pubDate>Fri, 16 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/tuya-plug-openbeken-grid-canary/</guid>
				<description>&lt;p&gt;The smart plug&#39;s vendor app put its energy monitoring behind a subscription. The metering chip inside measures voltage alongside current and power all the same, whatever the app agrees to show. I wanted that voltage. Read off a plug on wall power, it says whether the grid is up, and my &lt;a href=&#34;https://tsvinc.dev/posts/bluetti-ac180-ups-over-bluetooth/&#34;&gt;power-station UPS&lt;/a&gt; needed exactly that: a second opinion on the grid from something not behind a battery.&lt;/p&gt;&#xA;&lt;p&gt;So the plug had to leave Tuya&#39;s firmware for &lt;a href=&#34;https://github.com/openshwprojects/OpenBK7231T_App&#34;&gt;OpenBeken&lt;/a&gt;, an open firmware for the Beken chips in most Tuya plugs. That took one evening. Getting the pins right took the next day, because the template I borrowed was for a different plug, and the plug&#39;s own leftover settings were the only thing that knew.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The DJI&#39;s grid flag is labeled charge type</title>
				<link>https://tsvinc.dev/posts/dji-power-2000-ups-over-bluetooth/</link>
				<pubDate>Thu, 15 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/dji-power-2000-ups-over-bluetooth/</guid>
				<description>&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;Update, 2026-11-02:&lt;/strong&gt; The station&#39;s minutes field has a second meaning. Byte 4 of its battery record (tag &lt;code&gt;0x3020&lt;/code&gt;) is a time type, and while it is &lt;code&gt;1&lt;/code&gt; the minutes are a recharging time, the time to full charge, not a runtime. The bridge now leaves &lt;code&gt;runtime_min&lt;/code&gt; out whenever that byte says recharging, and the observer ignores the field while input power flows. The story is in &lt;a href=&#34;https://tsvinc.dev/posts/ups-said-two-minutes-at-95/&#34;&gt;The UPS said 2 minutes at 95 %&lt;/a&gt;.&lt;/p&gt;&#xA;&#xA;&lt;/blockquote&gt;</description>
			</item>
			<item>
				<title>Secure session ready. Battery: ?</title>
				<link>https://tsvinc.dev/posts/esp32-bluetti-ac180-bridge/</link>
				<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/esp32-bluetti-ac180-bridge/</guid>
				<description>&lt;p&gt;Porting a key exchange from Python to C++ should be the boring part. The Python works, it is already validated against this exact station, and mbedTLS ships every primitive it uses: MD5, AES-CBC, P-256, ECDSA, ECDH. Translate, compile, flash. The first run on the ESP32 went along with that, right up to the last line:&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;found AC180&amp;lt;redacted&amp;gt; XX:XX:XX:XX:XX:XX rssi=-57&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;connected, mtu=517&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KEX: challenge answered&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KEX: challenge accepted&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KEX: pubkey sent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KEX: pubkey sent&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;KEX: secure session ready&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;handshake 1913 ms&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;RESULT BATTERY_SOC=? DC_OUTPUT_POWER=? AC_OUTPUT_POWER=?&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every step of the handshake reported success. Then came the reads, the part that was supposed to be easy, and the first three came back as question marks. The capture ended there.&lt;/p&gt;</description>
			</item>
			<item>
				<title>The power went out twice. My UPS log saw it once.</title>
				<link>https://tsvinc.dev/posts/bluetti-ac180-ups-over-bluetooth/</link>
				<pubDate>Wed, 14 Oct 2026 00:00:00 +0000</pubDate>
				<guid>https://tsvinc.dev/posts/bluetti-ac180-ups-over-bluetooth/</guid>
				<description>&lt;p&gt;Thirty lines of log, one outage. Twenty-two lines on grid, seven on battery, one back on grid. Clean, readable, and short by one event: the plug came out of the wall twice.&lt;/p&gt;&#xA;&lt;p&gt;The setup itself works. A BLUETTI AC180 portable power station sits between the wall and my workstation as a UPS. Linux reads it over Bluetooth LE, through an encrypted link, with no account and no pairing, in about nine seconds per read. What it can&#39;t do is tell you about anything that happens between two of those reads. Neither can anything else built on polling. This one put it in writing.&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>
