{"id":550,"date":"2026-09-26T21:21:29","date_gmt":"2026-09-26T20:21:29","guid":{"rendered":"https:\/\/www.fabidouille.com\/?p=550"},"modified":"2026-10-03T19:24:04","modified_gmt":"2026-10-03T18:24:04","slug":"pioneer-avr","status":"publish","type":"post","link":"https:\/\/www.fabidouille.com\/?p=550","title":{"rendered":"Le Port Est Mort, Vive le Port"},"content":{"rendered":"<p>Every forum says the Ethernet port of my 2009 Pioneer SC-LX73 receiver is only for internet radio and firmware updates. Internet radio on this model has been dead for years, so: a dead port.<\/p>\n<p>I wanted Kodi to switch on the amp for movie night. So before giving up, I plugged in a cable and looked at what goes on the wire.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/www.fabidouille.com\/wp-content\/uploads\/2026\/09\/front.jpg\" alt=\"Front of the Pioneer SC-LX73 AV receiver: input selector and master volume knobs on each side of the display\"\/><figcaption>The receiver, a Pioneer SC-LX73 from around 2009.<\/figcaption><\/figure>\n<h2 class=\"wp-block-heading\">A dead port? No, it was waiting<\/h2>\n<p>I connected the Kodi Pi (LibreELEC) directly to the receiver. Link light on, nothing else.<\/p>\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/www.fabidouille.com\/wp-content\/uploads\/2026\/09\/lan-port.jpg\" alt=\"Rear panel of the receiver: a white Ethernet cable plugged into the LAN (10\/100) port\"\/><figcaption>The &lsquo;dead&rsquo; port.<\/figcaption><\/figure>\n<p>LibreELEC has no tcpdump, so I wrote a small Python sniffer:<\/p>\n<pre class=\"wp-block-code\"><code>[ 23.4s] [the AVR]  UDP 68-&gt;67 [DHCP DISCOVER]\n[ 31.0s] [the AVR]  UDP 68-&gt;67 [DHCP DISCOVER]   &lt;- every ~18s<\/code><\/pre>\n<p>The receiver was asking for an IP address. On a direct cable, nobody answers. It was probably asking since 2009.<\/p>\n<p>The fix: a 60-line DHCP server in Python on the Pi, only for Pioneer&rsquo;s MAC prefix. The receiver got its address.<\/p>\n<h2 class=\"wp-block-heading\">What is behind<\/h2>\n<pre class=\"wp-block-code\"><code>OPEN  23\/tcp     &lt;- telnet\nOPEN  80\/tcp     &lt;- web server\nOPEN  8102\/tcp   &lt;- unknown<\/code><\/pre>\n<p>The web page is a complete remote control. The HTTP server says <code>Server: Nu-OS\/1.13<\/code>, and the page is called \u00ab\u00a0Pioneer Web Control System\u00a0\u00bb. Its JavaScript (<code>js\/common.js<\/code>) shows how each button works:<\/p>\n<pre class=\"wp-block-code\"><code>a = \"EventHandler.asp?WebToHostItem=\";\nb = encodeURIComponent(query);           \/\/ \"BPO\", \"VU\", \"19ZT\"\nreq.open(\"get\", c, true);                \/\/ GET \/EventHandler.asp?WebToHostItem=BPO<\/code><\/pre>\n<p>There is even a function called <code>webCon.http.sndRs232cEvent(query)<\/code>. The state comes back as JSON from <code>GET \/StatusHandler.asp<\/code>. So each button just sends an RS-232 command over HTTP:<\/p>\n<ul class=\"wp-block-list\">\n<li>Power: <code>BPO<\/code> on, <code>BPF<\/code> off<\/li>\n<li>Volume: <code>VU<\/code> up, <code>VD<\/code> down<\/li>\n<li>Mute: <code>MO<\/code> \/ <code>MF<\/code><\/li>\n<li>Input: <code>19ZT<\/code> (my theatre input)<\/li>\n<li>Listening mode: <code>0001SR<\/code> stereo, <code>0010SR<\/code> standard surround, <code>0050SR<\/code> Home THX<\/li>\n<li>Status: <code>?AST<\/code>, <code>?M<\/code>&#8230;<\/li>\n<\/ul>\n<p>Telnet gives the same commands, directly: <code>?AST<\/code> answers <code>AST0302\u2026<\/code>, <code>?M<\/code> answers <code>MUT1<\/code>. No login, no session, ASCII ending with CR. Like in 2009.<\/p>\n<p>First test, one that can be undone (I like this amp): volume 104 \u2192 101 \u2192 104, checked each time. It works. Ouf.<\/p>\n<h2 class=\"wp-block-heading\">Kodi controls the amp<\/h2>\n<p>A small script asks Kodi every half second:<\/p>\n<ul class=\"wp-block-list\">\n<li>Kodi volume \u2192 <code>VU<\/code> \/ <code>VD<\/code> on the amp, then Kodi&rsquo;s own volume goes back to 100: the amp is the only volume button. Tested: Kodi 100 \u2192 90 moved the amp from 104 to 101.<\/li>\n<li>Kodi mute \u2192 <code>MO<\/code> \/ <code>MF<\/code><\/li>\n<li>Playback starts \u2192 power on + input 19<\/li>\n<\/ul>\n<pre class=\"wp-block-code\"><code>curl -s \"http:\/\/&lt;avr&gt;\/EventHandler.asp?WebToHostItem=BPO\"     # power on\ncurl -s \"http:\/\/&lt;avr&gt;\/EventHandler.asp?WebToHostItem=19ZT\"    # theatre input\nprintf '?AST\\r' | nc -w 3 &lt;avr&gt; 23                            # raw RS-232 query<\/code><\/pre>\n<p>One problem: LibreELEC&rsquo;s network manager also wants the port, and sometimes the receiver ends up with a link-local address. My script just finds the address it has.<\/p>\n<p>There is no password: anyone on that cable can control the amp. That is why it is on its own cable, not on the home network.<\/p>\n<p>Movie night is now one button.<\/p>\n<h2 class=\"wp-block-heading\">How AI was used<\/h2>\n<p>An AI coding agent (Claude Code) did the network work through SSH on the Kodi Pi: the AF_PACKET sniffer, the 60-line DHCP server with the MAC filter, the port scan, reading the receiver&rsquo;s JavaScript, and the Kodi bridge. My part: plug the cable, and stay next to the amp for the first volume test.<\/p>\n<p>Note: I don&rsquo;t have much time for the blog these days, so this post was written with the help of an AI, from my own notes, then read and corrected by me. Better to share the content this way than not at all.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Every forum says the Ethernet port of a 2009 Pioneer receiver is useless. It was just waiting for an IP address, with telnet and a web remote behind it.<\/p>\n","protected":false},"author":0,"featured_media":548,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-550","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-non-classe"],"_links":{"self":[{"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/posts\/550","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=550"}],"version-history":[{"count":4,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/posts\/550\/revisions"}],"predecessor-version":[{"id":582,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/posts\/550\/revisions\/582"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=\/wp\/v2\/media\/548"}],"wp:attachment":[{"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=550"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=550"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fabidouille.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=550"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}