Implement P2P protocol for device control
Describe what the PR does: This is an initial attempt at implementing the peer to peer protocol in Python that is heavily based on https://github.com/fbertone/lib32100 combined with Eufy-specific elements. I only have a single "standalone" device (floodlight) so I can't test certain features that I know won't work just yet. Apart from that, it does seem to at least work (see added example for usage) but I imagine there needs to be a discussion on the best API to expose from within this library to make it more friendly for other applications so there still aren't any unit tests.
Does this fix a specific issue? Nope, new feature.
Checklist:
- [ ] Confirm that one or more new tests are written for the new functionality.
- [ ] Update
README.mdwith any new documentation. - [ ] Add yourself to
AUTHORS.md.
Looks promising. Wasn't able to connect to the my doorbell with that yet though. Will dig deeper.
I think I figured out why it's not working with the doorbell:
When you do discovery, STUN servers actually send your (client's) host/port to the doorbell. Since you open a new connection (with a new port) to connect to every new host, the doorbell gets the port different from the one you're using to connect to it. You should open only one connection and use it to communicate with everything.
Ah, that does makes sense, but it seems like @joepadmiraal's attempt wasn't even getting that far -- it didn't seem like there was even a valid response from the discovery servers.
Could be API_BASE switching. In my case it switches to -eu and can't find anything. I think that's also the reason why my doorbell is no longer displayed in the web-app.
I'm replying here instead of in the issue to concentrate our findings. I tested with the EU addresses and it now seems to get a bit further for me. Sometimes I get this output:
DEBUG:asyncio:Using selector: EpollSelector
INFO:eufy_security.api:Switching to another API_BASE: https://security-app-eu.eufylife.com/v1
------------------
Station Name: eufy base
Serial Number: T8010P2320020A43
DEBUG:eufy_security.station:Unable to process parameter "1266", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1176", value "192.168.0.248"
DEBUG:eufy_security.station:Unable to process parameter "1236", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1155", value "2"
DEBUG:eufy_security.station:Unable to process parameter "1135", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1670", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1265", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1362", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1253", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1200", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1043", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1280", value "30"
DEBUG:eufy_security.station:Unable to process parameter "1140", value "1"
Station params: {1266: '0', 1176: '192.168.0.248', 1236: '1', <ParamType.GUARD_MODE: 1224>: 1, <ParamType.CAMERA_SPEAKER_VOLUME: 1230>: 26, 1155: '2', 1135: '0', 1670: '0', 1265: '1', <ParamType.CAMERA_UPGRADE_NOW: 1133>: 0, 1362: '1', 1253: '0', 1200: '0', 1043: '0', <ParamType.SCHEDULE_MODE: 1257>: 63, 1280: '30', 1140: '1'}
Camera params: DeviceType.STATION
INFO:eufy_security.p2p.session:Trying discovery seed 34.235.4.153
INFO:eufy_security.p2p.session:Trying discovery seed 54.153.101.7
INFO:eufy_security.p2p.session:Trying discovery seed 18.223.127.200
INFO:eufy_security.p2p.session:Trying discovery seed 54.223.148.206
INFO:eufy_security.p2p.session:Trying discovery seed 18.197.212.165
INFO:eufy_security.p2p.session:Trying discovery seed 13.251.222.7
INFO:eufy_security.p2p.session:Trying addresses: ('192.168.0.248', 29798)
ERROR:eufy_security.p2p.session:Error received
Traceback (most recent call last):
File "/usr/lib64/python3.8/asyncio/selector_events.py", line 1009, in _read_ready
data, addr = self._sock.recvfrom(self.max_size)
ConnectionRefusedError: [Errno 111] Connection refused
ERROR:eufy_security.p2p.session:Error received
Traceback (most recent call last):
File "/usr/lib64/python3.8/asyncio/selector_events.py", line 1009, in _read_ready
data, addr = self._sock.recvfrom(self.max_size)
ConnectionRefusedError: [Errno 111] Connection refused
INFO:eufy_security.p2p.session:Connection closed
INFO:eufy_security.p2p.session:Trying addresses: ('94.208.195.16', 29798)
ERROR:eufy_security.p2p.session:Error received
Traceback (most recent call last):
File "/usr/lib64/python3.8/asyncio/selector_events.py", line 1009, in _read_ready
data, addr = self._sock.recvfrom(self.max_size)
ConnectionRefusedError: [Errno 111] Connection refused
ERROR:eufy_security.p2p.session:Error received
Traceback (most recent call last):
File "/usr/lib64/python3.8/asyncio/selector_events.py", line 1009, in _read_ready
data, addr = self._sock.recvfrom(self.max_size)
ConnectionRefusedError: [Errno 111] Connection refused
INFO:eufy_security.p2p.session:Connection closed
Traceback (most recent call last):
File "test_p2p.py", line 42, in <module>
asyncio.get_event_loop().run_until_complete(main())
File "/usr/lib64/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "test_p2p.py", line 30, in main
async with station.connect() as session:
File "/usr/lib64/python3.8/contextlib.py", line 171, in __aenter__
return await self.gen.__anext__()
File "/home/joep/Documents/joep/domotica/eufy/python-keshavdv/eufy_security/station.py", line 45, in connect
raise EufySecurityP2PError(f"Could not connect to {self.name}")
eufy_security.errors.EufySecurityP2PError: Could not connect to eufy base
And sometimes I get this output. In this case it will hang (waited for 2 minutes) instead of stop the program.
DEBUG:asyncio:Using selector: EpollSelector
INFO:eufy_security.api:Switching to another API_BASE: https://security-app-eu.eufylife.com/v1
------------------
Station Name: eufy base
Serial Number: T8010P2320020A43
DEBUG:eufy_security.station:Unable to process parameter "1266", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1176", value "192.168.0.248"
DEBUG:eufy_security.station:Unable to process parameter "1236", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1155", value "2"
DEBUG:eufy_security.station:Unable to process parameter "1135", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1670", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1265", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1362", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1253", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1200", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1043", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1280", value "30"
DEBUG:eufy_security.station:Unable to process parameter "1140", value "1"
Station params: {1266: '0', 1176: '192.168.0.248', 1236: '1', <ParamType.GUARD_MODE: 1224>: 1, <ParamType.CAMERA_SPEAKER_VOLUME: 1230>: 26, 1155: '2', 1135: '0', 1670: '0', 1265: '1', <ParamType.CAMERA_UPGRADE_NOW: 1133>: 0, 1362: '1', 1253: '0', 1200: '0', 1043: '0', <ParamType.SCHEDULE_MODE: 1257>: 63, 1280: '30', 1140: '1'}
Camera params: DeviceType.STATION
INFO:eufy_security.p2p.session:Trying discovery seed 34.235.4.153
INFO:eufy_security.p2p.session:Trying discovery seed 54.153.101.7
INFO:eufy_security.p2p.session:Trying discovery seed 18.223.127.200
INFO:eufy_security.p2p.session:Trying discovery seed 54.223.148.206
INFO:eufy_security.p2p.session:Trying discovery seed 18.197.212.165
INFO:eufy_security.p2p.session:Trying discovery seed 13.251.222.7
INFO:eufy_security.p2p.session:Trying addresses: ('192.168.0.248', 23219)
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_PING (20): bytearray(b'\xd1\x00\x00\x00XZYHs\x04\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00')
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_PING (20): bytearray(b'\xd1\x00\x00\x01XZYHs\x04\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00')
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_PING (20): bytearray(b'\xd1\x00\x00\x02XZYHs\x04\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00')
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_PING (20): bytearray(b'\xd1\x00\x00\x03XZYHs\x04\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00')
DEBUG:eufy_security.p2p.session:Processing P2PClientProtocolResponseMessageType.DATA:EufyP2PDataType.CONTROL with seq 0
DEBUG:eufy_security.p2p.session:Received command type CommandType.CMD_PING
DEBUG:eufy_security.p2p.session:Processing P2PClientProtocolResponseMessageType.DATA:EufyP2PDataType.CONTROL with seq 1
DEBUG:eufy_security.p2p.session:Received command type CommandType.CMD_PING
Sweet! So I think you're getting around the NAT issues that @nonsleepr might be hitting since you’re accessing your device over LAN, but it's at least looking more promising. It seems like it was able to communicate with the doorbell and is stuck because it didn't receive a packet that I expected it should based on my own testing. Can you try the latest commit and share another tcpdump if it still hangs?
Seems better now:
DEBUG:asyncio:Using selector: EpollSelector
INFO:eufy_security.api:Switching to another API_BASE: https://security-app-eu.eufylife.com/v1
------------------
Station Name: eufy base
Serial Number: T8010P2320020A43
DEBUG:eufy_security.station:Unable to process parameter "1266", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1176", value "192.168.0.248"
DEBUG:eufy_security.station:Unable to process parameter "1236", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1155", value "2"
DEBUG:eufy_security.station:Unable to process parameter "1135", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1670", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1265", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1362", value "1"
DEBUG:eufy_security.station:Unable to process parameter "1253", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1200", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1043", value "0"
DEBUG:eufy_security.station:Unable to process parameter "1280", value "30"
DEBUG:eufy_security.station:Unable to process parameter "1140", value "1"
Station params: {1266: '0', 1176: '192.168.0.248', 1236: '1', <ParamType.GUARD_MODE: 1224>: 1, <ParamType.CAMERA_SPEAKER_VOLUME: 1230>: 26, 1155: '2', 1135: '0', 1670: '0', 1265: '1', <ParamType.CAMERA_UPGRADE_NOW: 1133>: 0, 1362: '1', 1253: '0', 1200: '0', 1043: '0', <ParamType.SCHEDULE_MODE: 1257>: 63, 1280: '30', 1140: '1'}
Camera params: DeviceType.STATION
INFO:eufy_security.p2p.session:Trying discovery seed 34.235.4.153
INFO:eufy_security.p2p.session:Trying discovery seed 54.153.101.7
INFO:eufy_security.p2p.session:Trying discovery seed 18.223.127.200
INFO:eufy_security.p2p.session:Trying discovery seed 54.223.148.206
INFO:eufy_security.p2p.session:Trying discovery seed 18.197.212.165
INFO:eufy_security.p2p.session:Trying discovery seed 13.251.222.7
INFO:eufy_security.p2p.session:Trying addresses: ('192.168.0.248', 23192)
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_PING (20): bytearray(b'\xd1\x00\x00\x00XZYHs\x04\x00\x00\x00\x00\x01\x00\xff\x00\x00\x00')
INFO:eufy_security.p2p.session:Connected to ('192.168.0.248', 23192)
Turning the on-screen watermark on
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_SET_DEVS_OSD (156): bytearray(b'\xd1\x00\x00\x01XZYH\xbe\x04\x88\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00c37274750c94e96532bfeaad0bd4bfd815bef36a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
DEBUG:eufy_security.p2p.session:Processing P2PClientProtocolResponseMessageType.DATA:EufyP2PDataType.CONTROL with seq 0
DEBUG:eufy_security.p2p.session:Received command type CommandType.CMD_PING
DEBUG:eufy_security.p2p.session:Processing P2PClientProtocolResponseMessageType.DATA:EufyP2PDataType.DATA with seq 0
DEBUG:eufy_security.p2p.session:Received command type CommandType.CMD_SET_DEVS_OSD
Turning watermark off
DEBUG:eufy_security.p2p.session:Sending packet CommandType.CMD_SET_DEVS_OSD (156): bytearray(b'\xd1\x00\x00\x02XZYH\xbe\x04\x88\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00c37274750c94e96532bfeaad0bd4bfd815bef36a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
INFO:eufy_security.p2p.session:Connection closed
Do you still want the a new tcpdump?
Nope, from the output it looks like it ran successfully. It should have momentarily turned on the on screen watermark (the Eufy logo in the top left) of the live video feed for a couple seconds and then turned it off. Can you confirm that actually happens? Also, to clarify, do you have a wired or wireless doorbell?
The watermark is successfully added and removed in the video. Also when I look at the app I see the watermark toggle is on, and later is off. I have the Battery video doorbell set which is wired for power and the base station is also wired to ethernet. The doorbell itself communicates wireless to the base station. So it's both wireless and wired ;)
https://www.coolblue.nl/product/857838/eufy-by-anker-video-doorbell-battery-set.html#product-specifications
So I think you're getting around the NAT issues that @nonsleepr might be hitting since you’re accessing your device over LAN
I'm trying to connect over internet and not getting the response from the doorbell (I explained the reason above). (my own implementation using single connection works, BTW, I'll see if I can release that).
As for the LAN connection, the discovery piece is not needed at all. You could simply broadcast \xf1\x30\x00\x00 to port 32108 to locate the doorbell (not sure about other cameras).
@keshavdv and @nonsleepr u guys gave up on this ? Or can I still check out this branch and give it a shot ?