Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #17

Merged
merged 7 commits into from
Oct 24, 2023
Merged

Dev #17

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
95 changes: 79 additions & 16 deletions myFox2Mqtt/business/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def ha_devices_config(
other_devices = api.get_devices_other(site_id=site_id)
camera_devices = api.get_devices_camera(site_id=site_id)
shutter_devices = api.get_devices_shutter(site_id=site_id)
gate_devices = api.get_devices_gate(site_id=site_id)
socket_devices = api.get_devices_socket(site_id=site_id)

for device in my_devices:
Expand Down Expand Up @@ -229,6 +230,40 @@ def ha_devices_config(
retain=True,
)

# State
for state_device in state_devices:
if state_device.get("deviceId") == device.device_id:
LOGGER.info(f"Found State for {device.device_id}: {state_device.get('stateLabel')}")
state = ha_discovery_devices(
site_id=site_id,
device=device,
mqtt_config=mqtt_config,
sensor_name="stateLabel",
)
mqtt_publish(
mqtt_client=mqtt_client,
topic=state.get("topic"),
payload=state.get("config"),
retain=True,
)

# Light
for light_device in light_devices:
if light_device.get("deviceId") == device.device_id:
LOGGER.info(f"Found Light for {device.device_id}: {light_device.get('light')}")
light = ha_discovery_devices(
site_id=site_id,
device=device,
mqtt_config=mqtt_config,
sensor_name="light",
)
mqtt_publish(
mqtt_client=mqtt_client,
topic=light.get("topic"),
payload=light.get("config"),
retain=True,
)

# Smoke
for other_device in other_devices:
if other_device.get("deviceId") == device.device_id:
Expand Down Expand Up @@ -264,6 +299,24 @@ def ha_devices_config(
)
mqtt_client.client.subscribe(shutter.get("config").get("command_topic"))

# Gate
for gate_device in gate_devices:
if gate_device.get("deviceId") == device.device_id:
LOGGER.info(f"Found Gate for {device.device_id}: {gate_device.get('label')}")
gate = ha_discovery_devices(
site_id=site_id,
device=device,
mqtt_config=mqtt_config,
sensor_name="gate",
)
mqtt_publish(
mqtt_client=mqtt_client,
topic=gate.get("topic"),
payload=gate.get("config"),
retain=True,
)
mqtt_client.client.subscribe(gate.get("config").get("command_topic"))

# Sockets
for socket_device in socket_devices:
if socket_device.get("deviceId") == device.device_id:
Expand Down Expand Up @@ -331,20 +384,22 @@ def update_sites_status(
payload = {}
events = api.get_site_history(site_id=site_id)
for event in events:
# Only Push last Event
if event:
created_at = event.get("createdAt")
date_format = "%Y-%m-%dT%H:%M:%SZ"
created_at_date = datetime.strptime(created_at, date_format)
now = datetime.now()
if now - created_at_date < timedelta(seconds=70):
payload = f"{event.get('type')} {event.get('createdAt')} {event.get('label')}"
# Push status to MQTT
mqtt_publish(
mqtt_client=mqtt_client,
topic=f"{mqtt_config.get('topic_prefix', 'myFox2mqtt')}/{site_id}/history",
payload=payload,
retain=True,
)
# created_at = event.get("createdAt")
# date_format = "%Y-%m-%dT%H:%M:%SZ"
# created_at_date = datetime.strptime(created_at, date_format)
# now = datetime.now()
# if now - created_at_date < timedelta(seconds=70):
payload = f"{event.get('type')} {event.get('createdAt')} {event.get('label')}"
# Push status to MQTT
mqtt_publish(
mqtt_client=mqtt_client,
topic=f"{mqtt_config.get('topic_prefix', 'myFox2mqtt')}/{site_id}/history",
payload=payload,
retain=True,
)
break

except Exception as exp:
LOGGER.warning(f"Error while getting site history: {exp}")
Expand Down Expand Up @@ -377,11 +432,9 @@ def update_devices_status(
try:
my_devices = api.get_devices(site_id=site_id)
temperature_devices = api.get_devices_temperature(site_id=site_id)
other_devices = api.get_devices_other(site_id=site_id)
light_devices = api.get_devices_light(site_id=site_id)
state_devices = api.get_devices_state(site_id=site_id)
other_devices = api.get_devices_other(site_id=site_id)
camera_devices = api.get_devices_camera(site_id=site_id)
scenarios = api.get_scenarios(site_id=site_id)

for device in my_devices:
settings = device.settings
Expand All @@ -405,6 +458,16 @@ def update_devices_status(
if temperature_device.get("deviceId") == device.device_id:
keys_values["lastTemperature"] = temperature_device.get("lastTemperature")

# Light
for light_device in light_devices:
if light_device.get("deviceId") == device.device_id:
keys_values["light"] = int(light_device.get("light"))

# State
for state_device in state_devices:
if state_device.get("deviceId") == device.device_id:
keys_values["stateLabel"] = state_device.get("stateLabel")

# Smoke
for other_device in other_devices:
if other_device.get("deviceId") == device.device_id:
Expand Down
2 changes: 1 addition & 1 deletion myFox2Mqtt/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ version: "3"
services:
myfox2mqtt:
build: .
image: myfox2mqtt:v2023.10.1
image: myfox2mqtt:v2023.10.2
volumes:
- ./config:/config
28 changes: 19 additions & 9 deletions myFox2Mqtt/homeassistant/ha_discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@
},
"shutter": {
"type": "cover",
"config": {"pl_open": "open", "pl_close": "close", "pl_stop": "my", "optimistic": "true"},
"config": {"pl_open": "open", "pl_cls": "close", "pl_stop": "my", "optimistic": "true"},
},
"gate": {
"type": "cover",
"config": {"pl_open": "one", "pl_cls": "two", "optimistic": "true", "device_class": "gate"},
},
"socket": {
"type": "switch",
Expand Down Expand Up @@ -112,6 +116,13 @@
"unit_of_measurement": "°C",
},
},
"light": {
"type": "sensor",
"config": {
"device_class": "illuminance",
"unit_of_measurement": "lx",
},
},
"battery_level": {
"type": "sensor",
"config": {
Expand All @@ -127,6 +138,13 @@
"pl_off": "False",
},
},
"stateLabel": {
"type": "binary_sensor",
"config": {
"pl_on": "opened",
"pl_off": "closed",
},
},
"state": {
"type": "binary_sensor",
"config": {
Expand Down Expand Up @@ -423,14 +441,6 @@
"type": "button",
"config": {"payload_press": "halt"},
},
"gate": {
"type": "switch",
"config": {
"pl_on": "gate_open",
"pl_off": "gate_close",
"optimistic": "True",
},
},
"garage": {
"type": "switch",
"config": {
Expand Down
65 changes: 18 additions & 47 deletions myFox2Mqtt/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import argparse
import logging
import threading
from functools import partial
from signal import SIGINT, SIGTERM, signal
import time

from exceptions import MyFoxInitError
Expand All @@ -13,9 +11,8 @@
from mqtt import init_mqtt
from myfox.sso import init_sso
from myfox.api import MyFoxApi
from myfox.websocket import MyFoxWebsocket

VERSION = "2023.10.1"
VERSION = "2023.10.2"


def myfox_loop(config, mqtt_client, api):
Expand All @@ -29,16 +26,6 @@ def myfox_loop(config, mqtt_client, api):
close_and_exit(myfox_api, 3)


def myfox_wss_loop(sso, debug, config, mqtt_client, api):
"""MyFox WSS Loop"""
try:
wss = MyFoxWebsocket(sso=sso, debug=debug, config=config, mqtt_client=mqtt_client, api=api)
wss.run_forever()
except Exception as exc:
LOGGER.error(f"Force stopping WebSocket {exc}")
close_and_exit(wss, 3)


if __name__ == "__main__":
# Read Arguments
PARSER = argparse.ArgumentParser()
Expand All @@ -59,12 +46,6 @@ def myfox_wss_loop(sso, debug, config, mqtt_client, api):
API = MyFoxApi(sso=SSO)
MQTT_CLIENT = init_mqtt(config=CONFIG, api=API)

# Trigger Ctrl-C
signal(SIGINT, partial(close_and_exit, MyFox2Mqtt, 0))
signal(SIGTERM, partial(close_and_exit, MyFox2Mqtt, 0))
signal(SIGINT, partial(close_and_exit, MyFoxWebsocket, 0))
signal(SIGTERM, partial(close_and_exit, MyFoxWebsocket, 0))

try:
p1 = threading.Thread(
target=myfox_loop,
Expand All @@ -74,33 +55,23 @@ def myfox_wss_loop(sso, debug, config, mqtt_client, api):
API,
),
)
# p2 = threading.Thread(
# target=myfox_wss_loop,
# args=(
# SSO,
# DEBUG,
# CONFIG,
# MQTT_CLIENT,
# API,
# ),
# )

p1.start()
# p2.start()
# p2.join()
# while True:
# if not p2.is_alive():
# p2 = threading.Thread(
# target=myfox_wss_loop,
# args=(
# SSO,
# DEBUG,
# CONFIG,
# MQTT_CLIENT,
# API,
# ),
# )
# p2.start()
# p2.join()

while True:
if not p1.is_alive():
LOGGER.warning("API is DEAD, restarting")
p1 = threading.Thread(
target=myfox_loop,
args=(
CONFIG,
MQTT_CLIENT,
API,
),
)
p1.start()

time.sleep(1)

except Exception as exp:
LOGGER.error(f"Force stopping application {exp}")
# close_and_exit(MYFOX, 3)
46 changes: 45 additions & 1 deletion myFox2Mqtt/myfox/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ def get_device_light(self, site_id: str, device_id: str):
"""
response = self.get(f"/v2/site/{site_id}/device/{device_id}/data/light/")
response.raise_for_status()
LOGGER.info(f"Device: {response.json()}")
LOGGER.info(f"Light: {response.json()}")
return response.json()

def get_devices_other(
Expand Down Expand Up @@ -630,6 +630,50 @@ def shutter_action_device(
response.raise_for_status()
return response.json()

def get_devices_gate(self, site_id: str):
"""Get Devices Gate from a Site ID

Args:
site_id (Optional[str], optional): Site ID. Defaults to None.

Returns:
List[Device]: List of Device object
"""
response = self.get(f"/v2/site/{site_id}/device/gate/items")
try:
content = response.json()
except JSONDecodeError:
response.raise_for_status()
LOGGER.info(f"Devices Gate: {response.json()}")
return content.get("payload").get("items")

def gate_action_device(
self,
site_id: str,
device_id: str,
action: str,
) -> Dict:
"""Make an action on a Gate

Args:
site_id (str): Site ID
device_id (str): Device ID
action (str): Action

Returns:
str: Task ID
"""
if action not in ["one", "two"]:
raise ValueError(f"Unknown action {action}")

response = self.post(
f"/v2/site/{site_id}/device/{device_id}/gate/perform/{action}",
json={},
)
LOGGER.info(f"Gate Action: {response.status_code} => {response.text}")
response.raise_for_status()
return response.json()

def get_devices_socket(self, site_id: str):
"""Get Devices Socket from a Site ID

Expand Down
Loading