czech english

Bezpečnostní kamery

AI na hlídání AI?

Bezpečnostní kamery jsou již běžné spotřební zboží — nelze je nějak využít pro mobilní robotiku? Jsou to „černé krabičky” pouze s mobilní aplikací a daty na cloudu nebo je alternativa? Blog update: 16/9/2024 — Reolink Support

Obsah



Blog

26. srpna 2024 — Náhodný výběr

Původně jsem to chtěl nazvat spíše „výběr kamery”, ale nabídka bezpečnostních kamer je široká a má trpělivost cokoliv nakupovat je nerozumně omezená. Asi jediný požadavek byl outdoor s tím, že bych rád nějaké otevřené API. Konzultoval jsem to s perplexity a ve zkratce mi doporučila Reolink a ke kamerám TP-Link Tapo C500 naznačovala, že existuje PyTapo Python knihovna.
Teď zpětně trošku chápu, o čem to ta AI psala. Zatím jsem vybalil tu TP-Link Tapo C500, která podporuje pouze WiFi přípojení a používá zdroj 12V/1A. Vyžadovalo to instalovat TP-Link Tapo Android applikaci, aby se kamera přepnula z access point módu na připojení na WiFi router. V rozšířených nastaveních lze pak přidat nového uživatele s heslem. A s tím je spojeno to RTSP (Real-Time Streaming Protocol):
  • rtsp://username:password@camera_ip:554/stream1
… toto fungovalo vlastně ve VLC Media Playeru hned. Časem jsem dohledal, že stream1 je s vyšším rozlišením a existuje ještě stream2 s nižším rozlišením. Stejné URL funguje i v OpenCV a tím pádem i rovnou v OSGARovi (stačí změnit v config/test-opencv-camera.json port na URL výše). Jen v tom VLC je navíc slyšet i audio.
Další krok byl s kamerou pohnout. Co fungovalo bylo posouvání v aplikaci na telefonu (a stále streamovat video). S tím je spojeno to druhé klíčové slovo ONVIF (Open Network Video Interface Forum). A jelikož o tom nic nevím, tak jsem zase zkoušel perplexity. Podle doporučení jsem nainstaloval zeep a onvif_zeep. Ale příklad použití na Tapo C500 úplně nefungoval. První zrada byla s portem — místo 80 je třeba použít 2020, jen už nevím, kde jsem tuto nápovědu sebral. Což mi ale připomíná, že jsem úplně vynechal PyTapo, které se zaseklo na problému autorizace a přes to jsem se nedostal — stáhl si github repo, jestli tam není novější verze, ale nepomohlo to. Také jsem zapomněl zmínit, že na kameře jsem po prvním připojení upgradeoval firmware — to také mohlo rozbít aktuální pytapo. A také jsem nezmínil, že při dalším připojení se změnila IP adresa kamery, ale to bych asi případně mohl změnit na routeru (aneb další možnost, jak se to mohlo pokazit).
from onvif import ONVIFCamera

# Replace with your camera's IP address, port, username, and password
camera_ip = '192.168.1.100'
camera_port = 2020
username = 'admin'
password = 'password'

# Create an ONVIF camera object
camera = ONVIFCamera(camera_ip, camera_port, username, password)

# Get device information
device_info = camera.devicemgmt.GetDeviceInformation()
print("Manufacturer:", device_info.Manufacturer)
print("Model:", device_info.Model)
print("Firmware Version:", device_info.FirmwareVersion)
print("Serial Number:", device_info.SerialNumber)
print("Hardware ID:", device_info.HardwareId)
… toto fungovalo (se správnou IP, username a password)
Manufacturer: tp-link
Model: Tapo C500
Firmware Version: 1.1.4 Build 240506 Rel.39487n
Serial Number: a19999 (upraveno)
Hardware ID: 1.0
ale při pokusech o posunutí se mi podařilo „položit server”, míněno server běžící na kameře:
capabilities = camera.devicemgmt.GetCapabilities()
skončilo s chybou:
http.client.BadStatusLine: POST /onvif/device_serviceHTTP/1.1Host 192.168.1.18:2020
User-Agent Zeep/4.2.1 (www.python-zeep.org)Accept-Encoding gzip, deflateAcHTTP/1.1
500 Internal Server Error
Pro dnešek asi stačí … časem bych doplnil i úvodní „omáčku” aneb motivace a pod.
p.s. thumb jsem převzal z https://www.railfanguides.us/oblivion/

6. září 2024 — AbsoluteMove

Toto se pokusím ještě teď v noci „odbavit” jako důkaz, že už nic nebrání nočnímu testování.
Posledně jsem psal, že dostat video z Tapo C500 bylo vlastně bez problémů (s použítím VLC). Dobrá zpráva je, že je i poměrně triviální to streamované video nahrát (pokud je kamera na síti). Co ale bylo (naštěstí už minulý čas) peklo bylo s tou kamerou programově pohnout! Jako ten ONVIF je pěkná věc, ale to by to musel každý výrobce pořádně dodržovat. A jak jsem psal, že posledně to skončilo 500 na serveru, tak s tím jsem dnes začal …
A k mému překvapení to není tak stará věc:
Jako myslím, že to novějším FW nevyřešili (mě to s 1.1.4 padá stále), ale zaujala mne tam další poznámka: the "UtcTime" element should be returned in the ISO 8601 format., která pěkně korelovala s chybou:
ERROR:zeep.xsd.types.simple:Error during xml -> python translation
Traceback (most recent call last):
  File "/home/md/.virtualenvs/tapo/lib/python3.8/site-packages/isodate/isodatetime.py", line 51, in parse_datetime
    datestring, timestring = datetimestring.split('T')
ValueError: not enough values to unpack (expected 2, got 1)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/md/.virtualenvs/tapo/lib/python3.8/site-packages/zeep/xsd/types/simple.py", line 79, in parse_xmlelement
    return self.pythonvalue(xmlelement.text)
  File "/home/md/.virtualenvs/tapo/lib/python3.8/site-packages/zeep/xsd/types/builtins.py", line 44, in _wrapper
    return func(self, re.sub(r"[\n\r\t ]", " ", value).strip())
  File "/home/md/.virtualenvs/tapo/lib/python3.8/site-packages/zeep/xsd/types/builtins.py", line 180, in pythonvalue
    return isodate.parse_datetime(value)
  File "/home/md/.virtualenvs/tapo/lib/python3.8/site-packages/isodate/isodatetime.py", line 53, in parse_datetime
    raise ISO8601Error("ISO 8601 time designator 'T' missing. Unable to"
isodate.isoerror.ISO8601Error: ISO 8601 time designator 'T' missing. Unable to parse datetime string 
                                                                                          'Fri Sep  6 20:52:11 2024'
Teď už si nevzpomenu, co jsem z té kamery chtěl dostat, asi
media = mycam.create_media_service()

# Create ptz service object
ptz = mycam.create_ptz_service()

# Get target profile
media_profile = media.GetProfiles()[0]

# Get PTZ configuration options for getting continuous move range
request = ptz.create_type('GetConfigurationOptions')
request.ConfigurationToken = media_profile.PTZConfiguration.token
ptz_configuration_options = ptz.GetConfigurationOptions(request)
… no nevím, měl jsem si to hned psát. Sigh.
Ale je to Python, takže stačilo oeditovat /home/md/.virtualenvs/tapo/lib/python3.8/site-packages/isodate/isodatetime.py, konkrétně
try:
        datestring, timestring = datetimestring.split('T')
    except ValueError:
        return datetime.strptime(datetimestring, "%a %b %d %H:%M:%S %Y")
#        raise ISO8601Error("ISO 8601 time designator 'T' missing. Unable to"
#                           " parse datetime string %r" % datetimestring)
Další milník byl výpis ptz_configuration_options:
'Spaces': {
        'AbsolutePanTiltPositionSpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace',
                'XRange': {
                    'Min': -1.0,
                    'Max': 1.0
                },
                'YRange': {
                    'Min': -1.0,
                    'Max': 1.0
                }
            }
        ],
        'AbsoluteZoomPositionSpace': [],
        'RelativePanTiltTranslationSpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace',
                'XRange': {
                    'Min': -1.0,
                    'Max': 1.0
                },
                'YRange': {
                    'Min': -1.0,
                    'Max': 1.0
                }
            }
        ],
        'RelativeZoomTranslationSpace': [],
        'ContinuousPanTiltVelocitySpace': [],
        'ContinuousZoomVelocitySpace': [],
        'PanTiltSpeedSpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace',
                'XRange': {
                    'Min': 0.0,
                    'Max': 1.0
                }
            }
        ],
        'ZoomSpeedSpace': [],
        'Extension': None,
        '_attr_1': None,
        …
    },
    'PTZTimeout': {
        'Min': datetime.timedelta(seconds=1),
        'Max': datetime.timedelta(seconds=600)
    },
    '_value_1': [
        
    ],
    'PTControlDirection': None,
    'Extension': None,
    '_attr_1': None
}
Nyní mám zpětně teorii, že ty prázdné listy znamenají, že to ta kamera prostě neumí. Ale co by měla umět je AbsolutePanTiltPositionSpace! Jenom k tomu dohledat, co že je to klíčové slovo, které se má někde vyplnit? Kupodivu to je AbsoluteMove.
# 
    positionrequest = ptz.create_type('AbsoluteMove')
    positionrequest.ProfileToken = media_profile.token

    if positionrequest.Position is None:
        positionrequest.Position = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
        positionrequest.Position.PanTilt.space = ptz_configuration_options.Spaces.AbsolutePanTiltPositionSpace[0].URI
#        positionrequest.Position.Zoom.space = ptz_configuration_options.Spaces.AbsoluteZoomPositionSpace[0].URI
    if positionrequest.Speed is None:
        positionrequest.Speed = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
        positionrequest.Speed.PanTilt.space = ptz_configuration_options.Spaces.PanTiltSpeedSpace[0].URI

    request = positionrequest
    request.Position.PanTilt.x = x
    request.Position.PanTilt.y = y
    ptz.AbsoluteMove(request)
Z velké části opsáno z FalkTannhaeuser/python-onvif-zeep. Ten Zoom je třeba zakomentovat/odstranit, protože C500 žádný zoom nemá. A výsledek po mini wrapperu a volání z konzole:
(tapo) md@md-ThinkPad-P50:~/git/pytapo$ python patapo.py 0.5 -0.5
(tapo) md@md-ThinkPad-P50:~/git/pytapo$ python patapo.py -0.4 -0.5
(tapo) md@md-ThinkPad-P50:~/git/pytapo$ python patapo.py 0 -0.7
… viz noční video – aréna je přípravena!


15. září 2024 — Reolink E1 Outdoor

Venku lije, tak jsem z trudomyslnosti rozbalil další kameru, tentokrát od firmy Reolink. Po pravdě už první problém byl zjistit, co přesně mám za kameru. Na krabici jsou hlavně reklamy, tj. Pan, Tilt and 3x Optical Zoom, 5MPx, 2.4/5GHz Dual-Band Wifi, Auto Tracking, a pod. Na faktůře je IP kamera Reolink E1 Outdoor — no jo, teď už jsem to našel i na te „reklamní” krabici. Na českých stránkách (ale myslím, že jsou pouze přeložené z angličtiny) mne zmátlo "Typ připojení: wi-fi", ale tuto kameru jsem primárně vybíral s tím, že má i Ethernetový konektor (a kabel). Ale je to ona, podle dalších indicií (nemá např. 4K video).
Můj první cíl byl rozchodit komunikaci s kamerou, aniž bych si instaloval aplikaci. Pokud kameru zapojíte do napájení, tak začne dokola asi v pěti jazycích hlasitě prskat, ať si nainstalujete aplikaci a ukážete jí na kameru. :-( … zacpat „reprák” jí můžete jen pár způsoby:
  • vypnete napájení
  • nainstalujete si aplikaci
  • připojíte Ethernetový kabel
Že funguje třetí varianta jsem zjistil náhodou.
Alternativou k aplikaci je nějaký client, ale ten je pouze pod Windows — začínám chápat Jirkovo trápení, když nová zařízení vyžadují instalaci čehosi, co pak typicky pošle jen dotaz po síti. Stáhnul jsem si i manuál, kde první co mne uhodilo mezi oči bylo The default username is "admin" and the password is blank (no password). Teď už chápu, proč jsou některé kamery snadno napadnutelné, aneb kolik uživatelů si heslo změní? (mimochodem, já si ho rovnou změnil, ale už se tam nemůžu dostat, ale to později)
Uživatel a „heslo” není vše - jakou IP adresu použít? Zkusil jsem znova perplexity.ai, která suveréně odpověděla: The default IP address for Reolink cameras and NVRs with an Ethernet interface is: 192.168.1.108 s odkazem na Reolink support. Tam žádná IP adresa není a ono i doporučení: All Reolink cameras and NVRs with Ethernet interface are allocated a default IP Address when they came out from the factory. Their default IP address can be located when connected directly to your PC with an Ethernet cable. Prostě když do browseru vyplníte IP adresu, tak vám pak stránka vygenerovaná kamerou, řekne IP adresu, žádný probém!
Nakonec jsem udělal to, co jsem úplně nechtěl, a připojil kameru do routeru s DHCP. Pak jsem pustil již osvědčený příkaz:
md@md-ThinkPad-P50:~/git/osm$ nmap -sP 192.168.1.*
Starting Nmap 7.80 ( https://nmap.org ) at 2024-09-15 13:32 CEST
Nmap scan report for router.home (192.168.1.1)
Host is up (0.00064s latency).
…
Nmap scan report for Camera1.home (192.168.1.31)
Host is up (0.0013s latency).
…
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.51 seconds
a pak v browseru opravdu fungovala https://192.168.1.31/, admin a prázdné heslo.
Zapnul jsem si RSTP a ONVIF, nastavil statickou IP adresu (stejnou co kamera dostala přes DHCP) a rebootoval. A už jsem se více z prohlížeče na kameru nedostal. Předpokládám, že je nutné i ten první RTMP a možná i to HTTP … no nic, asi budu zkoušet resetovat.
Streamování s novým heslem a pevnou IP adresou funguje OK, ale upravený kus kódu pro Tapo C500 už nikoliv. Přidal jsem si tam assert 0, až mi vypíše schopnosti kamery:
AssertionError: {
    'Spaces': {
        'AbsolutePanTiltPositionSpace': [],
        'AbsoluteZoomPositionSpace': [],
        'RelativePanTiltTranslationSpace': [],
        'RelativeZoomTranslationSpace': [],
        'ContinuousPanTiltVelocitySpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/PanTiltSpaces/VelocityGenericSpace',
                'XRange': {
                    'Min': -1.0,
                    'Max': 1.0
                },
                'YRange': {
                    'Min': -1.0,
                    'Max': 1.0
                }
            }
        ],
        'ContinuousZoomVelocitySpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/ZoomSpaces/VelocityGenericSpace',
                'XRange': {
                    'Min': -1.0,
                    'Max': 1.0
                }
            }
        ],
        'PanTiltSpeedSpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace',
                'XRange': {
                    'Min': 0.0,
                    'Max': 1.0
                }
            }
        ],

        'ZoomSpeedSpace': [
            {
                'URI': 'http://www.onvif.org/ver10/tptz/ZoomSpaces/ZoomGenericSpeedSpace',
                'XRange': {
                    'Min': -1.0,
                    'Max': 1.0
                }
            }
        ],
        'Extension': None,
        '_attr_1': None
    },
    'PTZTimeout': {
        'Min': datetime.timedelta(seconds=1),
        'Max': datetime.timedelta(seconds=10)
    },
    '_value_1': None,
    'PTControlDirection': None,
    'Extension': None,
    '_attr_1': None
}
Přijde mi pěkné, že existuje nějaký ONVIF, ale rozhodně nemůžu prohodit jednu IP kameru za druhou, když jejich schopnosti jsou doslova ortogonální (co má jedna nemá druhá a obráceně). Ale možná jsem jenom škarohlíd. Paradoxně si teď dovedu snáz představit programování té levnější Tapo kamery s absolutním poziciováním, než E1, kde ovládám jenom rychlost posunu. Ona možná vrací aktuální pozici, ale pak bych čekal i ty absolutní příkazy?
p.s. po hard resetu už nefunguje ani ONVIF ani RSTP ani prohlížeč. Je čas se vrátit ke trudomyslnosti …

16. září 2024 — Reolink Support

Včera jsem si ještě chvíli povídal s AI chatbotem na stránkách podpory. Jako úplně jsme si nerozumněli, takže když napsal:
(22:55:55) Reolink Bot: Sorry. You can try to rephrase your question or directly contact an agent by typing “Talk to human”.
(22:56:14) Web User 66e6f48bddc40a1b5199c30a: Talk to human
Pak to chtělo vyplnit pětipoložkový formulář a za chvíli přišel mail s detaily naší konverzace. Ty časy z konverzace jsou nejspíše Čína??
Dnes jsem si vyměnil cca 5 mailu s vyšší AI Ewelina — možná to byl člověk a možná lepší kompilátor: Firstly, I'd like to acknowledge that you're using a Linux-based system, which can sometimes present unique challenges when interfacing with security cameras. While Reolink doesn't officially support Linux operating systems, there are still ways we can try to resolve your issue. Když to hodně zkrátím, tak jsem si myslel, že mám skoro nejnovější verzi firmware v3.1.0, ale ona se dost zásadně lišila v buildu: Firmware Version v3.1.0.1789_23021701 vs. v3.1.0.3429_24041813. Firmware lze upgradeovat i z browseru, ale když ten nefunguje, tak smůla. Skončilo to nainstalováním klienta na prastarý notebook s Win7 a tam vše krásně fungovalo. Např. první krok, co to chtělo, byla změna hesla administrátora. Fajn.
Naklikal jsem stejné nastavení jako včera, naformátoval 256GB SD kartu a ověřil, že kameru mohou ovládat z linuxového prohlížeče. Asi bych si to teď měl zopakovat, jestli se mi to náhodou nezdálo …
Co Evelína zmiňovala byl pro mne nový příkaz rtsp://[username]:[password]@[IP_address]:554//h264Preview_01_main … funguje, jenom další screenshot nepořádku už asi sdílet nemusím. Ten časový posun se nějak neuložil … 10h, tj. zase západní pobřeží USA. Ono by to až tak nevadilo, ale pak v těch nahrávkách je hrozný guláš.
Zkoušel jsem ted tracking feature a opravdu se to otáčelo za naším psem — no hlavně jestli se to bude otáčet i za Patem.
p.s. už zase prší …