Skip to content

Fix hybrid/thermal cameras misdetected as doorbells, dropping IVS events - #587

Open
jaaneo wants to merge 1 commit into
rroller:mainfrom
jaaneo:fix/hybrid-camera-doorbell-channel-filter
Open

Fix hybrid/thermal cameras misdetected as doorbells, dropping IVS events#587
jaaneo wants to merge 1 commit into
rroller:mainfrom
jaaneo:fix/hybrid-camera-doorbell-channel-filter

Conversation

@jaaneo

@jaaneo jaaneo commented Jul 24, 2026

Copy link
Copy Markdown

Problem

I have a DHI-TPC-BF1241 (hybrid visual+thermal camera) alongside several regular IPC-HFW3849T1-AS-PV cameras. The regular cameras receive line-crossing/region events fine, but the hybrid camera never received any events at all, not even VideoMotion.

Root cause 1: is_doorbell() false positive

def is_doorbell(self) -> bool:
    m = self.model.upper()
    return m.startswith("VTO") or m.startswith("DH-VTO") or (
        "NVR" not in m and m.startswith("DHI")) or ...

Any model starting with DHI- (and not containing NVR) is treated as a doorbell (VTO). That's too broad - it's meant to catch doorbell models like DHI-VTO2211G-P, but it also matches regular cameras that happen to use the common DHI- prefix, like DHI-TPC-BF1241. Once misclassified, the integration opens a VTO connection on port 5000 instead of the normal event stream, which the camera doesn't support, so it silently never receives any events.

Fix: match on the VTO substring instead, which still catches VTO..., DH-VTO..., DHI-VTO..., without matching unrelated DHI- prefixed models.

Root cause 2: channel filter drops IVS events on hybrid cameras

After fixing is_doorbell(), the camera started connecting normally, but cross-line/cross-region events were still silently dropped:

if index != self._channel:
    continue

This filter exists so NVRs/DVRs - where multiple config entries (one per channel) share one event stream - can discard events meant for other channels. But the DHI-TPC-BF1241 reports CrossLineDetection/CrossRegionDetection on an internal sub-channel index (index: 1) that differs from its configured video channel (channel: 0), so this filter dropped them too, even for a single standalone entry with no channel-sharing going on.

Fix: only apply the filter when it's actually needed - i.e. when more than one config entry points at the same device address. A standalone camera (including a hybrid one with only one entry) isn't sharing its event stream with anything else, so there's nothing to filter out.

Testing

  • IPC-HFW3849T1-AS-PV (regular camera, unaffected by either bug): confirmed still works and channel filtering still applies correctly since it's unaffected either way.
  • DHI-TPC-BF1241 added as a single entry: confirmed is_doorbell() now returns False, event stream connects normally, and CrossRegionDetection/CrossLineDetection events arrive in the debug log with index: 1.
  • DHI-TPC-BF1241 split into two entries (one per channel, e.g. visual on channel 0 and thermal on channel 1): confirmed via the recorder history that a cross-region event correctly flips only the thermal-channel entry's sensor and leaves the visual-channel entry's sensor untouched.

is_doorbell() treated any model starting with "DHI-" (and not containing
"NVR") as a VTO doorbell. This misclassifies regular cameras whose model
just happens to use the common "DHI-" prefix, e.g. the DHI-TPC-BF1241
hybrid thermal camera. Once misclassified, the integration tried to open
a VTO connection on port 5000 instead of the normal camera event stream,
so the device never received any events at all (not even VideoMotion).
is_doorbell() now only matches on the "VTO" substring, matching real
Dahua doorbell model names like DHI-VTO2211G-P.

Separately, once events do arrive, on_receive() discarded any event
whose channel index didn't match the entry's configured channel. That
filter exists to handle NVRs/DVRs, where several config entries (one per
channel) share a single event stream and must ignore events meant for
other channels. Hybrid cameras report IVS events (CrossLineDetection,
CrossRegionDetection) on an internal sub-channel that differs from the
video channel, so this filter was silently dropping them too, even after
the device is correctly detected as a camera. The filter is now only
applied when more than one config entry shares the same device address,
which is the actual condition that requires per-channel filtering - a
standalone camera isn't sharing its stream with anything else.

Tested against an IPC-HFW3849T1-AS-PV (unaffected, still filters
correctly) and a DHI-TPC-BF1241 added both as a single entry and split
into two entries (visual + thermal channel), confirming cross-line and
cross-region events now reach the correct entry's sensors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant