<feed xmlns='http://www.w3.org/2005/Atom'>
<title>luke/esp32-poe-scrypted-viewport/scrypted/diagnostic.ts, branch main</title>
<subtitle>ESP32-POE Scrypted viewport (private)
</subtitle>
<id>https://src.nth.io/luke/esp32-poe-scrypted-viewport/atom?h=main</id>
<link rel='self' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/'/>
<updated>2026-07-18T00:49:47+00:00</updated>
<entry>
<title>scrypted: mdns discovery — browse, host choices, auto-heal</title>
<updated>2026-07-18T00:49:47+00:00</updated>
<author>
<name>Luke Hoersten</name>
<email>luke@hoersten.org</email>
</author>
<published>2026-07-18T00:49:47+00:00</published>
<link rel='alternate' type='text/html' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/commit/?id=3821512b18be69cad002faf77f1e5844bda13c95'/>
<id>urn:sha1:3821512b18be69cad002faf77f1e5844bda13c95</id>
<content type='text'>
Browse for _scrypted-viewport._tcp with a plain dgram socket on an
EPHEMERAL port: per RFC 6762 §6.7 a query from a non-5353 source port is
a legacy unicast query and responders reply unicast to that port —
verified in the ESP-IDF responder (mdns_send.c answers to the querier's
addr/port whenever src_port != 5353). No :5353 bind means no conflict
with Scrypted's own HomeKit mDNS or a host avahi-daemon, and it works
under Docker host-networking or native alike. One response packet
carries PTR+SRV+TXT+A (RFC 6763 §12.1), so parsing is per-packet with
no follow-up queries; the wire codec (name compression included) is
~150 lines, no dependencies.

Surfaced three ways:
- add-device form: host field is a combobox listing discovered
  viewports as "ip — name (vX, WxH)"; manual entry still works and
  only the address token is stored.
- child settings page: same choices on the existing host field.
- auto-heal: when a /config register fails, re-browse and match by MAC
  (seeded from /state and discovery; survives renames) then by name;
  on a hit at a new address, rewrite host and retry once. Runs only on
  register failure, so it's rate-limited to the 5-min cycle and removes
  the need for a DHCP reservation.

Browses are best-effort ([] on any failure) and cached 30s so settings
re-renders don't spam the LAN. diagnostic.ts gains the same browse as a
paste-and-run probe that validates dgram + multicast reachability from
inside the real Scrypted sandbox before trusting the feature.
</content>
</entry>
<entry>
<title>scrypted: code-review fixes — reload drain order, reconnect storm, wake guards</title>
<updated>2026-07-17T23:56:17+00:00</updated>
<author>
<name>Luke Hoersten</name>
<email>luke@hoersten.org</email>
</author>
<published>2026-07-17T23:56:17+00:00</published>
<link rel='alternate' type='text/html' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/commit/?id=0ac000e0db3feb235fae37389d0af18609e91c50'/>
<id>urn:sha1:0ac000e0db3feb235fae37389d0af18609e91c50</id>
<content type='text'>
- bootstrap: drain the shutdown-cleaner array FIRST, not after the child
  re-discovery loop. The old order tore down the listeners the loop had
  just attached, and since the instance maps still referenced them the
  attachListener fast-path blocked the 5-min register-cycle self-heal
  from ever re-attaching after a warm re-paste. The attach cleaner now
  also invalidates listeners/attachedCameraId (one cleaner per attach),
  so a drain by another instance can't strand dead registrations either.
- stream socket: single-flight reconnect scheduled from 'close' only.
  A failed connect emits 'error' then 'close'; scheduling from both
  doubled outstanding attempts every 500ms against a rebooting device.
  openStreamSocket also destroys the previous socket first.
- onRequest wake: same streams/streamStarting guard as every other start
  path (a concurrent second startStream overwrote the streams entry and
  orphaned the first ffmpeg), respond 204 immediately (the device's POST
  times out at 1s — awaiting startStream turned every tap-wake into a
  firmware state_post_failure), and skip the redundant wake POST back.
- startStream: bail-out paths after the wake POST (camera missing, no
  usable stream, ffmpeg-input conversion failure) now send a
  compensating sleep instead of stranding the panel on Loading; the
  last-ditch getVideoStream fallback no longer rejects out of the call.
- key streams/streamStarting/stopStream by nativeId — v.name drifts to
  the nativeId on reload, stranding or duplicating streams keyed under
  the drifted value; findByName matches display_name first for the same
  reason.
- idle_timeout_ms=0: the Scrypted-side safety timeout still reclaims
  ffmpeg/socket but no longer POSTs sleep over the always-on setting.
- pending bindingDebounce timers cleared across re-paste (they fired
  against the dead instance and attached duplicate listeners);
  releaseDevice drops lastRegisterSig/streamStarting/debounce entries.
- start() single-flights bootstrap; createDevice drops its redundant
  second registerViewport; streamLogger rolls its window on quiet ticks
  (post-lull rates were diluted) and lastLogUs -&gt; lastLogMs; hoist the
  JPEG EOI needle + resume-scan offset in the demux loop; postJSON drops
  the dead 204 check; remove unused sandbox declares and the legacy
  streams.interval field.
- tsconfig: moduleResolution Node -&gt; Bundler (removed in TS 6).
</content>
</entry>
<entry>
<title>scrypted/diagnostic: probe for mDNS modules ahead of auto-discovery</title>
<updated>2026-06-15T01:27:06+00:00</updated>
<author>
<name>Luke Hoersten</name>
<email>luke@hoersten.org</email>
</author>
<published>2026-06-15T01:27:06+00:00</published>
<link rel='alternate' type='text/html' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/commit/?id=97a177b3dd134b5457c5a96688626f7cdfe53a6d'/>
<id>urn:sha1:97a177b3dd134b5457c5a96688626f7cdfe53a6d</id>
<content type='text'>
</content>
</entry>
<entry>
<title>scrypted: add diagnostic.ts to probe scriptedEval scope on user's core 0.3.147</title>
<updated>2026-06-15T00:18:18+00:00</updated>
<author>
<name>Luke Hoersten</name>
<email>luke@hoersten.org</email>
</author>
<published>2026-06-15T00:18:18+00:00</published>
<link rel='alternate' type='text/html' href='https://src.nth.io/luke/esp32-poe-scrypted-viewport/commit/?id=30459a0d37d6ec390b36c8309fac7b12cb50de8c'/>
<id>urn:sha1:30459a0d37d6ec390b36c8309fac7b12cb50de8c</id>
<content type='text'>
</content>
</entry>
</feed>
