Skip to content

Commit

Permalink
Merge pull request #31 from krahabb/dev
Browse files Browse the repository at this point in the history
Refining Rebirth
  • Loading branch information
krahabb authored Jul 2, 2021
2 parents c4f4c41 + 4e526e2 commit 7b34681
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 67 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ venv
.venv
.coverage
*.secret
*.user
*.user
traces
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ Most of this software has been developed and tested on my owned Meross devices w

- Switches
- [MSS110](https://www.meross.com/product/2/article/): Smart Wifi plug mini
- [MSS210](https://www.meross.com/Detail/3/Smart%20Wi-Fi%20Plug): Smart Wifi plug
- [MSS310](https://www.meross.com/product/38/article/): power plug with metering capabilties
- [MSS425](https://www.meross.com/product/16/article/): Smart WiFi Surge Protector (multiple sockets power strip)
- [MSS510](https://www.meross.com/product/23/article/): Smart WiFi single pole switch
Expand All @@ -64,7 +65,7 @@ Most of this software has been developed and tested on my owned Meross devices w
- [MTS100](https://www.meross.com/Detail/30/Smart%20Thermostat%20Valve): Smart Thermostat Valve
- Covers
- Support for garage door opener and roller shutter is implemented by guess-work so I'm not expecting flawless behaviour but...could work

- [MSG100](https://www.meross.com/product/29/article/): Smart Wi-Fi Garage Door Opener

## Features

Expand All @@ -77,7 +78,7 @@ I'm sorry to not be able to write a complete wiki at the moment in order to bett

## Service

There is a service (since version 0.0.4) exposed to simplify communication with the device and play with it a bit. It basically requires the needed informations to setup a command request and send it over MQTT or HTTP without the hassle of signatures and timestamps computations. You can check it in the 'Developer Tools' of the HA instance, everything should be enough self-explanatory there.
There is a service (since version 0.0.4) exposed to simplify communication with the device and play with it a bit. It basically requires the needed informations to setup a command request and send it over MQTT or HTTP without the hassle of signatures and timestamps computations. You can check it in the 'Developer Tools' of the HA instance, everything should be enough self-explanatory there.
I find it a bit frustrating that the HA service infrastructure does not allow to return anything from a service invocation so, the eventual reply from the device will get 'lost' in the mqtt flow. I've personally played a bit with the MQTT integration configuration pane to listen and see the mqtt responses from my devices but it's somewhat a pain unless you have a big screen to play with (or multiple monitors for the matter). Nevertheless you can use the service wherever you like to maybe invoke features at the device level or dig into it's configuration
*WARNING*: the service name has changed from 'mqtt_publish' to 'request' to accomodate the more general protocol support

Expand Down
31 changes: 25 additions & 6 deletions custom_components/meross_lan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

from .const import (
DOMAIN, SERVICE_REQUEST,
CONF_HOST, CONF_PROTOCOL, CONF_OPTION_HTTP,
CONF_HOST, CONF_PROTOCOL, CONF_OPTION_HTTP, CONF_OPTION_MQTT,
CONF_DEVICE_ID, CONF_KEY, CONF_PAYLOAD,
CONF_POLLING_PERIOD_DEFAULT,
PARAM_UNAVAILABILITY_TIMEOUT,
Expand All @@ -54,13 +54,28 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):

device_id = entry.data.get(CONF_DEVICE_ID)
if (api.unsub_mqtt is None) and \
(api.mqtt_subscribing is False) and \
((device_id is None) or (entry.data.get(CONF_PROTOCOL) != CONF_OPTION_HTTP)):
# this is the MQTT Hub entry or a device which needs MQTT
# and we still havent registered MQTT
"""
this is the MQTT Hub entry or a device which could/should use MQTT
and we still havent registered MQTT
"""
api.mqtt_subscribing = True # guard ON
try:
await api.async_mqtt_register()
except Exception as e:
raise ConfigEntryNotReady from e
except Exception:
pass
api.mqtt_subscribing = False

"""
this is a hell of race conditions: the previous mqtt_register could be overlapping (awaited)
because of a different ConfigEntry request (where CONF_PROTOCOL != HTTP)
here we need to be sure to delay load this entry until mqtt is in place (at least for those
directly requiring MQTT)
"""
if (device_id is None) or (entry.data.get(CONF_PROTOCOL) == CONF_OPTION_MQTT):
if api.unsub_mqtt is None:
raise ConfigEntryNotReady

if device_id is None:
# this is the MQTT Hub entry
Expand All @@ -72,7 +87,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
device = api.build_device(device_id, entry)
device.unsub_entry_update_listener = entry.add_update_listener(device.entry_update_listener)
device.unsub_updatecoordinator_listener = api.coordinator.async_add_listener(device.updatecoordinator_listener)
hass.config_entries.async_setup_platforms(entry, device.platforms.keys())
# this api is too recent (around April 2021): hass.config_entries.async_setup_platforms(entry, device.platforms.keys())
for platform in device.platforms.keys():
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, platform))


return True

Expand Down Expand Up @@ -120,6 +138,7 @@ def __init__(self, hass: HomeAssistant):
self.key = None
self.devices: Dict[str, MerossDevice] = {}
self.discovering: Dict[str, dict] = {}
self.mqtt_subscribing = False # guard for asynchronous mqtt sub registration
self.unsub_mqtt = None
self.unsub_entry_update_listener = None
self.unsub_updatecoordinator_listener = None
Expand Down
12 changes: 11 additions & 1 deletion custom_components/meross_lan/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Config flow for Meross IoT local LAN integration."""

from time import time
from homeassistant.components.mqtt import DATA_MQTT
import voluptuous as vol
from typing import OrderedDict, Optional
from typing import OrderedDict
import json

from homeassistant import config_entries
Expand All @@ -19,6 +20,7 @@
CONF_PAYLOAD, CONF_DEVICE_TYPE,
CONF_PROTOCOL, CONF_PROTOCOL_OPTIONS,
CONF_POLLING_PERIOD, CONF_POLLING_PERIOD_DEFAULT,
CONF_TRACE, CONF_TRACE_TIMEOUT,
)


Expand Down Expand Up @@ -211,6 +213,7 @@ async def async_step_device(self, user_input=None):
data[CONF_KEY] = user_input.get(CONF_KEY)
data[CONF_PROTOCOL] = user_input.get(CONF_PROTOCOL)
data[CONF_POLLING_PERIOD] = user_input.get(CONF_POLLING_PERIOD)
data[CONF_TRACE] = time() + CONF_TRACE_TIMEOUT if user_input.get(CONF_TRACE) else 0
self.hass.config_entries.async_update_entry(self._config_entry, data=data)
return self.async_create_entry(title=None, data=None)

Expand All @@ -234,6 +237,13 @@ async def async_step_device(self, user_input=None):
description={"suggested_value": data.get(CONF_POLLING_PERIOD)}
)
] = cv.positive_int
config_schema[
vol.Optional(
CONF_TRACE,
# CONF_TRACE contains the trace 'end' time epoch if set
description={"suggested_value": data.get(CONF_TRACE, 0) > time()}
)
] = bool

descriptor = MerossDeviceDescriptor(data.get(CONF_PAYLOAD, {}))
return self.async_show_form(
Expand Down
15 changes: 13 additions & 2 deletions custom_components/meross_lan/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
CONF_PAYLOAD = hac.CONF_PAYLOAD
CONF_DEVICE_TYPE = "device_type"
CONF_HOST = hac.CONF_HOST

CONF_PROTOCOL = hac.CONF_PROTOCOL # protocol used to communicate with device
CONF_OPTION_AUTO = 'auto'
CONF_OPTION_MQTT = 'mqtt'
Expand All @@ -29,10 +30,19 @@
CONF_OPTION_MQTT,
CONF_OPTION_HTTP
)

CONF_POLLING_PERIOD = 'polling_period' # general device state polling or whatever
CONF_POLLING_PERIOD_MIN = 5
CONF_POLLING_PERIOD_DEFAULT = 30
CONF_TIME_ZONE = hac.CONF_TIME_ZONE # if set in config we'll force time & zone for devices

CONF_TRACE = 'trace' # create a file with device info and communication tracing (only CONF_TRACE_TIMEOUT seconds then shut off)
CONF_TRACE_TIMEOUT = 600 # when starting a trace stop it and close the file after .. secs
CONF_TRACE_MAXSIZE = 65536 # or when MAXSIZE exceeded
CONF_TRACE_DIRECTORY = 'traces' # folder where to store traces
CONF_TRACE_FILENAME = '{}-{}.csv' # filename format: device_type-device_id.csv

CONF_TIME_ZONE = hac.CONF_TIME_ZONE # TODO: if set in config we'll force time & zone for devices

CONF_TIMESTAMP = mc.KEY_TIMESTAMP # this is a 'fake' conf param we'll add to config_entry when we want to force flush to storage

"""
Expand All @@ -44,4 +54,5 @@
PARAM_HUBBATTERY_UPDATE_PERIOD = 3595 # read battery levels only every ... second
PARAM_HUBSENSOR_UPDATE_PERIOD = 55
#PARAM_STALE_DEVICE_REMOVE_TIMEOUT = 60 # disable config_entry when device is offline for more than...

PARAM_GARAGEDOOR_TRANSITION_MAXDURATION = 30
PARAM_GARAGEDOOR_TRANSITION_MINDURATION = 10
Loading

0 comments on commit 7b34681

Please sign in to comment.