Files
Behavision/tests/test_discover.py
Suriyakumarvijayanayagam 1607f4ce74 Find the camera on the network instead of asking for its address
The add-camera form asked for an IP address, and a shop owner does not
know their camera's IP address - it is on a sticker under the camera or
in a menu that differs by make. That field is where onboarding stopped
for anyone who was not an installer.

behavision/discover.py: one ONVIF WS-Discovery multicast (names the
camera and often its make) merged with a TCP sweep of port 554 across
the local /24 (misses nothing that streams). Stdlib only, ~4 s on the
office network, both cameras found. The add-camera sheet leads with
'Find cameras on this network'; picking a row fills the address and,
when the make is recognisable, the stream path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGcjxF1cNLcuwc3DAPcnfj
2026-09-21 12:27:47 +05:30

45 lines
2.0 KiB
Python

"""Discovery parsing, with no network: the two shapes cameras actually send."""
from behavision.discover import parse_probe_match, guess_make, local_networks
HIK = ('<?xml version="1.0"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">'
'<env:Body><d:ProbeMatches xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery"><d:ProbeMatch>'
'<d:Scopes>onvif://www.onvif.org/type/video_encoder onvif://www.onvif.org/name/HIKVISION%20DS-2CD2043G2 '
'onvif://www.onvif.org/hardware/DS-2CD2043G2-I onvif://www.onvif.org/location/city/hangzhou</d:Scopes>'
'<d:XAddrs>http://192.168.1.122/onvif/device_service</d:XAddrs>'
'</d:ProbeMatch></d:ProbeMatches></env:Body></env:Envelope>')
BARE = ('<SOAP-ENV:Envelope><SOAP-ENV:Body><wsdd:ProbeMatches><wsdd:ProbeMatch>'
'<wsdd:XAddrs>http://10.0.0.9:8080/onvif/device_service http://[fe80::1]/onvif</wsdd:XAddrs>'
'</wsdd:ProbeMatch></wsdd:ProbeMatches></SOAP-ENV:Body></SOAP-ENV:Envelope>')
def test_hikvision_probe_match_is_named_and_recognised():
f = parse_probe_match(HIK, "192.168.1.122")
assert f.host == "192.168.1.122"
assert f.onvif and not f.rtsp
assert "HIKVISION DS-2CD2043G2" in f.name and "DS-2CD2043G2-I" in f.name
assert f.make == "hikvision"
def test_a_nameless_match_still_yields_its_address():
f = parse_probe_match(BARE, "10.0.0.9")
assert f.host == "10.0.0.9" and f.name == "" and f.make == ""
assert f.onvif_url.startswith("http://10.0.0.9:8080")
def test_garbage_is_not_a_camera():
assert parse_probe_match("<html>not soap</html>", "1.2.3.4") is None
def test_make_guesses_the_common_indian_retail_brands():
assert guess_make("CP PLUS CP-UNC-TA21L3") == "cpplus"
assert guess_make("Dahua IPC-HDW1230") == "dahua"
assert guess_make("TP-LINK Tapo C200") == "tplink"
assert guess_make("Something Else") == ""
def test_local_networks_are_slash_24_and_never_loopback():
for n in local_networks():
assert n.prefixlen == 24
assert not n.network_address.is_loopback