Releases: themactep/thingino-firmware
Releases · themactep/thingino-firmware
Release list
firmware-2026-08-14
Changes in this release:
- 2c3eca5 wpa_supplicant: re-disable P2P and MATCH_IFACE after configure buildroot's WPA_SUPPLICANT_CONFIGURE_CMDS ends with a loop that re-adds any CONFIG_ENABLE symbol whose uncommented line is missing. CONFIG_P2P (via AP_SUPPORT) and CONFIG_MATCH_IFACE (base list) are in buildroot's ENABLE list, so the DISABLE sed comments them out and the loop appends them back as =y, defeating the override and bloating the binary (~52%). Disable the two again in a post-configure hook, after buildroot's loop. Signed-off-by: Paul Philippov paul@themactep.com
- 7c9cf8f isp-inspector: make live badge health absolute ranges Derive every live badge color from the current absolute value only, never from the previous sample, and align thresholds with the issue log. - add healthAbove/healthBelow classifiers (ok/warn/crit) - FPS ok >= 15, warn 10-15, crit < 10 (matches the issue log) - DMA queue ok >= 3, warn 2, crit < 2 - drops and interrupt-ahead ok 0, warn 1-9, crit >= 10 - digital gain warn only while analog gain has headroom, crit at max - match issue-log severities to the same bands Signed-off-by: Paul Philippov paul@themactep.com
- 90dfeb3 external.mk: exclude -override.mk from package glob The -override.mk fragments are already included through BR2_PACKAGE_OVERRIDE_FILE (thingino-overrides.mk). external.mk's package//.mk glob picked them up a second time, so every override ran twice. Harmless for idempotent overrides (duplicate sed expressions), but a real bug for any override that registers hooks or uses non-idempotent +=. Signed-off-by: Paul Philippov paul@themactep.com
- 2921579 uboot: restore binary blobs dropped by GNU patch GNU patch cannot apply the "Binary files differ" hunks in the 2013.07-to-thingino patch, so the blobs vendored in the bundle came out empty after patching. Only the three prebuilt SPL images were restored; the host tools, logos, GPT/MBR blobs and NAND manager library were silently lost. Vendor all thirty binaries under package/thingino-uboot/files/, mirroring the U-Boot source layout, and copy the whole directory back in a single post-patch hook. The extracted tarball plus the 2013.07 patch set is now byte-identical to the previous git checkout, apart from the follow-up text patches. Signed-off-by: Paul Philippov paul@themactep.com
- 6598e3f soc/ingenic: state a family's shared values once (#1451) The family files enumerated one ifeq block per model, so a value the whole family shares got repeated once per model. t33 named isvp_t33_sfcnor eight times; a1 and t21 named theirs five times each; t10 repeated its RAM size three times. State what the models share once, and express what differs as an exhaustive if/else: # what's common SOC_ARCH := xburst1 SOC_FAMILY := t33 SOC_UBOOT_NOR := isvp_t33_sfcnor # what's different ifneq (
$(filter $ (SOC_MODEL),t33n t33vn t33zn),) SOC_RAM_MB := 128 else SOC_RAM_MB := 64 endif No variable is assigned a value that a later line replaces. A default with per-model overrides would read shorter still, but it means every model briefly holds a value that is wrong for it, and a model added to the filter and nowhere else would inherit that default rather than being noticed. Which value is common differs by family. t10 shares a RAM size and splits on the bootloader; a1 and t21 share a bootloader and split on RAM; t20, t40 and t41 vary in both, so their branches carry both lines. t41 gains least -- its six parts take six different NAND defconfigs -- but a per-model ladder still reads shorter than six ifeq blocks. Changed: a1, t10, t20, t21, t33, t40, t41 -- 153 lines out, 63 in. Left alone: c100 has one model. t23, t30, t31 and t32 have a distinct bootloader per model with no majority to hoist, so this would save a line or two while making a model's values harder to find. t31's eight models carry five NOR defconfigs and six NAND ones -- that table is earning its length. No functional change, verified two ways: 1. Evaluated both versions for all 35 models the seven filters claim and diffed every variable they set (SOC_FAMILY, SOC_ARCH, SOC_RAM_MB, SOC_UBOOT_NOR, SOC_UBOOT_NAND, SOC_UBOOT_BIN). Identical. 2. Checked that no file assigns a variable at both the common level and inside a branch. Worth doing properly because 27 of the 54 models have no camera config -- including all eight t33 parts -- so no build would have caught a wrong value. Co-authored-by: John Chia john@johnchia.com Co-authored-by: Paul Philippov themactep@gmail.com - a429e0a usbnet: fix MAC address lookup in CDC NCM scripts (#1463) The S36cdcnet and S36cdcnet-client scripts read ethaddr from U-Boot env via fw_printenv, but S03mac never set ethaddr in the env - it only stored MACs in thingino.json. When ethaddr is absent, both scripts fail. - S03mac: also persist eth MAC to U-Boot env (ethaddr) for network ops - S36cdcnet: add jct fallback for eth.mac, save MAC before decrement_mac, remove redundant second fw_printenv call - S36cdcnet-client: fix pre-existing bug where ethaddr was never read before decrement_mac, add jct fallback, remove redundant fw_printenv Reported-by: Josh <@wltechblog> Signed-off-by: WLTB-Gino gino@wltechblog.com Co-authored-by: WLTB Gino gino@wltb.local
- 1951efc scripts: add local site method support to manage-package-overrides (#1464) The manage-package-overrides.sh script only supported cloning git repos for package overrides. Packages using SITE_METHOD = local (e.g. usbnet, where source lives in package//files/) would fail with 'Unsupported site method: local'. This patch adds a local branch to download_package() that copies the package source files into overrides// instead of cloning, and registers the override in local.mk just like git packages. Signed-off-by: WLTB-Gino gino@wltechblog.com Co-authored-by: WLTB Gino gino@wltb.local
- f342e06 webui: raptor/timps preview pages, install-order fix (no plugin schema change) (#1460) * thingino-raptor: install preview.html directly, drop plugin indirection Simpler alternative to the "provides" manifest key added and then reverted in this branch's history, per upstream review feedback: rather than a new manifest schema entry that assemble_plugins.py has to resolve and apply, raptor's preview page just uses the exact same filename as core webui's (files/www/preview.html, moved from thingino-webui into thingino-raptor) and is installed straight over it. thingino-webui.mk drops the BR2_PACKAGE_THINGINO_STREAMER_RAPTOR ifeq that used to pick preview-raptor.html vs preview.html at ITS OWN install time - core webui always installs its own default now, no knowledge of raptor. raptor's THINGINO_RAPTOR_INSTALL_TARGET_CMDS overwrites it with its own copy, gated on THINGINO_RAPTOR_DEPENDENCIES += thingino-webui (added earlier in this branch) for ordering: that dependency guarantees the stock page exists first, and raptor's own per-package install step always completes before Buildroot's global target-finalize phase - where thingino-webui's plugin-assembly hook lives - runs. So by the time assembly processes preview.html, raptor's version is already there, and it comes out the other side with the normal plugin layer (<script src="/a/plugins.js">, nav data, THINGINO_PLUGIN_PREVIEW_BODY overlays) same as any other page. No manifest, no assemble_plugins.py changes. Also keeps THINGINO_WEBUI_ASSEMBLE_PLUGINS failing the build on any assemble_plugins.py error instead of printing "non-fatal" and continuing - independent of this change, but was bundled with it upstream; every error that script raises (duplicate plugin name, two plugins claiming the same page) is a real manifest conflict that silently ships a broken WebUI if swallowed. Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com * timps: install preview.html directly, drop plugin manifest indirection Same simplification as the previous commit for thingino-raptor, applied to timps: files/www/preview-timps.html is renamed to files/www/preview.html (same filename core webui uses) and package/timps/files/timps.webui.json (a manifest that existed only to declare the swap) is dropped entirely. Unlike raptor, timps needed no new install step at all: preview.html now sits in the same files/www/*.html directory TIMPS_INSTALL_WEBUI_CGIS already glob-installs for its other ~15 native pages (
for f in $(TIMPS_PKGDIR)/files/www/*.html), so it goes out through that existing loop and wins by the same plain-overwrite, same-filename mechanism - no separate TIMPS_INSTALL_PREVIEW hook, no separate gate (TIMPS_INSTALL_WEBUI_CGIS was already gated identically: WebUI present + TIMPS_CONTROL enabled, the same condition the removed hook used, since preview.html pulls /x/timps-token.cgi which only that hook installs). TIMPS_DEPENDENCIES += thingino-webui and TIMPS_INSTALL_WEBUI_CGIS's move to TIMPS_POST_INSTALL_TARGET_HOOKS (both from the previous commit in this branch's history) still stand and are what make the overwrite land before thingino-webui's plugin-assembly finalize hook runs - that ordering fix is unrelated to the provides-vs-plain-overwrite question and is still needed either way. Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com * timps: drop USE_TRACE/TIMPS_TRACE debug flag from this PR Unrelated scope: a debug-build make-variable override for src/trace.c's opt-in latency instrumentation, deliberately not a Kconfig option. Flagged in upstream review as not belonging in a preview-page/install-order PR - correct, it has nothing to do with either. Dropping it here; it belongs in its own small, separate change. Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com --------- Co-authored-by: Claude Sonnet 5 noreply@anthropic.com Co-authored-by: Paul Philippov themactep@gmail.com - 3bbaa82 litokam c1: correct audio gpio active level
- d201ce9 Merge remote-tracking branch 'origin/ciao' into ciao
- 482ed3a prudynt-t: bump to 6afc440 (RTSP audio-only fix) Pic...
master-2026-08-13
Changes in this release:
- 69fd433 soc/ingenic: state a family's shared values once (#1451) The family files enumerated one ifeq block per model, so a value the whole family shares got repeated once per model. t33 named isvp_t33_sfcnor eight times; a1 and t21 named theirs five times each; t10 repeated its RAM size three times. State what the models share once, and express what differs as an exhaustive if/else: # what's common SOC_ARCH := xburst1 SOC_FAMILY := t33 SOC_UBOOT_NOR := isvp_t33_sfcnor # what's different ifneq (
$(filter $ (SOC_MODEL),t33n t33vn t33zn),) SOC_RAM_MB := 128 else SOC_RAM_MB := 64 endif No variable is assigned a value that a later line replaces. A default with per-model overrides would read shorter still, but it means every model briefly holds a value that is wrong for it, and a model added to the filter and nowhere else would inherit that default rather than being noticed. Which value is common differs by family. t10 shares a RAM size and splits on the bootloader; a1 and t21 share a bootloader and split on RAM; t20, t40 and t41 vary in both, so their branches carry both lines. t41 gains least -- its six parts take six different NAND defconfigs -- but a per-model ladder still reads shorter than six ifeq blocks. Changed: a1, t10, t20, t21, t33, t40, t41 -- 153 lines out, 63 in. Left alone: c100 has one model. t23, t30, t31 and t32 have a distinct bootloader per model with no majority to hoist, so this would save a line or two while making a model's values harder to find. t31's eight models carry five NOR defconfigs and six NAND ones -- that table is earning its length. No functional change, verified two ways: 1. Evaluated both versions for all 35 models the seven filters claim and diffed every variable they set (SOC_FAMILY, SOC_ARCH, SOC_RAM_MB, SOC_UBOOT_NOR, SOC_UBOOT_NAND, SOC_UBOOT_BIN). Identical. 2. Checked that no file assigns a variable at both the common level and inside a branch. Worth doing properly because 27 of the 54 models have no camera config -- including all eight t33 parts -- so no build would have caught a wrong value. Co-authored-by: John Chia john@johnchia.com Co-authored-by: Paul Philippov themactep@gmail.com - 97f207c raptor family: bump to current heads raptor 712d513: set-fps now reaches the SDP of the next client (rvd republishes the ring header, rsd refreshes its rate cache), and audio clock resync bursts are summarised per episode instead of warning once per threshold crossing, so a sustained loss no longer evicts the syslog ring. Both contributed by johnchia. raptor-hal ec778b3: hal_gpio_set configures the direction on pins it exported itself (fresh sysfs exports are inputs, value writes were failing EPERM on images where init scripts configure nothing). Also johnchia. raptor-ipc and raptor-common move for the new diff-scoped clang-format CI only; no code change. compy stays at c12c594, which the raptor head still requires for the SR clock reference API. Combination build-verified for T41 from these exact heads.
- f0851c3 raptor, compy: bump to current heads together rsd now anchors audio RTCP sender reports on compy's new media-clock reference API, so raptor c59041c does not build against the old compy. compy c12c594: sender reports project NTP and RTP from one sampled instant and applications supply the (rtp timestamp, monotonic instant) reference defining the media clock (RFC 3550 6.4.1). raptor c59041c: the audio timeline campaign from the T23 field report (rtcp_sr blips every 5s). AAC frames stamped on the sample grid instead of the 20ms chunk grid (the weave was baked into recordings), rad's synthetic clock and rsd's wire steering both slewed proportionally instead of deadband stepping, an audio SDP header use-after-free fixed, and sender reports anchored on capture time. Measured on T31: steady sender-report mapping wobble fell from 16..46ms per 5s to under 4ms on every codec; 48k HE-AAC on T41 reads 0.6ms. rtcp_sr can stay enabled everywhere.
- b2d225d prudynt-t: fix dead version pin, bump to 6afc440 d5336b3d no longer resolves in themactep/prudynt-t (422 No commit found). Bump to the current stable head, which also carries the RTSP audio-only session fix from themactep/prudynt-t#30. Signed-off-by: Paul Philippov paul@themactep.com
- 32d442e raptor, raptor-hal: bump to current heads raptor dd05912104451e4bebbbf239e636905c8537980a: the T41 refmode keyframe drop fix (silent publish_ref rejection starved every new RTSP client once the encoder used a third buffer), rmr segment rotation aligned to the wall boundary (the pre-boundary IDR request landed a full GOP late on long-GOP HEVC), the day/night campaign for Gen1 sensors (IR-off ambient probe, EV dip, photo trigger dark boot in seconds, forced modes always drive hardware), the rsd send queue extracted and unit-tested, and a ric audit pass (config file clamped like the ctrl API, SIGFPE on poll_interval_ms=0 fixed, ctrl surface validates and rejects unknown commands). raptor-hal d473d8a85f026a0c493fdcee02b7952730cc6d8f: real AE histogram luma and exposure-time fallback on Gen1 SoCs, the foundation for the day/night work.
- 857eea6 configs: fix leakage
- 3e538ec open-isp: integrate the complete open media stack (#1368) * open-isp: integrate the complete open media stack Extend open-tx-isp to its current T23, T31, T40, and T41 targets, with OpenIMP on its supported T31 and T40 platforms. Pin open-tx-isp after its native canonical-module and T40 SDK sensor-registry integration. Add an opt-in aggregate profile that selects the neo system and audio libraries, while making the proprietary providers mutually exclusive. Order the replacement libraries before streamer consumers and preserve them during target finalization. Document the current support matrix and limitations. Camera profiles remain unchanged; local fragments can opt individual builds into the complete open stack. Signed-off-by: Matt Davis matteius@gmail.com * PR feedback * open-isp: add provider choice and update open stack Signed-off-by: Matt Davis matteius@gmail.com * raptor: gate V4L2 OpenIMP backend with provider Signed-off-by: Matt Davis matteius@gmail.com * open-isp: advance source pins for mainline T31 fixes Signed-off-by: Matt Davis matteius@gmail.com * openimp: make symbol coverage locale-stable Signed-off-by: Matt Davis matteius@gmail.com --------- Signed-off-by: Matt Davis matteius@gmail.com
- 19ac212 raptor: let daynightd replace RIC as the day/night engine Invert the exclusion from 5c29bf3: daynightd is selectable on any image again, and selecting it disables RIC instead (both would drive the same IR-CUT and LED pins and ship the same wrapper scripts). The raptor wrappers install only with RIC, so daynightd images get its scripts; json-imp.cgi prefers daynightd when present, so the web UI drives whichever engine the image ships.
- 5c29bf3 daynightd: exclude on raptor images Raptor's ric owns day/night and the same wrapper script names, so daynightd on a raptor image means two daemons driving the same GPIO pins plus a rootfs file collision. Prudynt still selects daynightd; the streamer choice already keeps raptor out of those configs.
- 579c94e raptor: daynight, ircut and light wrappers for the web UI On raptor images the daynightd package is absent, so the web UI's day/night, ircut and light calls went nowhere. These wrappers keep the daynightd era CLI and route it through raptorctl: ric owns the filter, the IR LEDs and the ISP mode, so read/toggle answer from live ric state instead of a run file, auto is a real verb, and ir850/ir940 switching stays coherent with automatic day/night. White light keeps the stock gpio path with active_low handling. json-imp.cgi branches per streamer: raptor paths skip the daynightd config keys and reload, prudynt paths are unchanged. Validated on z55 T31: full verb matrix, filter+LED+ISP coherent on mode changes, gpio readback confirms LED level, camera left in auto. Supersedes the approach in PR #1454.
- fcc0521 thingino-pkg: use curl instead of wget wget is not present in the firmware image. curl is provided by thingino-libcurl, so add it as a dependency and switch the download command. Co-authored-by: Matias De lellis matiasdelellis@users.noreply.github.com
- 90214d0 webui: report a failed termbin upload instead of an empty redirect On failure url is empty, and unquoted it left redirect_to with no arguments at all, so the response was a 303 carrying an empty Location: a broken redirect and no explanation. The path was barely reachable while the old bin accepted anything; the bin refuses payloads, oversized bodies and an exhausted daily allowance, so it is reachable now. Uses the flash message every other failure in this file already uses.
- 2c43257 send2termbin: post to the diagnostics bin over HTTPS The bin is a Cloudflare Worker now, not fiche on a raw TCP port, so netcat cannot reach it. stdout stays one line so url=$(send2termbin) keeps working for thingino-diag -u, -j and the web UI. Also stops the empty-file branch printing stray echo args and leaking its temp file. thingino-diag and the web UI both said uploads are kept for a week and named the old host. The bin keeps diagnostic reports for three days, and the hostname now lives only in send2termbin.
- f5113c8 scripts/tts: add standardized Kokoro TTS pipeline Add text-to-speech audio generation using Kokoro-82M neural TTS model with pinned voice configuration for repeatable output across sessions. - setup.sh: one-time bootstrap (downloads model + voices, creates venv) - generate.py: main engine (text -> espeak-ng phonemes -> Kokoro -> WAV) - config.yaml: locked voice (af_heart), speed, format settings - run.sh / batch.sh: convenience wrappers (single phrase or batch) - kokoro/: spacy-free model modules (avoids Python 3.14 incompatibility) - README.md: full documentation Model weights and voices are downloaded by setup.sh and gitignor...
firmware-2026-08-12
Changes in this release:
- 6668fe6 uboot: fix flashing autoupdate-full.bin from a card
- 5ce4522 sysupgrade: fix segfault when flashing data partition after rootfs in full upgrade The full upgrade loop flashes partitions sequentially with dd. After rootfs (mtd4) is overwritten, the on-disk dd binary is corrupted, causing a segfault when the loop reaches the data partition (mtd5). Create tmpfs symlinks for dd and flash_eraseall after cloning busybox to tmpfs, and prepend the workdir to PATH so the loop uses tmpfs binaries that survive the rootfs being overwritten. Also add dd to the global bbapplets list for the stage2 exec path. Signed-off-by: Paul Philippov paul@themactep.com
- cc178f6 AGENTS: add strict rule against inventing git hashes Never type hashes by hand. Always obtain the full hash from the actual git repo, verify it with git cat-file -t, and use update_packages.py for package version changes. Includes the recovery procedure for when a bogus hash is already committed. Signed-off-by: Paul Philippov paul@themactep.com
- de7b305 prudynt-t: update package hash to 73ae2b8 (DMA fallback fix) Signed-off-by: Paul Philippov paul@themactep.com
- 6f88c84 prudynt-t: fix mangled package hash The previous hash 84edac095beb10c4ae0982ed98c1b85b40cd3eae was a typo of 84edac016f21f3419591407eccababeeb7812861. The mangled hash was never a real commit and can't be resolved by update_packages.py. Signed-off-by: Paul Philippov paul@themactep.com
- b74ec29 package/buildscope: update to 6ce53f6 Update buildscope from 902e0af to 6ce53f6 Hash change: 902e0af3ad90b208d49b1c74f5c1f9cb938b68da -> 6ce53f6a4a687ae0ae228b9e5691b449a9a2d66f Changelog: 6ce53f6: Point the fleet proxy at the thingino Cloudflare account
- 21ab390 timps: install the board day/night hardware scripts (daynight/ircut/light) timps runs its own day/night detection and drives the hardware by exec'ing a configurable switch_cmd (default "daynight"). On a timps image that command did not exist: /usr/sbin/{daynight,ircut,light} and S06ircut are installed only by thingino-daynightd, which is selected by exactly one Kconfig symbol - BR2_PACKAGE_THINGINO_STREAMER_PRUDYNT. A camera built with the timps streamer therefore never got any of them. Live incident (Garage, T31/SC4336P): detection worked correctly ("[DAYNIGHT] switching to night (total_gain 3557)") but every switch_cmd failed with rc=127, so the IR-cut filter was never removed and the IR illuminator never lit. The ISP kept ramping total_gain (3500 -> 22000+) trying to expose a scene it could not see through the IR-cut filter, and the image went purple/IR-tinted. Installing only 'daynight' would not have been enough: it guards every hardware step with command_present, so without ircut/light it would have called 'color' alone - an ISP-only flip, i.e. the same purple image, just silently. ircut/light are installed unconditionally because timps's own WebUI bridge (json-imp.cgi) shells out to them for the control-bar IR-cut and IR-LED buttons regardless of who does the detection. Installed straight from thingino-daynightd's PKGDIR (same pattern TIMPS_INSTALL_SEND2 already uses for prudynt-t's send2* tools) so there is a single source of truth and no copy to drift. Also fix TIMPS_DISABLE_DAYNIGHTD, which still removed S97daynightd after thingino-daynightd 2.0.0 renamed it to S10daynightd - it had been a no-op, leaving the daemon free to autostart and double-switch against timps. Match by glob, and cover S07dusk2dawn for the same reason. S06ircut is deliberately kept: it is a one-shot boot-time IR-cut latch, not a daemon. Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
- aa82ae0 raptor, raptor-hal: bump to current heads raptor dd05912104451e4bebbbf239e636905c8537980a: the T41 refmode keyframe drop fix (silent publish_ref rejection starved every new RTSP client once the encoder used a third buffer), rmr segment rotation aligned to the wall boundary (the pre-boundary IDR request landed a full GOP late on long-GOP HEVC), the day/night campaign for Gen1 sensors (IR-off ambient probe, EV dip, photo trigger dark boot in seconds, forced modes always drive hardware), the rsd send queue extracted and unit-tested, and a ric audit pass (config file clamped like the ctrl API, SIGFPE on poll_interval_ms=0 fixed, ctrl surface validates and rejects unknown commands). raptor-hal d473d8a85f026a0c493fdcee02b7952730cc6d8f: real AE histogram luma and exposure-time fallback on Gen1 SoCs, the foundation for the day/night work.
- c853870 configs: fix leakage
- d5b5261 open-isp: integrate the complete open media stack (#1368) * open-isp: integrate the complete open media stack Extend open-tx-isp to its current T23, T31, T40, and T41 targets, with OpenIMP on its supported T31 and T40 platforms. Pin open-tx-isp after its native canonical-module and T40 SDK sensor-registry integration. Add an opt-in aggregate profile that selects the neo system and audio libraries, while making the proprietary providers mutually exclusive. Order the replacement libraries before streamer consumers and preserve them during target finalization. Document the current support matrix and limitations. Camera profiles remain unchanged; local fragments can opt individual builds into the complete open stack. Signed-off-by: Matt Davis matteius@gmail.com * PR feedback * open-isp: add provider choice and update open stack Signed-off-by: Matt Davis matteius@gmail.com * raptor: gate V4L2 OpenIMP backend with provider Signed-off-by: Matt Davis matteius@gmail.com * open-isp: advance source pins for mainline T31 fixes Signed-off-by: Matt Davis matteius@gmail.com * openimp: make symbol coverage locale-stable Signed-off-by: Matt Davis matteius@gmail.com --------- Signed-off-by: Matt Davis matteius@gmail.com
- f36b26c webui: remove extras storage from system usage page The extras partition no longer exists. Remove it from the UI (progress bar, legend, summary line), the JS rendering logic, the dead CSS class, and the CGI so it stops reading /opt. Also add shellcheck suppressions for pre-existing warnings: SC1091 (auth.sh not available at lint time), SC2329 (unused json_error kept for API completeness), and SC2086 (intentional word splitting for df output parsing). Signed-off-by: Paul Philippov paul@themactep.com
- 7a7229b isp-inspector: show EV as log2 stops instead of raw register value The EV stat card and chart previously displayed ev.value, a raw ISP register integer (e.g. 524288) that users could not interpret. - EV stat card now shows ev.log2 (photographic EV in stops, e.g. 12.3 EV) - EV chart plots dual y-axes: EV in log2 stops (left) + exposure time in microseconds (right, dashed) - statCard() now accepts a 5th tooltip arg, rendering a ? help icon with a native browser title tooltip on hover - All 11 stat card tooltips rewritten with plain-language explanations of what each parameter is, what affects it, and what abnormal values mean - Chart card titles also have hover tooltips - LLM prompt sends ev.log2 for more useful AI analysis Signed-off-by: Paul Philippov paul@themactep.com
- 0fed06a AGENTS.md: document that cameras use BusyBox sh, not bash Signed-off-by: Paul Philippov paul@themactep.com
- c3de103 package/prudynt-t: move prudynt-specific webui files from thingino-webui Move all prudynt-streamer-specific CGIs, streamer config pages, audio settings page, and supporting JavaScript from thingino-webui into the prudynt-t package, wired through the WebUI plugin manifest system. Files moved (16 CGIs, 6 HTML, 3 JS): - CGIs: json-prudynt*, restart-prudynt, json-imaging, json-osd-sei, ch0/ch1/dl0/dl1 snapshots, mjpeg streams, events, preview - HTML: streamer-{main,substream,image,osd,sensor}, config-audio - JS: streamer-config, audio, sei-osd Added prudynt.webui.json manifest that populates the ddStreamer dropdown, adds Audio to Settings, and declares all pages/CGIs. navigation.js: emptied hardcoded ddStreamer items, removed Audio from Settings, removed attachPrudyntHandlers — all now driven by the plugin manifest at build time via assemble_plugins.py. json-imp.cgi kept in thingino-webui (shared day/night control with raptor fallback). Signed-off-by: Paul Philippov paul@themactep.com
- 09c2d0c isp-inspector: add T10/T20 field name fallbacks in CGI parsers The T20 isp_info proc file uses different field names than T31+: - No SENSOR Max Integration Time field - EV: ISP total gain / ISP exposure log2 id (not ISP EV value / log2) - WB: ISP WB rg / ISP WB bg / ISP WB Temperature (not ISP WB weighted rgain / bgain / color temperature) Add fallback lookups so EV and WB cards show data on T20 cameras. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: hide max integration time on T20 when absent T20 isp_info has no SENSOR Max Integration Time field. Show just '1405 lines' instead of '1405 / 0 lines' when the max value is missing or zero. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: use soc -f for accurate platform detection T20 was showing as T10 because both use isp_info proc file. Use 'soc -f' command (already present on all Thingino cameras) to report the actual SoC model: t20, t31, t40, etc. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: show Antiflicker as '60 Hz' not 'AF:60' Map raw T20 antiflicker frequencies (50, 60) to human-readable '50 Hz' / '60 Hz' instead of the cryptic 'AF:' prefix. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: restore Antiflicker label in header bar Show 'Antiflicker: 60 Hz' instead of bare '60 Hz'. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: move Day/Night mode badge to header bar Mode is now a compact badge next to resolution instead of a full stat card. Shows 'Night', 'Day', 'Day +Custom', etc. Signed-off-by: Paul Philippov paul@themactep.com isp-inspector: drop badge class from header mode span Plain text-muted, matching t...
firmware-2026-08-10
Changes in this release:
- 01110e3 cameras: move Cinnado B6 to experimental (missing libs)
- e033522 webui: add speaker config and playonspeaker toggle to Send to Services page Add Speaker configuration card to the Send to Services page with fields for file path, volume, gain, and loop count. Add 'Play audio on speaker when motion detected' toggle to the Motion Detection card. Wire both through json-send2.cgi (GET/POST) and send.cgi (test button). Signed-off-by: WLTB-Gino WLTB-Gino@users.noreply.github.com
- 963cb2f prudynt-t: add missing playonspeaker script The motion script calls 'playonspeaker &' when motion.playonspeaker is enabled, but no such script was ever installed. This left the speaker notification feature completely non-functional. Add a playonspeaker script that reads speaker config (file, volume, gain, loop) from /etc/send2.json and invokes the existing 'play' command, matching the pattern of the other send2* scripts. Signed-off-by: WLTB-Gino gino@wltechblog.com
- 74ab6e0 cameras: graduate Sannce I21AG to supported
- e5628af thingino.mk: derive UBOOT_BOARDNAME from defconfig-provided BR2_TARGET_UBOOT_BOARDNAME When a camera defconfig provides BR2_TARGET_UBOOT_BOARDNAME directly (e.g. eufy_t8400x_t31x_sc3235_syn4343), the ifeq block was skipped, leaving UBOOT_BOARDNAME empty. force-config then wrote an empty board name into .config, overriding the defconfig value and causing u-boot to fail with "No U-Boot board name set". Fix by adding an else branch that strips quotes from the defconfig- supplied value to populate UBOOT_BOARDNAME. Signed-off-by: Paul Philippov paul@themactep.com
master-2026-08-08
Changes in this release:
- 08dc225 thingino-uboot: park IR-cut filter coils at boot Add gpio.ircut (and gpio.ircut_sub) to the boot-window GPIO presets: the filter solenoid sits behind an H-bridge whose inputs float from power-on until the runtime takes over, which can leave a coil partially energised and heating. Park every ircut pin at the /usr/sbin/ircut idle level - dual-pin boards rest both pins at idle between the 10ms pulses and single-pin boards de-energise at the open level, so both reduce to active_low ? HIGH : LOW per pin. The parser mirrors /usr/sbin/ircut exactly: scalar pins, token sequences, {pin, active_low} objects, lists, per-token o/O suffixes (which mean pin POLARITY here - "57o" = active-low = idle HIGH - unlike the drive-level suffixes of gpio.wlan/mmc_power), the 999 tmi8152 kernel-shim sentinel (no gpio), and -1 disabling the whole domain. Swept all 222 build units: strictly additive - every previously emitted node is preserved and only ircut hogs are added (378 pins: 370 low, 8 high on the tapo c500/tc70 suffixed and tapo c100/c110 object boards). No ircut pin collides with an MMC/button DT binding or sits in any U-Boot pinctrl group. Build-verified on personal_campan: ircut_52/ircut_53 output-low in u-boot.dtb next to the 8 motor-park hogs, none in SPL.
- 96d1311 package/ingenic-lib: install libsysutils only when selected No libimp variant in any SoC/SDK/libc combination links or dlopens libsysutils.so, and nothing in the tree links -lsysutils. The default y kept it shipping in every non-a1 image (5.6 KiB flash) since the per-lib split. Default it off and gate the staging install on the same option.
- f7755ef thingino-uboot: never hog a pin owned by an MMC/button DT binding A gpio-hog claims its pin at DM init, so a pin that inject-uboot-mmc-dt.sh also turns into a DT binding (gpio.mmc_cd -> cd-gpios, single-object gpio.mmc_power -> vmmc regulator, gpio.button_reset -> gpio-keys) would make the binding's own gpio request fail and break that subsystem. cinnado_b6 hits this today: its config lists pin 61 as both mmc_cd and a motor phase (config bug, reported to the author), and since the motor coil-park commit the hog has been stealing card-detect from the mmc core in U-Boot. Skip such pins with a build-log note instead - the binding wins, and once the config is fixed the guard is a no-op. Also collapse the same pin appearing in several hog domains to its first occurrence. Re-proven over all 222 build units: cinnado_b6 dropping motor_park_61 is the only output change.
- 738f749 configs: normalize legacy mmc_power notation in cameras-exp Same conversion as the main cameras tree: 8 bare-int mmc_power entries become {pin, active_low: false} objects (bare token = drive high in S09mmc). Proven by replaying get_mmc_power_sequence with host jct over old and new configs: 8/8 identical drive sequences. These boards build through the same U-Boot inject hooks, and the bare-int shape never reached the vmmc-supply injection.
- e32d932 thingino-uboot: unify boot-window GPIO presets in one inject script Replace inject-uboot-motor-dt.sh and inject-uboot-wlan-dt.sh with inject-uboot-gpio-dt.sh, one gpio-hog injector for everything whose job is "drive pin X to level Y and hold it through boot": - motors.gpio_pan/gpio_tilt parked at the kernel driver's de-energised level (gpio_invert aware), as before - gpio.wlan at the final resting level of the S36wireless sequence, as before - NEW: gpio.mmc_power list form - boards whose SD slot needs more than one supply/enable pin get each pin hogged at its power-on level (active_low aware). The single-pin object form intentionally stays in inject-uboot-mmc-dt.sh as a vmmc-supply regulator: the mmc core sequences slot power itself there, which a static hog cannot, but a fixed regulator can only own one gpio, so multi-pin boards get hogs. The two per-domain mk hooks and their config gates collapse into one ungated hook (still skipping the 2013.07 vendor U-Boot, which has its own env-driven gpio_default path). Safe: an audit of all 169 camera configs found zero cameras where a domain emits hogs without its old gate symbol set (BR2_THINGINO_MOTORS / BR2_PACKAGE_WIFI), so gating purely from json content changes no board's output. The script also dedups repeated pins; 9 cameras list identical gpio_pan and gpio_tilt, which previously emitted duplicate same-named nodes that dtc merged - the compiled dtb is identical either way. Proven by regenerating every camera's injection with the old scripts and the new one: 169/169 node-identical after dedup, the only additions being the mmc_power hogs on the 5 multi-pin boards (hl_jdpan01, tapo c100 t23n, wyze_campan2, wyze_vdb2, xiaomi mjsxj05hl). Build-verified on personal_campan (dict mmc_power: vmmc regulator + 8 motor hogs, unchanged) and wyze_campan2 (8 motor + wlan_58 + mmc_power_47/54 hogs in u-boot.dtb, none in SPL).
- 876c3bb configs: normalize legacy gpio token notation to active_low objects The o/O drive-level suffix tokens ("mmc_power": "47o 54o", bare-int "mmc_power": 17) are vendor gpio_default notation; the proper thingino convention is the {pin, active_low} object like the other 31 mmc_power entries already use. Convert: - 17 bare-int entries -> {pin, active_low: false} (bare token = drive high in S09mmc parse_legacy_token) - 5 token strings -> arrays of {pin, active_low} objects (o = drive low = active_low true, O = drive high = active_low false), a shape S09mmc's indexed gpio.mmc_power.N walk already parses natively - ajcloud_cp8040 "wlan": "47O 47o" (high-then-low pulse) -> {pin: 47, active_low: true, toggle: true}, matching its cp2011/cp8010 siblings (S36wireless emits the identical pre-pulse sequence for both forms) Proven equivalent by replaying the real consumers over old and new configs: get_mmc_power_sequence (S09mmc) and get_wlan_sequence (S36wireless) run with host jct produce byte-identical drive sequences for all 23 touched cameras.
- 926072e Generate release artifacts on the MMC boot path The MMC0_BOOT branch of pack: only printed dd instructions and never ran generate_release_artifacts.sh, so no .bin.sha256sum was written. The NAND and NOR branches both call it. firmware-master sets FULL_FW_SHA=${FULL_FW}.sha256sum unconditionally and passes it to gh release upload, which failed the wanjiaan_hdc51 mmc job with "no matches found for ...bin.sha256sum". Previously masked by the earlier parted failure, which killed the job before the release step.
- 869277b thingino-uboot: preset Wi-Fi module GPIO at boot via gpio-hog Some Wi-Fi modules need their power/enable line at a defined level before Linux is up: SDIO parts must be powered so the kernel MMC scan can enumerate them, and S36wireless drives gpio.wlan only on 3.10 kernels, late in boot. Until then the pin sits at the SoC reset default. Add inject-uboot-wlan-dt.sh (sibling of inject-uboot-motor-dt.sh): it reads gpio.wlan from the board's thingino.json in every shape S36wireless.in accepts - bare pin, suffixed token (47o/47O/47t), token sequence, {pin, active_low, toggle, action, state} object, or a list of those - and appends a gpio-hog per pin to this board's U-Boot leaf .dts at the final resting level of the runtime sequence (active_low aware, explicit state wins). A pin whose last action is a toggle depends on prior state and cannot be a static hog, so it is skipped; an object's toggle flag only prepends a pulse and does not change the resting level. The hook is gated on BR2_PACKAGE_WIFI, skips the 2013.07 vendor U-Boot (env gpio_default covers it there), and enables CONFIG_GPIO_HOG so U-Boot acts on the hogs. Hogs land in U-Boot proper only, not SPL. Swept over all camera configs: 121 of 122 gpio.wlan entries emit a hog (90 high / 31 low), the -1 entry emits nothing, and no wlan pin overlaps mmc_cd/mmc_power on any board. Build-verified on personal_campan (no gpio.wlan: clean no-op, motor hogs intact) and wyze_campan2 (wlan 58 -> output-high in u-boot.dtb alongside the 8 motor-park hogs, none in SPL).
- 55d4d2d Record thingino.json in the build report Nothing in .config carries what is in it. On a pan camera not one of the twelve GPIO values in thingino.json appears anywhere in the expanded config, and the Kconfig options that look like they should hold them are empty strings, so the build report suggested no pins were assigned when the device had them. buildscope v0.1.9 adds --capture for this. Attempted rather than assumed: the copy on PATH may predate the flag, and an unknown argument would cost the whole report rather than just the capture, so a failure falls back to the plain scan.
- 684421d raptor: do not default RWC on for DWC2_OTG cameras DWC2_OTG only describes the USB controller mode, it does not make the device a webcam.
- fa0f81a Pin buildscope v0.1.8 Reads the device tree inside a compressed bootloader, so a board tree with its GPIO configuration is reported instead of only the loader tree.
- 6d28521 package/thingino-sensor-info: bump to 625667a Size-optimized build: packed table, 32-bit kHz clock math, LTO, non-PIE, -mno-abicalls. All features intact.
- 77a2ff5 package/thingino-sensor-info: -mno-abicalls -mplt
- e0e665f package/thingino-sensor-info: enable lto
- a3e7d7c package/thingino-sensor-info: build non-PIE 5% smaller compressed; ASLR protects nothing in a root-run offline diagnostic.
- 97391fa package/thingino-sensor-info: pass the size flags buildroot omits The package overrides CFLAGS/LDFLAGS on the make command line, so the repo Makefile's section-GC flags never reached firmware builds. TARGET_LDFLAGS already carries max-page-size; this adds -ffunction-sections/-fdata-sections, --gc-sections, and the unwind/ident/constant-merge trims.
- bbd8a54 thingino-raptor: bump pins for backchannel and refmode ring fixes rsd 707376dc8ae6d25e8067b205c01a2cfa01b3bf7b: backchannel created a consumer handle for the speaker ring whenever one already existed -- rac playing a file, or a s...
master-2026-08-07
firmware-master: publish to its own master-YYYY-MM-DD release, never …
firmware-2026-08-02
Changes in this release:
- c334a03 ingenic-sdk: move gpio-userkeys config generation to finalize hook GENERATE_GPIO_USERKEYS_CONFIG reads gpio.button_reset from /etc/thingino.json, but the camera-specific GPIO settings are only merged during target-finalize (by thingino-core). Running it during INSTALL_TARGET_CMDS means button_reset is never present, so the gpio-userkeys module config is silently skipped. Move the call to INGENIC_SDK_TARGET_FINALIZE_HOOKS so it runs after thingino.json is fully assembled. Signed-off-by: Paul Philippov paul@themactep.com
- 9657a04 wyze-accessory: fix echo >> absorbing next command when make += joins define blocks When multiple accessory variants are enabled (e.g. SPOTLIGHT + CAR), GNU make's += operator joins the last line of one define block with the first line of the next without a newline. This caused: echo ch341 >> /etc/modules.d/accessory -D -m 0755 ... The install command became arguments to echo, corrupting the modules.d file and preventing car_control from being installed. Fix by adding a blank line at the end of each conditional define block so the shell commands are properly separated regardless of += behavior. Signed-off-by: Paul Philippov paul@themactep.com
- a25e7b7 sysupgrade: compute total flash size by summing all MTD partitions full_upgrade_partition_size() previously relied on an "all" partition in /proc/mtd, which does not exist on all cameras. When absent, the function returned 0, causing the free-space check to fail with: Firmware is larger than flash chip: 16777216 > 0 Sum all individual MTD partitions (skipping the header line and the "all" partition if present) so the check works regardless of whether the kernel exposes a concatenated "all" device. Signed-off-by: Paul Philippov paul@themactep.com
- b6b1bef pre-commit: fix pipe subshell swallowing shfmt errors, fix bashism in json-imp.cgi Replace echo|while pipes with heredoc-based loops so set -e catches shfmt/prettier/sort failures inside the loop body. Replace bash-specific ${1:0:1} slice in json-imp.cgi with a POSIX case pattern, fixing shfmt parsing error on merge.
- 1a51809 libhelix-mp3, libflac: fail the build too; drop the .mk comment Extends the previous commit's fix to the two remaining packages built the same way, and removes its explanatory comment from libhelix-aac.mk, whose reasoning is already in that commit's notes. All three packages share one BUILD_CMDS shape, and they are the only three in the tree that do: a
$(foreach ...) whose commands are joined by ";", followed by a link of "find ... | xargs $ (TARGET_CC) -shared". Without "set -e" a source that fails to compile does not stop the loop, and a shared link permits undefined symbols, so the package builds green and installs a library missing whatever did not compile. libhelix-mp3 carries the identical gate that libhelix-aac tripped -- assembly.h:353, included by 8 of its 15 sources -- and would fail the same way on the same target; it was not hit there only because that build does not select it. libflac's own "#error Unsupported platform" is a narrower ppc-hwcaps path (cpu.c:257) rather than the same trigger, but its BUILD_CMDS has the same shape and the same silent partial-link outcome for any source that fails. Co-Authored-By: Claude Opus 5 noreply@anthropic.com - 3aa830e Revert "sysupgrade: add status=progress to dd for per-partition transfer progress" The camera's busybox does not support status=progress, causing dd to fail with "invalid argument 'progress' to 'status'". This reverts commit 3134bf2341820deeb549eab88777b01c4dbb3f78. Signed-off-by: Paul Philippov paul@themactep.com
- 3134bf2 sysupgrade: add status=progress to dd for per-partition transfer progress Busybox is built with CONFIG_FEATURE_DD_STATUS=y, so status=progress shows real-time throughput during each partition write. Signed-off-by: Paul Philippov paul@themactep.com
- 1fa169d sysupgrade: let dd print transfer stats during full upgrade Remove 2>/dev/null so dd reports records in/out, giving visibility into write progress for each partition. Signed-off-by: Paul Philippov paul@themactep.com
- 7e75ea4 sysupgrade: flash partitions directly from firmware image without temp files Previously the full upgrade path extracted each partition to a temp file in /tmp and then called flashcp on it. On memory-constrained cameras the combined size of the firmware image plus the extracted partition file exhausted tmpfs, producing a truncated file that caused flashcp to segfault. Drop the intermediate file entirely: flash_eraseall each mtd partition, then dd directly from the firmware image at the correct offset. No extra space is needed beyond the firmware image itself. Signed-off-by: Paul Philippov paul@themactep.com
- d62fe3d sysupgrade: verify extracted partition size before flashing If the firmware binary is shorter than the sum of all MTD partitions, dd produces a truncated file and flashcp may segfault on it. Check the extracted size matches the partition size and die with a clear message before handing bad input to flashcp. Signed-off-by: Paul Philippov paul@themactep.com
- 36bbfe1 sysupgrade: fix subshell pipe so flash failures actually stop the script The
tail ... | while readloop ran in a subshell, sodie(which callsexit) only killed the subshell — the main script continued to print "Full upgrade complete" and attempt reboot after a failed flash. Replace the pipe with a temp file + input redirection so the loop runs in the main shell and die() properly aborts. Signed-off-by: Paul Philippov paul@themactep.com - a532db9 sysupgrade: use hardware watchdog reset before reboot -f on full upgrade The full upgrade path did a plain
reboot -fafter flashing, which can fail with EIO because the rootfs has been overwritten and the kernel may have stale page cache entries for the reboot binary. Add the same pre-reboot sequence already used in stage2's go_reboot(): sync, sleep 5, trigger the Ingenic WDT reset via /proc/jz/reset/reset, then fall back to reboot -f. Signed-off-by: Paul Philippov paul@themactep.com - 3c26abc lightnvr: add tarball hash for v0.36.6 Signed-off-by: Paul Philippov paul@themactep.com
- bb234e1 jct: add tarball hash for v1.2.0
- c93c02f install packages system handler by default
- 61fde40 package/thingino-jct: update to v1.2.0 Update thingino-jct from v1.1.0 to v1.2.0 Hash change: v1.1.0 -> v1.2.0 (No changelog available)
- 2c6455c package/open-tx-isp: update to ad9db44 Update open-tx-isp from fddb684 to ad9db44 Hash change: fddb6843814385dad8b684dd922bc488cbcb70c2 -> ad9db44cb71b25460ee50e6bcbc5cfc27a5a0958 Changelog: 74a033c: share T41 exposure and scaler pipelines 33603c9: share T23 polyphase scaler generation 7486de9: share T31 flicker exposure and repair ISP tuning 42948f7: share T41 fixed-point division fef815c: share T23 fixed-point division 07c2a95: add tests 76d6f9c: share native 64-bit fixed-point multiplication bbba792: preserve accepted T31 AE code generation 13633bc: share T23 wrapped fixed-point multiplication c1c133d: share T23 and T41 fixed-point add subtract 2ebc0a5: share T23 and T41 64-bit add subtract 2a5c061: share generic T23 and T41 fixed point add subtract 86ea753: share exact signed fixed point rounding 4b2576c: restore T31 full-rate pre-dequeue and high-gain profile 4c7fd31: share full-width fixed point multiply on T41 43acaed: share full-width fixed point divide on T41 a2fb1c9: move T41 fixed point log2 into shared math 1c663ed: move T41 exp2 into shared math 4406c6c: share T41 Q7 tuning ratio without shifting text 54c035d: share frame channel wire ABI across active SoCs 1c3f2d0: share frame buffer state flag policies a80cba4: stabilize shared frame image format ABI a5eb611: t40: support SDK sensors in canonical module 67a4c72: Check pt 315faa9: complete shared frame channel contracts 994a604: share frame request wire contract aec02a9: share subdevice link ABI a3206d0: share recovered link detach operation b7ff3f2: share subdevice graph resolver f77e9a3: share subdevice graph wire ABI 87d6f44: share subdevice link state core 163cccf: share remote pad event resolver b50702b: share recovered subdevice state policy 7251cb0: share T40 subdevice core policies f85440d: fix T31 frame buffer ownership and timestamps ad9db44: document T31 DMA-done buffer rotation
- a32a595 package/lightnvr: update to 0.36.6 Update lightnvr from 0.36.5 to 0.36.6 Hash change: 0.36.5 -> 0.36.6 (No changelog available)
- c1791e4 fixed-size partitions, config backup/restore, selective upgrades Replace the sysupgrade re-exec/GitHub dance for boot, kernel, and rootfs OTA with a minimal flash-ota script that receives pre-assembled, partition-sized files and flashes them directly to the matching MTDs. Host-side (scripts/fw_ota.sh): - Pads partition files to exact MTD sizes (boot 256K, env 64K, rootfs 64K-aligned) - Uploads flash-ota.sh + individual partition files to /tmp/ - No more concatenation + camera-side extraction Camera-side (package/thingino-sysupgrade/files/flash-ota): - Resolves MTD names early, clones busybox to tmpfs for rootfs mode, remounts / ro before erasing rootfs - Auto-detects flashcp -A support to avoid double-erase - Stops streamer, flashes, reboots — 85 lines total Makefile targets now pass partition files directly: - ota-kernel: (uImage) - ota-uboot: (+ u-boot-env.bin from images dir) - ota-rootfs: (+ data.jffs2 from images dir) - ota-full: unchanged (uses sysupgrade with full firmware) sysupgrade bug fixes (no longer used for partial OTAs): - Replace fragile '! echo | grep -qE' with case patterns (busybox compat) - Clear GITHUB_URL immediately after getopts when a local file is present - Skip file-move when fw_file already exists in workdir Signed-off-by: Paul Philippov paul@themactep.com sysupgrade: use flash_partition helper to avoid double-erase Add fla...
firmware-2026-07-31
Changes in this release:
- ece1953 fix: imp-control missing API key breaks prudynt color/ISP commands imp-control communicates with prudynt via its HTTP API (/api/v1/config). Prudynt requires an X-API-Key header for /api/v1/config, read from /etc/thingino-api.key. imp-control was not sending this header, causing all ISP commands (ispmode, brightness, contrast, etc.) to fail silently with 401. - imp-control: read /etc/thingino-api.key and include X-API-Key header in all curl requests - S10daynightd: generate the API key file early (before starting daynightd), so it exists when daynightd first calls color on/off. Previously the key was only created at S48 (webui-config), leaving a window where prudynt's API was inaccessible to local tools. - S31prudynt: after prudynt starts and its HTTP API is ready, re-sync the ISP daynight mode from /run/thingino/daynight_mode. This fixes a boot race where daynightd (S10) tried to set the ISP mode before prudynt (S31) was listening. Signed-off-by: Paul paul@earendilworks.com
- 684c705 webui: gate WireGuard button on feature flag, reorder offcanvas nav - WireGuard VPN button now only appears when thinginoUIConfig.device.wireguard is set (via wireguard.webui.json plugin featureFlags) - toggleWireGuard() bails early if WireGuard feature flag is absent - Offcanvas nav: move Information block to bottom, just before Help Signed-off-by: Paul Philippov paul@themactep.com
- 9c4f57d webui: use port 8080 config API directly with X-API-Key auth Replace CGI middleware passthrough (/x/json-prudynt.cgi, /x/json-prudynt-save.cgi, /x/json-prudynt-config.cgi, /x/json-config-rtsp.cgi) with direct port 8080 API calls. - All config read/write now hits http://{camera}:8080/api/v1/config - API key loaded from /x/api-key.cgi and sent as X-API-Key header - apiFetch() helper awaits key promise before sending requests - Export config now uses dump_config action + Blob download - OSD save uses POST with action.save_config for persistence - SEI OSD check uses osd.sei.enabled path Signed-off-by: Paul Philippov paul@themactep.com
- b04c33f pack: correct where the size report is written It goes to the build root, beside uenv.txt, not into images/ -- which is what the CI glob that collects it already assumes.
- d4e7cff package/prudynt-t: update to 4e29b88 Update prudynt-t from 0f3fa5e to 4e29b88 Hash change: 0f3fa5edbcafd1513afce6f34430edea2a9cc18b -> 4e29b8858478e6a229fb75f946b4db5f6d034f0d Changelog: 740ff75: osd: replace burnin background bool with color, nest SEI under osd.sei 713302c: osd: auto-migrate old osd.enabled/elements to osd.sei on config load 62c64af: osd: rename sei.elements -> sei.entries 7e6ce62: osd: fix entries null-wipe on query ac650c5: api: add REST GET endpoints for config domains 80b6947: osd: fix burnin outline, background via alpha blending in putBlock 2a241b8: osd: skip burnin passes when color alpha is zero 4e29b88: api: move config GET endpoints before auth check
- 8f9d9d3 webui: fix autocomplete warning on HA config page Replace form-level autocomplete=off (ignored by Chrome) with autocomplete=current-password on the password field. Signed-off-by: Paul Philippov paul@themactep.com
- bcaba05 webui: drop redundant console.error in timelapse toggle The error is already shown to the user via showAlert; the console.error was just noise that made it look like the error wasn't being handled. Signed-off-by: Paul Philippov paul@themactep.com
- 1f5537a webui: replace preview.js null-query with parallel REST GETs loadConfig() now fetches image/motion/privacy/rtsp/stream0/stream1 in parallel from :8080/api/v1/config/* instead of sending a monolithic null-filled POST through the CGI. Signed-off-by: Paul Philippov paul@themactep.com
- 80202be webui: use REST GET for OSD config reads Replace null-filled POST queries with clean GET to :8080/api/v1/config/osd. Signed-off-by: Paul Philippov paul@themactep.com
- 109074f webui: osd.sei.elements -> osd.sei.entries Signed-off-by: Paul Philippov paul@themactep.com
- 995f2b7 webui: replace burnin background switch with color picker, nest SEI OSD under osd.sei - Replace burnin background checkbox with full color selector (swatch + picker + hex field + alpha slider), matching fill/outline UX - Change API field from osd.burnin.background (bool) to osd.burnin.background_color (hex string #RRGGBBAA, default #80) - Nest SEI OSD under osd.sei (enabled + elements) for consistency with osd.burnin - Update timps bridge docs: osd.enabled -> osd.sei.enabled Signed-off-by: Paul Philippov paul@themactep.com
- 1915392 thingino-ha: skip WiFi RSSI on Ethernet-only cameras, rename Live View to Preview - Add ha_has_wifi() helper to detect wireless interfaces - RSSI discovery and state publish now gated on ha_has_wifi - Rename 'Live View' camera entity to 'Preview' to avoid confusion with actual RTSP live streams Signed-off-by: Paul Philippov paul@themactep.com
- 88189b9 webui: install json-osd-sei.cgi with 0755 permissions Signed-off-by: Paul Philippov paul@themactep.com
- 6ead84a webui: add json-osd-sei.cgi SSE bridge, convert consumers to SSE - New /x/json-osd-sei.cgi: SSE bridge that polls prudynt :8080 and pushes events as text/event-stream, deduplicated by content - preview.html SEI overlay: single persistent SSE connection - sei-rotate.js: SSE, closes after first rotation received Signed-off-by: Paul Philippov paul@themactep.com
- 9d081b3 webui: restore :8080/api/v1/osd-sei — CGI endpoint does not exist Signed-off-by: Paul Philippov paul@themactep.com
- d45046b webui: revert SSE to fetch polling — /x/json-osd-sei.cgi returns text/html Signed-off-by: Paul Philippov paul@themactep.com
- dee5f12 preview: switch SEI overlay from fetch polling to SSE Signed-off-by: Paul Philippov paul@themactep.com
- 84063a0 sei-rotate: switch from poll to SSE, remove inline polling from streamer pages - sei-rotate.js: use EventSource (SSE) instead of fetch polling, close connection after first rotation event received - streamer-{main,substream,image,sensor}.html: remove redundant inline polling scripts, rely on sei-rotate.js Signed-off-by: Paul Philippov paul@themactep.com
- cc62e08 sei-rotate: skip preview.html to avoid double-polling with its own handler Signed-off-by: Paul Philippov paul@themactep.com
- 66f4a88 thingino-diag: add wireless information thingino-diag: redact raw hex PSK and add overlay tree dump Redact unquoted 64-char hex PSK values in wpa_supplicant.conf that were leaking through the existing quoted-psk-only sed pattern. Also add a tree /overlay/ section so diagnostics include the overlay filesystem contents. Signed-off-by: Paul Philippov paul@themactep.com
- f78f308 webui: adjust osd modal form layout
- 0598b99 package/prudynt-t: bump to 0f3fa5e (@ glyph for beats) Signed-off-by: Paul Philippov paul@themactep.com
- 8393e1f package/prudynt-t: update to 980f01e Update prudynt-t from d81e6e9 to 980f01e Hash change: d81e6e93b1b2b9d906a7bb19c840fa13e403a0f9 -> 980f01e73d1b1e66b8549148af9a954532b29908 Changelog: e7de9c4: osd: add Font5x7 glyph set, configurable burn-in fill/outline colors 9cd9cbe: docs: comprehensive OSD documentation for burn-in and SEI layers 091e526: motion: exclude burn-in OSD area from motion detection ROI d2963a6: docs: document burn-in motion detection exclusion 8bb5fc5: osd: add @b/%b Swatch Internet Time (.beats) token for burn-in c4b51db: osd: restrict .beats token to @b only (%b conflicts with strftime) 42364da: font5x7: add # (hash) glyph 980f01e: font5x7: add / (slash) glyph
- cd726ab package/open-tx-isp: update to fddb684 Update open-tx-isp from f5224df to fddb684 Hash change: f5224df98e1326d9c443fa344e645211805cd1d5 -> fddb6843814385dad8b684dd922bc488cbcb70c2 Changelog: 2ef03b2: Check pt 29b2a38: Work on GIB d4c8315: Enable the full pipeline b13acb5: Check pt ec502f7: Check pt de6515a: mostly stable 12fcefa: more OEM matching c6e1a43: more OEM matching 5243486: Check pt avpu stalls 995b7bb: flickr is gone c132e02: Check pt c1abc35: Stream1 doesn't crash 7e574e2: Check pt f903758: multi-channel working b3b4064: Check pt e287cd9: Check pt 0e816ff: Dead code cleanup + CSI timing stabalization fix around sc2336 e61b962: Check pt 10927e3: Check pt fc4ab81: ADR working 37f7ce7: AWB work 308418e: Check pt 0d8ff79: Check pt 7dc544e: AWB color correction hacks + enable GIB block 511b46d: Revert WB register address change (0x1804 caused purple), keep GIB enabled 7312fa5: Fix AWB stats collection: bit16=0 gives raw Bayer data, fixes sepia e19ea2f: AWB stats fix (bit16=0) + GIB disabled pending investigation 4d35e4b: Check pt work on Gib acfc893: GIB deferred enable: bypass until libimp sends DEIR params b378e8d: AWB work e55374c: Fix AWB gain registers: 0x1804/0x1808/0x180c (OEM vic_mdma_enable+offsets) c1a9ae0: Implement OEM-exact cm_control 3x3 BT.601 saturation matrix 22092b0: Fix BCSH: compute OffsetRGB2yuv from tuning binary (was hardcoded) 263ad8d: Fix BCSH saturation: S-vector packing, EV interpolation, clip0/HLSP 419f1e0: Check pt 8f491c2: Add netlink param dispatch, AF params, fix MDNS/netlink timing d4f30af: Implement OEM-exact MDNS DMA buffer setup and enable ca22141: MDNS work a03add0: Check pt 6a062fb: Check pt MDNS 781ba3e: Check pt dacc0e1: check pt 52f881a: FIXED (AWB stats collection). 6c121fb: testing b2134b9: Check pt f3f7cf3: exclude c55369f: Fix color pipeline regressions — restore working image quality ea7fc44: Fix AE register clobbering and improve DMA buffer allocation 3c1166c: Revert WB gain registers to 0x183c/0x1840/0x1844/0x1810 71637ce: Revert WB registers to 0x183c/0x1840/0x1844/0x1810 (working colors) 51bfb0e: Add explicit AWB stats enable (0xb000=1) from OEM trace analysis 05a1153: Check pt 7d00fc4: AWB stats now working a8f25b6: Fix AE stats DMA: load...
ccache
Rolling per-branch build ccache (compiler cache). Not a firmware release; do not flash.
firmware-2026-07-18
Changes in this release:
- f433166 thingino-uboot: restore vendored SPL binaries after patching GNU patch cannot apply the binary diffs embedded in 0001-from-2013.07-to-thingino.patch, so spl/binary/*.bin ended up as zero-byte files in the patched U-Boot tree. Boards that use a prebuilt SPL (T31LC and Xiaomi MJSXJ03HL variants with CONFIG_XIAOMI_SPL) then got a firmware image with an empty SPL region, bricking the camera on flash. The correct blobs were already vendored into package/thingino-uboot/files/ (commit 58cda12) but nothing copied them into the source tree. Add a post-patch hook that restores them into spl/binary/ for the 2013.07 U-Boot. Verified: u-boot-with-spl.bin for xiaomi_mjsxj03hl_t31l_jxq03p_rtl8189ftv now begins with the 26624-byte t31_xiaomi_sfcnor.bin blob (Ingenic SPL magic 06 05 04 03 02 55 aa 55 aa) instead of zeros. Fixes: #1299 Signed-off-by: Paul Philippov paul@themactep.com
- b613a31 package/prudynt-t: update to 879a387 Pulls in the simple-rtsp RTCP SR fix: SR NTP time is now derived from CLOCK_MONOTONIC instead of gettimeofday(), so NTP daemon clock steps on the camera no longer shift the NTP<->RTP mapping mid-session and flood multi-stream RTSP receivers (ffmpeg/Frigate) with 'Non-monotonic DTS' errors. Signed-off-by: Paul Philippov paul@themactep.com
- 03a27bb sysupgrade: save on full erasing since we override entire chip now
- 37d4042 package/prudynt-t: update to c026768 Update prudynt-t from e61ba27 to c026768 Hash change: e61ba2765f9f55b8a15da67cfdc8e3de6351d919 -> c0267682fd98498c1f183a4196e3d85963a97918 Changelog: 920b97c: SDP: add framesize attribute for H.264 video dimensions af55238: rtsp: fix buffering, bitstream corruption, and data-partitioning errors 04fcb06: remove legacy live555 RTSP code, replaced by simple-rtsp afc86c5: rtsp: add audio-only endpoint (/mic) to simple-rtsp server 52df6b0: audio: fix RTP timestamp backward jumps from NTP clock adjustments 26bf54c: rtsp: include git commit hash in SDP session title ac18bcf: build: always regenerate version.hpp to avoid stale commit hash fe8987f: audio: use IMP driver capture timestamp instead of CLOCK_MONOTONIC 5f9d57f: encoder: increase stream buffer size for high resolutions 5b2ec33: framesource: ensure ≥2 buffers for large frames (>4MB) 887a056: rtsp: add backchannel (talkback) support to simple-rtsp server 3643c44: backchannel: fix SDP to use single m=audio line with multiple PTs 9c448bd: backchannel: remove from DESCRIBE SDP, negotiate via ANNOUNCE only 091d5c9: backchannel: fix session gate so backchannel receive actually runs a1e08fd: backchannel: return Session header in ANNOUNCE response 48e66e6: rtsp: demote drain counters from LOG_DEBUG to LOG_DDEBUG bf93e3c: backchannel: add debug logging to SETUP handler 1a6d3f2: backchannel: add dispatch tracing to diagnose SETUP hang 403f0f6: rtsp: consume request body after parsing (fix ANNOUNCE SDP leak) c1ee4f5: backchannel: remove debug logging, feature complete 16bab4a: rtsp: suppress RTCP SR for backchannel-only sessions d943109: rtsp: add dedicated backchannel DESCRIBE response a9cdece: rtsp: always return backchannel SDP for /backchannel DESCRIBE 692a82e: fix: restore truncated generateBackchannelSdp call after sed mishap e837941: backchannel: add Opus codec support for WebRTC talkback 70435d3: backchannel: include in main /ch0 SDP, no ANNOUNCE required 280ea99: backchannel: detect track0 and /backchannel URI patterns in SETUP c24e787: audio: use NOBLOCK in IMP_AO_SendFrame to prevent speaker lockup 3d17a5b: backchannel: fix worker thread lifecycle and wakeup race b24823c: backchannel: flush audio output on session teardown 302a9d5: backchannel: use silence tail instead of abrupt flush on teardown 337c4a1: backchannel: use track0 control URL, match go2rtc's URL convention 5ddb106: backchannel: let audio output drain naturally, no silence tail 06c4c33: audio: revert NOBLOCK change, original BLOCK mode restored 151796f: backchannel: support TCP interleaved transport, capture from TCP stream 6a9884e: rtsp: allow PLAY for backchannel-only sessions 59d974e: backchannel: set backchannel=true on SETUP so PLAY succeeds 0ee059d: revert backchannel from main /ch0 SDP to fix go2rtc playback 4d03b7e: restore backchannel track0 in main SDP for MediaMTX testing ff83cee: sdp: add AAC fmtp config to backchannel tracks 57bdfd2: sdp: add channel count to OPUS rtpmap in backchannel tracks 88a8170: rtsp: only advertise backchannel when client sends ONVIF Require header 23384a0: backchannel: activate on PLAY per ONVIF Streaming Spec §5.3 c29aa12: fix onvif backchannel in simple-rtsp for go2rtc WebRTC 260ff6b: backchannel PR: revert IMPEncoder/IMPFramesource/MsgChannel/globals/VideoWorker to pre-PR 477b106: IMPEncoder: disable SetStreamBufSize/SetMaxStreamCnt on T31 d99cd1e: WS: fix build error from incomplete delay -> delay_us rename 590b204: docs: formatting 6d47fb4: rewrite standalone compilation 9fa3bba: ignore trash/ 150f4a1: docs: cleanup c026768: VideoWorker: derive frame end from last pack, T31 libimp never sets frameEnd
- f0169fd ingenic-sdk: fix silently-dropped button (gpio-userkeys) config Commit 425637b switched the gpio-userkeys config generator from reading env.txt (which always wrote the module load file) to reading thingino.json via jct, guarded by 'if which jct'. Two problems made that silently drop the button config: - bare 'which jct' checks the host PATH for a target/host tool that is not guaranteed to be there, and a miss is swallowed with no error, so no /etc/modules.d/gpio-userkeys is written and physical buttons (reset, chime) do not work; - the package declared no dependency on host-thingino-jct, so even when the tool does end up on PATH there is no ordering guarantee that it exists when this step runs. Use the host jct by absolute path ($(HOST_DIR)/bin/jct) and error if it is missing, matching how prudynt-t already does it, and add host-thingino-jct to INGENIC_SDK_DEPENDENCIES. (cherry picked from commit 2d682b1) [backport to ciao: dropped the BR2_INGENIC_SDK_GPIO_USERKEYS guard, which belongs to the SDK-components refactor not present on this branch] Signed-off-by: Paul Philippov paul@themactep.com
- 9b2fb95 package/timps: update to v1.3.3 Update timps from v1.3.0 to v1.3.3 Hash change: v1.3.0 -> v1.3.3 (No changelog available)
- 87661f5 package/thingino-dfu: update to v1.5.30 Update thingino-dfu from v1.5.24 to v1.5.30 Hash change: v1.5.24 -> v1.5.30 (No changelog available)
- e50e929 scripts: backchannel-test accepts IP argument
- cdd8744 scripts: backchannel-probe accepts plain IP, shows full SDP scripts: backchannel-probe filters SDP, shows summary with codecs Parses the SDP and extracts only backchannel-relevant sections. Shows host, status, and per-track details: direction (recvonly/ sendonly/sendrecv), control URL, and supported codec list. Still accepts plain IP or full rtsp:// URL.
- be95166 prudynt-t: change default H.264 profile from High to Main The Ingenic T31 encoder emits data-partitioned NALs (types 2/3/4) at High profile which FFmpeg cannot decode, causing 'data partitioning is not implemented' and cascading bitstream corruption errors. Main profile eliminates data partitioning while keeping CABAC and B-frames for equivalent compression efficiency.
- 9ef4b3f prudynt-t: use override source git hash for version string Previously commit_tag was taken from the firmware repo, not the prudynt-t overrides directory. Now reads the short hash from PRUDYNT_T_OVERRIDE_SRCDIR first, falling back to the firmware repo for non-override builds.
- 19dcf6d thingino-ffmpeg: add mp4 muxer, H.264/AAC parsers, BSFs, NFS copy Enable minimal remuxing support in the fallback (non-IPC/NVR/DEV) configuration so that stripped ffmpeg builds can from RTSP to MP4 segments. Previously only the segment muxer was compiled in, which delegates to an inner muxer (mp4) that wasn't available. Changes: - Enable mp4 muxer (needed by segment muxer for .mp4 output) - Enable h264 and aac parsers (frame boundary detection for muxer) - Enable h264_mp4toannexb and aac_adtstoasc BSFs (format conversion) - Fix protocol order: --enable-protocol=file after --disable-protocols so the file protocol survives the blanket disable - Add post-install hook to copy ffmpeg binary to /nfs/ Signed-off-by: Paul Philippov paul@themactep.com
- 1aa0a24 package/prudynt-t: update to e61ba27 Update prudynt-t from c5ed7ca to e61ba27 Hash change: c5ed7ca708854acbd07e18e25e2f308709f8a6a5 -> e61ba2765f9f55b8a15da67cfdc8e3de6351d919 Changelog: e61ba27: fix h265: SDP fmtp, NAL header corruption, keyframe gate
- e00aff6 Add backup-overlay target and script Add make backup-overlay IP= to pull /overlay/ from a running Thingino camera via SSH and store it as a timestamped tarball in a global backup directory (~/.thingino/backups by default). - scripts/backup_overlay.sh: detects camera IMAGE_ID, copies /overlay/, creates --.tar.gz - Makefile: THINGINO_BACKUP_DIR variable, backup-overlay target, help, show-vars entry - board.mk: exempt backup-overlay from camera selection requirement - docs/overlay-backup.md: usage, restore, troubleshooting - docs/makefile.md: documented the new target Signed-off-by: Paul Philippov paul@themactep.com fix backup-overlay: stream via SSH tar instead of scp scp -r with trailing /. fails on dropbear servers ("unexpected filename: ."). Also, scp runs as the scp user and cannot read files with mode 000 (e.g. crond.reboot). Switch to streaming tar+gzip directly over SSH. The camera-side tar runs as root and reads all files regardless of local permissions. Signed-off-by: Paul Philippov paul@themactep.com
- d5fa9b1 cameras: move smart_nvr_a1n_eth to experimental
- ddb7447 cameras: move wanji...