Add packaged Insta360 X4 integration and recover paired Node channels

Discover independent camera instances and prepare their versioned runtime
from Node or remote Core. Add isolated SDK workers, camera controls, raw
dual-fisheye WebRTC preview, and shared action/region loading states.

Recover existing Node bindings over known Tailscale addresses after a Core
LAN address change. Preserve identities and trust, pin both peers, migrate
endpoints with revision checks, and require real heartbeats for online status.
Fix the Python client certificate profile for Go X509 verification.

Pin Design Guideline 8c53f73 and retain installer/build/acceptance history.
Node 0.8.19 is installed; X4 0.1.3-3 is bundled but hardware activation is pending.

Validation: qualified DG/Node builds and Go race tests; 31 fleet tests;
Python-to-Go certificate interoperability and live tailnet recovery with five
fresh heartbeats; prior 38 X4 tests and bounded remote WebRTC acceptance.
Clean-OS, replug/power autonomy, local X4 video and long-run stability remain open.
This commit is contained in:
DCCONSTRUCTIONS
2026-09-10 09:21:24 +03:00
parent 54a85fdf50
commit a3c15e11e9
125 changed files with 11916 additions and 251 deletions
+114
View File
@@ -0,0 +1,114 @@
"""Bounded image verification; packets alone never count as a working camera."""
import time
from .errors import failure
from .operations import UNKNOWN
class Control:
def __init__(self, camera, feed=None):
self.camera = camera
self.feed = feed
self.verified = False
def call(self, action, values):
if action == "verify":
return self.verify()
if self.feed and action in ("preview.start", "preview.stop"):
# The native adapter treats an already reached state as a no-op.
# Preserve the same feed generation: clearing it would discard the
# only initial keyframe even though the camera sends no new START.
current = self.camera.call("details", {})
target = 1 if action == "preview.start" else 0
if (
current.get("state") == "complete"
and current.get("result", {}).get("connected") is True
and current["result"].get("preview") == target
):
return self.camera.call(action, values)
return self.feed.change(lambda: self.camera.call(action, values))
return self.camera.call(action, values)
def verify(self, timeout=8):
import av
self.verified = False
result = self.camera.call("details", {})
status = result.get("result", {})
if (
result.get("state") != "complete"
or status.get("connected") is not True
or status.get("recording") != 0
or status.get("preview") not in (0, 1)
):
return failure("verification_recording_active")
owned = status["preview"] == 0
decoders, observed = {}, {}
outcome = failure("preview_no_decodable_image")
start = time.monotonic()
read_video = self.feed.reader() if self.feed else self.camera.video
try:
if owned and self.call("preview.start", {}).get("state") != "complete":
return dict(UNKNOWN)
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
value = read_video()
if value is None:
time.sleep(0.01)
continue
header, data = value
index, codec, generation = (
header["stream_index"],
header["codec"],
header["generation"],
)
name = "h264" if codec == 0 else "hevc" if codec == 1 else None
if index not in (0, 1) or name is None:
return dict(UNKNOWN)
key = (index, codec, generation)
if header.get("gap") or index not in decoders or decoders[index][0] != key:
decoder = av.CodecContext.create(name, "r")
decoder.thread_count = 1
decoders[index] = (key, decoder)
observed.pop(index, None)
decoder = decoders[index][1]
try:
for packet in decoder.parse(data):
for frame in decoder.decode(packet):
if not (0 < frame.width <= 4096 and 0 < frame.height <= 2160):
return dict(UNKNOWN)
current = observed.setdefault(
index,
{
"stream_index": index,
"codec": name,
"width": frame.width,
"height": frame.height,
"frames": 0,
},
)
current["frames"] += 1
except av.error.FFmpegError:
decoders.pop(index, None)
observed.pop(index, None)
continue
if any(item["frames"] >= 2 for item in observed.values()):
outcome = {
"state": "complete",
"result": {
"verified": True,
"streams": list(observed.values()),
"duration_ms": round((time.monotonic() - start) * 1000),
},
}
break
finally:
if owned:
try:
if self.call("preview.stop", {}).get("state") != "complete":
outcome = dict(UNKNOWN)
except (RuntimeError, ValueError, OSError):
outcome = dict(UNKNOWN)
self.verified = outcome["state"] == "complete"
return outcome