Closed foxel closed 6 months ago
onvif_srvd is a very complex C++ program. It's very difficult. At the moment I don't have the time.
@roleoroleo I found onvif_srvd being a dedicated repo here. Can I compile and run it without uploading to the camera? Maybe I could try adding the functionally developing on a regular desktop PC.
Yes you can try. You could build it for x86.
I looked at the onvif events and saw that onvif_srvd is completely devoid of any management. Perhaps pull management could be implemented with relatively little code, but push management is a lot of stuff.
I added events management (pull) to the sonoff project https://github.com/roleoroleo/sonoff-hack It's based on the same software. If it works correctly I could add to MStar and Allwinner too.
That sounds really cool. I've read thru the code there. looks reasonable. I would love to try it out. Unfortunately, I have no sonoff camera available.
Do you want to try this beta? onvif_srvd.gz
I recommend you to use "Onvif Device Manager" and "Onvif Device Test Tool".
Hi, @roleoroleo
I tried the binary by replacing the original one with the one you've provided. It works and not:
first I tested with onvif-device-tool
. I was able to see the events. Small issue thought is the timestamp of motion stop event:
having this working I started testing with Home-Assistant:
GetServiceCapabilities
for event service returns no WSPullPointSupport
capability, which is checked in HA.CreatePullPointSubscriptionRequest
. When this call happens the process on the camera side exits and SOAP connection closed unexpectedly. Here are some logs:
2020-09-19 01:12:37 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry Second - 50:13:95:f0:97:fd for onvif
Traceback (most recent call last):
File "/home/foxel/projects/home-assistant/homeassistant/config_entries.py", line 228, in async_setup
result = await component.async_setup_entry(hass, self) # type: ignore
File "/home/foxel/projects/home-assistant/homeassistant/components/onvif/__init__.py", line 83, in async_setup_entry
if device.capabilities.events and await device.events.async_start():
File "/home/foxel/projects/home-assistant/homeassistant/components/onvif/event.py", line 82, in async_start
if await self.device.create_pullpoint_subscription():
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/onvif/client.py", line 279, in create_pullpoint_subscription
pullpoint = await events.CreatePullPointSubscription()
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/zeep/asyncio/bindings.py", line 14, in send
response = await client.transport.post_xml(
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/zeep/asyncio/transport.py", line 107, in post_xml
response = await self.post(address, message, headers)
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/zeep/asyncio/transport.py", line 90, in post
response = await self.session.post(
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/aiohttp/client.py", line 504, in _request
await resp.start(conn)
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/aiohttp/client_reqrep.py", line 847, in start
message, payload = await self._protocol.read() # type: ignore # noqa
File "/home/foxel/projects/home-assistant/venv/lib/python3.8/site-packages/aiohttp/streams.py", line 591, in read
await self._waiter
aiohttp.client_exceptions.ServerDisconnectedError
the payload:
<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope"><soap-env:Header xmlns:wsa="http://www.w3.org/2005/08/addressing"><wsa:Action>http://www.onvif.org/ver10/events/wsdl/EventPortType/CreatePullPointSubscriptionRequest</wsa:Action><wsa:MessageID>urn:uuid:8eb9e99d-1db8-4088-8eb9-69f8da547992</wsa:MessageID><wsa:To>http://192.168.0.217:80</wsa:To><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">xeUQBp5oJvv1Gb+DF1RD/BMF3yU=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">5GvohAhNU4beAYs0DrXBtA==</wsse:Nonce><wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-09-18T18:12:37+00:00</wsu:Created></wsse:UsernameToken></wsse:Security></soap-env:Header><soap-env:Body><ns0:CreatePullPointSubscription xmlns:ns0="http://www.onvif.org/ver10/events/wsdl"/></soap-env:Body></soap-env:Envelope>
I then run onvif_srvd --no_fork ...
and saw that it fails with Segmentation fault. Seeking thru the code for sonoff-hack I think the issue is that the request above does not have InitialTerminationTime
which is optional according to WSDL
Some more investigation:
I force HA to send InitialTerminationTime
and was able to make it run until it sends 'Unsubscribe':
<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope"><soap-env:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">iE80+3iYwHA+RtX1BgC0cK0AemE=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">Z4EbiJRWPvAOHmMZ717Geg==</wsse:Nonce><wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-09-18T19:03:00+00:00</wsu:Created></wsse:UsernameToken></wsse:Security></soap-env:Header><soap-env:Body><ns0:Unsubscribe xmlns:ns0="http://docs.oasis-open.org/wsn/b-2"/></soap-env:Body></soap-env:Envelope>
... or Renew:
<?xml version=\'1.0\' encoding=\'utf-8\'?>\n<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope"><soap-env:Header><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><wsse:UsernameToken><wsse:Username>admin</wsse:Username><wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">C5U1KOgTg9noiPDRmu9lRfvLxrg=</wsse:Password><wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">fJohd1XaQTySyh/Uc854UA==</wsse:Nonce><wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2020-09-18T19:35:58+00:00</wsu:Created></wsse:UsernameToken></wsse:Security></soap-env:Header><soap-env:Body><ns0:Renew xmlns:ns0="http://docs.oasis-open.org/wsn/b-2"><ns0:TerminationTime>2020-09-19T19:29:40Z</ns0:TerminationTime></ns0:Renew></soap-env:Body></soap-env:Envelope>
The program exits like this:
/home/yi-hack # onvif_srvd --no_fork --model "Yi Hack" --manufacturer "Yi" --fir
mware_ver "3.5.0" --hardware_id 125125 --serial_num SNUM --ifs wlan0 --port 80 -
-scope onvif://www.onvif.org/Profile/S --name Profile_1 --width 640 --height 360
--url rtsp://%s/ch0_1.h264 --snapurl http://%s:8080/cgi-bin/snapshot.sh?res=low
--type H264 --user admin --password Password --log_file /proc/self/fd/1 --no_cl
ose
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid
Aborted
/home/yi-hack #
Another strange thing: when I start HA with all the modifications I made so far, it connects but receives empty set of messages until I open and close onvif-device-tool... Looks strange but that's it...
I will check your posts tomorrow and I will send you another beta. Thank you for your time.
first I tested with
onvif-device-tool
. I was able to see the events. Small issue thought is the timestamp of motion stop event:
Fixed.
* first issue I found is that `GetServiceCapabilities` for event service returns no [`WSPullPointSupport`](https://github.com/roleoroleo/sonoff-hack/blob/686f4d8d89386775d8d8e21bc44db5cd7e71625b/src/onvif_srvd/onvif_srvd/wsdl/event.wsdl#L47) capability, which is checked in HA.
Fixed.
* second issue I found when forced HA to think WSPullPointSupport is available and use `CreatePullPointSubscriptionRequest`. When this call happens the process on the camera side exits and SOAP connection closed unexpectedly. Here are some logs:
Fixed.
I'm investigating the other issues.
The renew request crashes because the request header doesn't contain "To" field.
Found a workaround. Please, try this version: onvif_srvd.gz
Checked this one. Results:
State
set to True
but HA expects 'true' (no capital letter). I was googling to understand what's correct value here and found two different sorces:
For the last item I can't say it's definetely an issue on yi-hack side, but since HA implementation works for other cameras it might still be a good decision to use 'true' there. I also think it's still makes sence to make HA case-insensitive and I may de a PR there too.
Added:
onvif-device-tool
now posts 'error: PullMessages exit virtual void EventThread::run()' after one or two messages received
I will check renew and PullMessages request. No problem to change True in true and False in false.
Another beta release... onvif_srvd.gz
Tests result:
* Renew.TerminationTime is ignored and termination time is 1 minute ahead next time PullMessagesResult is returned
Could you explain me better? When I test it with onvif device test tool I don't notice this problem.
* if there are two connections, e.g. onvif-device-tool and HA in my tests. Only one gets the messages
Yes, at the moment is not thread safe. Next step.
@roleoroleo sure: When Renew request is sent TerminationTime contains the desired subscription termination time. So it's expected to have at least this value returned in subsequent PullMessagesResult.
So, the problem isn't the RenewResponse but the PullMessageResponse...
I have a new version and a few questions. Reading onvif specifications I don't understand correctly the TerminationTime meaning.
TerminationTime [dateTime]
Date time when the PullPoint will be shut down without further pull requests.
So, the server must extend termination time when a PullMessage request is submitted? Or only aftera a renew command?
Hi, @roleoroleo . I was reading thru https://www.onvif.org/specs/core/ONVIF-Core-Specification.pdf and I can't say anything about extending termination time when PullMessage is submitted, I think it's not restricted since each PullMessageResponse has new TerminationTime. But renew should be available as I can say.
Checked out the latest binary. I can't see any difference. It's still does nor update TerminationTime when Renew passed and two connection are not handled
Did you try the new version? It should fix the TerminationTime issue. Let me know...
Yes. I did try the latest archive
Have ONVIF Motion Alarm and Detected Sound been implemented?
It's work in progress.
I made a beta version with event support but I encountered a lot of problems. The daemon exits due to a segmentation fault that seems to be related to gsoap. At the moment I suspended the development.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Hi. It looks like the ONVIF protocol has the ability to deliver events from cameras. And there is an ONVIF integration in HA that supports these events.
In case of YI-hack, some of the events are particularly interesting as they are already supported with MQTT:
And for the following the values are present in mi-hack UI:
Do you see a way of integrating this into the firmware? At least the MotionAlarm section?