Thin wrappers `get_detect_info()` / `set_detect_info(data)` in both the
sync (`dvrip.py`) and async (`asyncio_dvrip.py`) clients for the
top-level `Detect` config path — per-channel MotionDetect /
HumanDetection (and, on multi-channel NVRs, BlindDetect / LossDetect).
The library already supported this via the generic `get_info("Detect")` /
`set_info("Detect", …)`, but the path and payload shape were undocumented.
README now carries a worked example showing the per-channel-array schema
and the sparse-merge semantics (fields omitted from a SET payload retain
their current value), plus a caveat that AlarmInfo push behaviour is
firmware-dependent — some XM builds emit events to the existing TCP
session, others only to a separately-configured `AlarmServer`, and some
do neither.
Verified on a live XM IPC unit (single-channel, hostname
IVG85HG50PYA-S-2): the canonical OpenIPC "turn motion detection on"
snippet returns `Ret: 100`, round-trip GET shows the change, sparse merge
works (`{"MotionDetect":[{"Level":4}]}` flips only `Level`).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The existing default flow built a per-board InstallDesc with `armbenv -s
telnetctrl 1` and the camera's real Hardware/Vendor/FlashID. On firmware
built after 2020-05-07 Xiongmai accepts the upload (returns "Upgrade
successful") but silently drops the embedded Shell commands, so telnet
never opens. The script worked around this with a `downgrade_old_version`
gate that simply refused to proceed — usable only if the user could
source a pre-2020 downgrade blob.
Replace the default path with a SkipCheck InstallDesc:
- Hardware/Vendor/SupportFlashType all set to the literal "SkipCheck"
magic, which bypasses the firmware-side validation.
- Two Shell commands flip telnetctrl=1 via both env tool variants
(`armbenv` and `XmEnv`), covering boards that ship one or the other.
- The env var only takes effect on reboot, so the helper now sends an
explicit OPMachine Reboot after the upload (the upload itself does
not auto-reboot in this flow).
- The post-reboot telnet port is firmware-determined, so probe a list
(default 23, 4321, 50119 — 50119 observed on GK7205V300 / 000699H7)
and return whichever opens. `--ports` overrides the list.
`do_backup_via_telnet` now probes the same port list instead of hard-
coding 23, and threads the discovered port through to the telnet socket.
The `-t` busybox-telnetd no-reboot path is left untouched (different
mechanism, not re-verified under SkipCheck).
Verified end-to-end on IPC_GK7205V300_85K50T running firmware 000699H7
(build 2023-01-10): upload + reboot + telnet listening on 50119.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Previously --backup required telnet to already be enabled, so a fresh
camera needed two invocations: one to enable telnet (with reboot), then
one to back up. Now --backup auto-enables telnet via the InstallDesc
exploit when port 23 is closed, waits for the reboot, and proceeds. The
script also exits 0 / non-0 so it composes cleanly in shell loops and
automation:
for ip in 10.0.0.10 10.0.0.11 10.0.0.12; do
python3 telnet_opener.py "$ip" -b --nfs 10.0.0.1:/srv/ipctool
done
The old `-b/--backup` mounted a now-defunct NFS share at 95.217.179.189
and ran `ipctool -w` (the silent S3-upload mode disabled per
OpenIPC/ipctool#78). Both pieces are gone. The new flow telnets in as
root/xmhdipc, mounts a user-supplied NFS share, and runs
`ipctool backup /utils/backup-<MAC>` so the dump stays on the user's
network.
Also fall back to the XMV4 SupportFlashType list when the camera's
SWVER is unknown — without this, older firmware (e.g. 50H20L /
00031520) rejects the InstallDesc payload entirely.
- Restore the blank line between GetAllAddr and SearchXM, drop the
stray blank lines added in ConfigXM and the trailing whitespace on
the new Password label grid call.
- Rename the duplicated self.l6 used for the Username label to self.l8
so the Password label's self.l6 is no longer shadowed.
- Prefill the Username entry from devices[dev] when the discovered
value is available, falling back to "admin" only when missing.
- Drop the inline #"admin" comment.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
- add get_channel_titles()
- add get_channel_statuses()
- change send_custom() and get_file(): get the first chunk size from netip header instead of hardcoded
- change list_local_files(): allow list files for any channel, review error processing logic
Add NVR class
Add NVRVideoDownloader application which allows downloading video-files from NVR