Skip to content

Commit b71573d

Browse files
authored
VTO buffer and keepalive fix (#301)
* Buffer asyncio data_received * Remove keep_alive handler after response is received * Added DHI-VTO3311Q-WP to supported devices
1 parent 321a576 commit b71573d

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ Brand | 2 Megapixels | 4 Megapixels | 5 Megapixels | 8 Megapixels
118118
| *Dahua* |
119119
| | DHI-VTO2202F-P |
120120
| | DHI-VTO2211G-P |
121+
| | DHI-VTO3311Q-WP |
121122
| *IMOU* |
122123
| | IMOU C26EP-V2 |
123124

custom_components/dahua/vto.py

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class DahuaVTOClient(asyncio.Protocol):
5353
lock_status: {}
5454
auth: HTTPDigestAuth
5555
data_handlers: {}
56+
buffer: bytearray
5657

5758
def __init__(self, host: str, username: str, password: str, is_ssl: bool, on_receive_vto_event):
5859
self.dahua_details = {}
@@ -71,6 +72,7 @@ def __init__(self, host: str, username: str, password: str, is_ssl: bool, on_rec
7172
self.hold_time = 0
7273
self.lock_status = {}
7374
self.data_handlers = {}
75+
self.buffer = bytearray()
7476

7577
# This is the hook back into HA
7678
self.on_receive_vto_event = on_receive_vto_event
@@ -90,17 +92,26 @@ def connection_made(self, transport):
9092

9193
def data_received(self, data):
9294
_LOGGER.debug(f"Event data {self.host}: '{data}'")
93-
try:
94-
messages = self.parse_response(data)
95-
for message in messages:
96-
message_id = message.get("id")
9795

98-
handler: Callable = self.data_handlers.get(message_id, self.handle_default)
99-
handler(message)
100-
except Exception as ex:
101-
exc_type, exc_obj, exc_tb = sys.exc_info()
96+
self.buffer += data
10297

103-
_LOGGER.error(f"Failed to handle message, error: {ex}, Line: {exc_tb.tb_lineno}")
98+
while b'\n' in self.buffer:
99+
100+
newline_index = self.buffer.find(b'\n') + 1
101+
packet = self.buffer[:newline_index]
102+
self.buffer = self.buffer[newline_index:]
103+
104+
try:
105+
messages = self.parse_response(packet)
106+
for message in messages:
107+
message_id = message.get("id")
108+
109+
handler: Callable = self.data_handlers.get(message_id, self.handle_default)
110+
handler(message)
111+
except Exception as ex:
112+
exc_type, exc_obj, exc_tb = sys.exc_info()
113+
114+
_LOGGER.error(f"Failed to handle message, error: {ex}, Line: {exc_tb.tb_lineno}")
104115

105116
def handle_notify_event_stream(self, params):
106117
try:
@@ -326,6 +337,12 @@ def keep_alive(self):
326337
def handle_keep_alive(message):
327338
Timer(self.keep_alive_interval, self.keep_alive).start()
328339

340+
message_id = message.get('id')
341+
if message_id is not None and message_id in self.data_handlers:
342+
del self.data_handlers[message_id]
343+
else:
344+
_LOGGER.warning(f'Could not delete keep alive handler with message ID {message_id}.')
345+
329346
request_data = {
330347
"timeout": self.keep_alive_interval,
331348
"action": True

0 commit comments

Comments
 (0)