Skip to content

Commit

Permalink
Fix #17 error due to unsupported event and log level of invalid matrix
Browse files Browse the repository at this point in the history
  • Loading branch information
elad-bar committed Sep 28, 2021
1 parent 8a701c6 commit 1b26347
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 28 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## 1.1.13

- Fix error due to unsupported event messages [#17](https://github.com/elad-bar/ha-shinobi/issues/17)
- Change message's log level of empty matrices to `DEBUG`

## 1.1.12

- Added support for single camera (response of an object instead of array) [#16](https://github.com/elad-bar/ha-shinobi/issues/16)
Expand Down
95 changes: 69 additions & 26 deletions custom_components/shinobi/api/shinobi_websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from datetime import datetime
import json
import logging
import sys
from typing import Callable, Optional

import aiohttp
Expand Down Expand Up @@ -52,6 +53,12 @@ def __init__(self,
self.is_connected = False
self.api = api
self.is_aborted = False
self._messages_handler: dict = {
SHINOBI_WS_CONNECTION_ESTABLISHED_MESSAGE: self.handle_connection_established_message,
SHINOBI_WS_PONG_MESSAGE: self.handle_pong_message,
SHINOBI_WS_CONNECTION_READY_MESSAGE: self.handle_ready_state_message,
SHINOBI_WS_ACTION_MESSAGE: self.handle_action_message
}

self._handlers = {
"log": self.handle_log,
Expand Down Expand Up @@ -151,7 +158,7 @@ def handle_next_message(self, msg):
else:
self._last_update = datetime.now()

if msg.data == "close":
if msg.data is None or msg.data == "close":
result = False
else:
self.hass.async_create_task(self.parse_message(msg.data))
Expand All @@ -160,42 +167,78 @@ def handle_next_message(self, msg):
return result

async def parse_message(self, message: str):
if message.startswith(SHINOBI_WS_CONNECTION_ESTABLISHED_MESSAGE):
_LOGGER.debug(f"Connected, Message: {message[1:]}")

elif message.startswith(SHINOBI_WS_PONG_MESSAGE):
_LOGGER.debug(f"Pong received")
message_parts = message.split("[")
message_prefix = message_parts[0]

elif message.startswith(SHINOBI_WS_CONNECTION_READY_MESSAGE):
_LOGGER.debug(f"Back channel connected")
await self.send_connect_message()
message_handler = self._messages_handler.get(message_prefix)

elif message.startswith(SHINOBI_WS_ACTION_MESSAGE):
json_str = message[2:]
payload = json.loads(json_str)
await self.parse_payload(payload)
if message_handler is None:
_LOGGER.debug(f"No message handler available, Message: {message}")

else:
_LOGGER.debug(f"No message handler available, Message: {message}")
message_data = message.replace(message_prefix, "")

await message_handler(message_prefix, message_data)

@staticmethod
async def handle_connection_established_message(prefix, data):
_LOGGER.debug(f"WebSocket connection established")

@staticmethod
async def handle_pong_message(prefix, data):
_LOGGER.debug(f"Pong message received")

async def handle_ready_state_message(self, prefix, data):
_LOGGER.debug(f"WebSocket connection state changed to ready")

await self.send_connect_message()

async def handle_action_message(self, prefix, data):
try:
payload = json.loads(data)
action = payload[0]
data = payload[1]

async def parse_payload(self, payload):
action = payload[0]
data = payload[1]
if action == "f":
func = data.get(action)

if action == "f":
func = data.get(action)
if func in self._handlers.keys():
handler: Callable = self._handlers.get(func, None)

if func in self._handlers.keys():
handler: Callable = self._handlers.get(func, None)
if handler is not None:
await handler(data)

if handler is not None:
await handler(data)
else:
_LOGGER.debug(f"Payload received, Type: {func}")

else:
_LOGGER.debug(f"Payload received, Type: {func}")
_LOGGER.debug(f"No payload handler available, Payload: {payload}")

else:
_LOGGER.debug(f"No payload handler available, Payload: {payload}")
except Exception as ex:
exc_type, exc_obj, tb = sys.exc_info()
line_number = tb.tb_lineno

supported_event = False
for key in self._handlers.keys():
if key in data[0:50]:
supported_event = True
break

if supported_event:
_LOGGER.error(f"Failed to parse message, Data: {data}, Error: {ex}, Line: {line_number}")

else:
key = "Unknown"
unsupported_data = str(data[0:50])

if unsupported_data.startswith(TRIGGER_STARTS_WITH):
key_tmp = unsupported_data.replace(TRIGGER_STARTS_WITH, "")
key_arr = key_tmp.split("\"")

if len(key_arr) > 0:
key = key_arr[0]

_LOGGER.debug(f"Ignoring unsupported event message, Key: {key}, Data: {unsupported_data}")

async def handle_log(self, data):
monitor_id = data.get("mid")
Expand Down
2 changes: 2 additions & 0 deletions custom_components/shinobi/helpers/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@
ATTR_CAMERA_DETAILS_FPS: ATTR_FPS
}

TRIGGER_STARTS_WITH = "[\"f\",{\"f\":\""

TRIGGER_PLUG = "plug"
TRIGGER_NAME = "name"
TRIGGER_DETAILS = "details"
Expand Down
5 changes: 4 additions & 1 deletion custom_components/shinobi/managers/event_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def _handle_sensor_event(self, topic, payload):

for trigger_object in trigger_matrices:
if trigger_object is None:
_LOGGER.warning(f"Invalid trigger object, payload: {payload}")
_LOGGER.debug(f"Ignoring empty trigger object")

else:
trigger_tag = trigger_object.get(TRIGGER_DETAILS_MATRICES_TAG)
Expand All @@ -102,6 +102,9 @@ def _handle_sensor_event(self, topic, payload):
TRIGGER_TOPIC: topic
}

if len(trigger_tags) == 0 and sensor_type == REASON_MOTION:
_LOGGER.warning(f"No tags found for the event, Data: {payload}")

previous_data = self.get_state(topic, sensor_type)
previous_state = previous_data.get(TRIGGER_STATE, STATE_OFF)

Expand Down
2 changes: 1 addition & 1 deletion custom_components/shinobi/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"codeowners": ["@elad-bar"],
"requirements": [ ],
"config_flow": true,
"version": "1.1.12",
"version": "1.1.13",
"iot_class": "local_polling"
}

0 comments on commit 1b26347

Please sign in to comment.