Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions hatasmota/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
OPTION_BUTTON_SINGLE,
OPTION_BUTTON_SWAP,
OPTION_MQTT_BUTTONS,
RSLT_ACTION,
)
from .trigger import TasmotaTrigger
from .utils import get_state_button_trigger, get_topic_stat_button_trigger
from .utils import get_topic_stat_result, get_value_by_path

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -124,7 +125,7 @@ def from_discovery_message(cls, config, idx):
idx=idx,
source="button",
subtype=f"button_{idx+1}",
trigger_topic=get_topic_stat_button_trigger(config, idx),
trigger_topic=get_topic_stat_result(config),
type=trigger_type,
)
)
Expand All @@ -146,6 +147,6 @@ class TasmotaButtonTrigger(TasmotaTrigger):

def _trig_message_received(self, msg):
"""Handle new MQTT messages."""
event = get_state_button_trigger(msg.payload)
event = get_value_by_path(msg.payload, [f"Button{self.cfg.idx+1}", RSLT_ACTION])
if event == self.cfg.event:
self._on_trigger_callback()
7 changes: 5 additions & 2 deletions hatasmota/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
CONF_DEVICENAME = "dn"
CONF_FRIENDLYNAME = "fn"
CONF_FULLTOPIC = "ft"
CONF_IFAN = "if"
CONF_IP = "ip"
CONF_HOSTNAME = "hn"
CONF_MAC = "mac"
Expand All @@ -31,6 +32,7 @@
CONF_RELAY = "rl"
CONF_SW_VERSION = "sw"
CONF_SWITCH = "swc"
CONF_SWITCHNAME = "swn"
CONF_TOPIC = "t"
CONF_TUYA = "ty"
CONF_VERSION = "ver"
Expand All @@ -46,15 +48,16 @@
LST_RGBCW = 5

# fmt: off
OPTION_MQTT_RESPONSE = "4" # Return MQTT response as RESULT or %COMMAND%
OPTION_BUTTON_SWAP = "11" # Swap button single and double press functionality
OPTION_BUTTON_SINGLE = "13" # Allow immediate action on single button press
OPTION_DECIMAL_TEXT = "17" # Show Color string as hex or comma-separated
OPTION_NOT_POWER_LINKED = "20" # Update of Dimmer/Color/CT without turning power on
OPTION_HASS_LIGHT = "30" # Enforce Home Assistant auto-discovery as light
OPTION_PWM_MULTI_CHANNELS = "68" # Multi-channel PWM instead of a single light
OPTION_MQTT_BUTTONS = "73" # Enable Buttons decoupling and send multi-press and hold MQTT messages
OPTION_SHUTTER_MODE = "80" # Blinds and shutters support
OPTION_REDUCED_CT_RANGE = "82" # Reduce the CT range from 153..500 to 200.380
OPTION_MQTT_SWITCHES = "114" # Enable sending switch MQTT messages
# fmt: on

PREFIX_CMND = 0
Expand All @@ -66,7 +69,7 @@
RL_LIGHT = 2
RL_SHUTTER = 3

RSLT_ACTION = "ACTION"
RSLT_ACTION = "Action"
RSLT_POWER = "POWER"
RSLT_STATE = "STATE"
RSLT_TRIG = "TRIG"
Expand Down
10 changes: 8 additions & 2 deletions hatasmota/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
CONF_FRIENDLYNAME,
CONF_FULLTOPIC,
CONF_HOSTNAME,
CONF_IFAN,
CONF_IP,
CONF_LIGHT_SUBTYPE,
CONF_LINK_RGB_CT,
Expand All @@ -28,6 +29,7 @@
CONF_STATE,
CONF_SW_VERSION,
CONF_SWITCH,
CONF_SWITCHNAME,
CONF_TOPIC,
CONF_TUYA,
CONF_VERSION,
Expand All @@ -36,10 +38,11 @@
OPTION_DECIMAL_TEXT,
OPTION_HASS_LIGHT,
OPTION_MQTT_BUTTONS,
OPTION_MQTT_RESPONSE,
OPTION_MQTT_SWITCHES,
OPTION_NOT_POWER_LINKED,
OPTION_PWM_MULTI_CHANNELS,
OPTION_REDUCED_CT_RANGE,
OPTION_SHUTTER_MODE,
RL_LIGHT,
RL_RELAY,
)
Expand All @@ -57,15 +60,16 @@

TASMOTA_OPTIONS_SCHEMA = vol.Schema(
{
OPTION_MQTT_RESPONSE: cv.bit,
OPTION_BUTTON_SWAP: cv.bit,
OPTION_BUTTON_SINGLE: cv.bit,
OPTION_DECIMAL_TEXT: cv.bit,
OPTION_NOT_POWER_LINKED: cv.bit,
OPTION_HASS_LIGHT: cv.bit,
OPTION_PWM_MULTI_CHANNELS: cv.bit,
OPTION_MQTT_BUTTONS: cv.bit,
OPTION_SHUTTER_MODE: cv.bit,
OPTION_REDUCED_CT_RANGE: cv.bit,
OPTION_MQTT_SWITCHES: cv.bit,
},
required=True,
)
Expand All @@ -77,6 +81,7 @@
CONF_FRIENDLYNAME: vol.All(cv.ensure_list, [cv.optional_string]),
CONF_FULLTOPIC: cv.string,
CONF_HOSTNAME: cv.string,
CONF_IFAN: cv.bit,
CONF_IP: cv.string,
CONF_LIGHT_SUBTYPE: cv.positive_int,
CONF_LINK_RGB_CT: cv.bit,
Expand All @@ -89,6 +94,7 @@
CONF_STATE: vol.All(cv.ensure_list, [cv.string]),
CONF_SW_VERSION: cv.string,
CONF_SWITCH: vol.All(cv.ensure_list, [int]),
CONF_SWITCHNAME: vol.All(cv.ensure_list, [cv.optional_string]),
CONF_RELAY: vol.All(cv.ensure_list, [cv.positive_int]),
CONF_TOPIC: cv.string,
CONF_TUYA: cv.bit,
Expand Down
33 changes: 17 additions & 16 deletions hatasmota/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
CONF_MAC,
CONF_STATE,
CONF_SWITCH,
SENSOR_SWITCH,
RSLT_ACTION,
STATE_HOLD,
STATE_TOGGLE,
STATUS_SENSOR,
Expand Down Expand Up @@ -41,12 +41,10 @@
config_get_state_online,
config_get_state_power_off,
config_get_state_power_on,
get_state_state,
get_state_switch_trigger,
config_get_switchname,
get_topic_command_status,
get_topic_stat_result,
get_topic_stat_status,
get_topic_stat_switch,
get_topic_stat_switch_trigger,
get_topic_tele_sensor,
get_topic_tele_will,
get_value_by_path,
Expand Down Expand Up @@ -175,6 +173,7 @@ class TasmotaSwitchTriggerConfig:
mac: str = attr.ib()
source: str = attr.ib()
subtype: str = attr.ib()
switchname: str = attr.ib()
trigger_topic: str = attr.ib()
type: str = attr.ib()

Expand All @@ -192,7 +191,8 @@ def from_discovery_message(cls, config, idx):
idx=idx,
source="switch",
subtype=f"switch_{idx+1}",
trigger_topic=get_topic_stat_switch_trigger(config, idx),
switchname=config_get_switchname(config, idx),
trigger_topic=get_topic_stat_result(config),
type=trigger_type,
)
)
Expand All @@ -214,7 +214,7 @@ class TasmotaSwitchTrigger(TasmotaTrigger):

def _trig_message_received(self, msg):
"""Handle new MQTT messages."""
event = get_state_switch_trigger(msg.payload)
event = get_value_by_path(msg.payload, [self.cfg.switchname, RSLT_ACTION])
if event == self.cfg.event:
self._on_trigger_callback()

Expand All @@ -225,13 +225,12 @@ class TasmotaSwitchConfig(TasmotaAvailabilityConfig, TasmotaEntityConfig):

off_delay: int = attr.ib()
poll_topic: str = attr.ib()
sensor: str = attr.ib()
state_power_off: str = attr.ib()
state_power_on: str = attr.ib()
state_topic1: str = attr.ib()
state_topic2: str = attr.ib()
state_topic3: str = attr.ib()
# unique_id: str = attr.ib()
switchname: str = attr.ib()

@classmethod
def from_discovery_message(cls, config, idx, platform):
Expand All @@ -253,12 +252,12 @@ def from_discovery_message(cls, config, idx, platform):
availability_offline=config_get_state_offline(config),
availability_online=config_get_state_online(config),
off_delay=off_delay,
sensor=SENSOR_SWITCH + f"{idx+1}",
state_power_off=config_get_state_power_off(config),
state_power_on=config_get_state_power_on(config),
state_topic1=get_topic_stat_switch(config, idx),
state_topic1=get_topic_stat_result(config),
state_topic2=get_topic_tele_sensor(config),
state_topic3=get_topic_stat_status(config, 8),
switchname=config_get_switchname(config, idx),
)


Expand All @@ -276,24 +275,26 @@ async def subscribe_topics(self):
def state_message_received(msg):
"""Handle new MQTT state messages."""
state = None
# tasmota_0848A2/stat/SWITCH1 / {"STATE":"OFF"}
# tasmota_0848A2/stat/RESULT / {"Switch1":{"Action":"ON"}}
if msg.topic == self._cfg.state_topic1:
state = get_state_state(msg.payload)
state = get_value_by_path(
msg.payload, [self._cfg.switchname, RSLT_ACTION]
)
# tasmota_0848A2/tele/SENSOR / {"Time":"2020-09-20T09:41:28","Switch1":"ON"}
if msg.topic == self._cfg.state_topic2:
state = get_value_by_path(msg.payload, [self._cfg.sensor])
state = get_value_by_path(msg.payload, [self._cfg.switchname])
# tasmota_0848A2/stat/STATUS8 / {"StatusSNS":{"Time":"2020-09-20T09:41:00","Switch1":"ON"}}
if msg.topic == self._cfg.state_topic3:
state = get_value_by_path(
msg.payload, [STATUS_SENSOR, self._cfg.sensor]
msg.payload, [STATUS_SENSOR, self._cfg.switchname]
)
if state == self._cfg.state_power_on:
self._on_state_callback(True)
elif state == self._cfg.state_power_off:
self._on_state_callback(False)

availability_topics = self.get_availability_topics()
# tasmota_0848A2/stat/SWITCH1 / {"STATE":"OFF"}
# tasmota_0848A2/stat/RESULT / {"Switch1":{"Action":"ON"}}
# tasmota_0848A2/tele/SENSOR / {"Time":"2020-09-20T09:41:28","Switch1":"ON"}
# tasmota_0848A2/stat/STATUS8 / {"StatusSNS":{"Time":"2020-09-20T09:41:00","Switch1":"ON"}}
topics = {
Expand Down
20 changes: 12 additions & 8 deletions hatasmota/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
CONF_PREFIX,
CONF_RELAY,
CONF_STATE,
CONF_SWITCHNAME,
CONF_TOPIC,
PREFIX_CMND,
PREFIX_STAT,
PREFIX_TELE,
RSLT_ACTION,
RSLT_POWER,
RSLT_STATE,
RSLT_TRIG,
STATE_OFF,
STATE_ON,
)
Expand Down Expand Up @@ -85,7 +85,7 @@ def get_topic_command_status(config):

def get_topic_stat_button_trigger(config, idx):
"""Get topic for tele state."""
return _get_topic_stat(config) + f"BUTTON{idx+1}T"
return _get_topic_stat(config) + f"BUTTON{idx+1}"


def get_topic_stat_result(config):
Expand All @@ -107,7 +107,7 @@ def get_topic_stat_switch(config, idx):

def get_topic_stat_switch_trigger(config, idx):
"""Get topic for tele state."""
return _get_topic_stat(config) + f"SWITCH{idx+1}T"
return _get_topic_stat(config) + f"SWITCH{idx+1}"


def get_topic_tele_sensor(config):
Expand Down Expand Up @@ -185,11 +185,6 @@ def get_state_button_trigger(status):
return get_value(status, RSLT_ACTION)


def get_state_switch_trigger(status):
"""Get state of switch."""
return get_value(status, RSLT_TRIG)


def config_get_friendlyname(config, platform, idx):
"""Get config friendly name."""
friendly_names = config[CONF_FRIENDLYNAME]
Expand All @@ -204,6 +199,15 @@ def config_get_friendlyname(config, platform, idx):
return friendly_names[idx]


def config_get_switchname(config, idx):
"""Get switch name."""
switch_names = config[CONF_SWITCHNAME]

if idx >= len(switch_names) or switch_names[idx] is None:
return f"Switch{idx+1}"
return switch_names[idx]


TOPIC_MATCHER = re.compile(r"^(?P<mac>[A-Z0-9_-]+)\/(?:config|sensors)$")


Expand Down