Change the way the devices are organized in the plugin

This commit is contained in:
2024-12-09 22:40:40 +01:00
parent 76a4169308
commit 07240a1693

150
plugin.py
View File

@@ -31,6 +31,7 @@
import math import math
import time import time
from datetime import datetime from datetime import datetime
from enum import IntEnum
import requests import requests
import DomoticzEx as Domoticz # type: ignore import DomoticzEx as Domoticz # type: ignore
@@ -69,6 +70,10 @@ HEATZY_MODE_VALUE_INV = {v: k for k, v in HEATZY_MODE_VALUE.items()}
DEFAULT_POOLING = 60 DEFAULT_POOLING = 60
class HeatzyUnit(IntEnum):
CONTROL = 1
SELECTOR = 2
class BasePlugin: class BasePlugin:
"""Class for plugin""" """Class for plugin"""
debug = False debug = False
@@ -114,20 +119,19 @@ class BasePlugin:
self.did = self.get_heatzy_devices() self.did = self.get_heatzy_devices()
# Create the child devices if these do not exist yet # Create the child devices if these do not exist yet
if "Control" not in Devices: for deviceid in self.did:
for did in self.did: if deviceid not in Devices:
unit = self.did[did]["unit"] alias = self.did[deviceid]["alias"]
Domoticz.Unit(Name=f"Heatzy {did} - Control", DeviceID="Control", Unit=unit, TypeName="Switch", Image=9, Used=1).Create() #Control
Domoticz.Unit(Name=f"Heatzy {alias} - Control", DeviceID=deviceid, Unit=HeatzyUnit.CONTROL, TypeName="Switch", Image=9, Used=1).Create()
if "Mode" not in Devices: #Selector switch
options = {"LevelActions": "||", options = {"LevelActions": "||",
"LevelNames": HEATZY_MODE_NAME['OFF'] + "|" + HEATZY_MODE_NAME['FROSTFREE'] + "|" + HEATZY_MODE_NAME['ECONOMY'] + "|" + HEATZY_MODE_NAME['NORMAL'], "LevelNames": HEATZY_MODE_NAME['OFF'] + "|" + HEATZY_MODE_NAME['FROSTFREE'] + "|" + HEATZY_MODE_NAME['ECONOMY'] + "|" + HEATZY_MODE_NAME['NORMAL'],
"LevelOffHidden": "false", #Bug with off mode... "LevelOffHidden": "false", #Bug with off mode...
#"LevelOffHidden": "true",t #"LevelOffHidden": "true",t
"SelectorStyle": "0"} "SelectorStyle": "0"}
for did in self.did: Domoticz.Unit(Name=f"Heatzy {alias} - Mode", DeviceID=deviceid, Unit=HeatzyUnit.SELECTOR,
unit = self.did[did]["unit"]
Domoticz.Unit(Name=f"Heatzy {did} - Mode", DeviceID="Mode", Unit=unit,
TypeName="Selector Switch", Switchtype=18, Image=15, TypeName="Selector Switch", Switchtype=18, Image=15,
Options=options, Used=1).Create() Options=options, Used=1).Create()
@@ -141,10 +145,10 @@ class BasePlugin:
def on_command(self, DeviceID, Unit, Command, Level, Color): #pylint: disable=unused-argument def on_command(self, DeviceID, Unit, Command, Level, Color): #pylint: disable=unused-argument
"""Send a command""" """Send a command"""
if DeviceID == "Control": if Unit == HeatzyUnit.CONTROL:
self.on_off(Unit, Command) self.on_off(DeviceID, Command)
elif DeviceID == "Mode": elif Unit == HeatzyUnit.SELECTOR:
self.set_mode(Unit, Level) self.set_mode(DeviceID, Level)
def on_heartbeat(self): def on_heartbeat(self):
"""Time to heartbeat :)""" """Time to heartbeat :)"""
@@ -157,7 +161,7 @@ class BasePlugin:
#Force refresh token/did #Force refresh token/did
Domoticz.Status("Force refresh token and device id.") Domoticz.Status("Force refresh token and device id.")
self.token = "" self.token = ""
self.did = "" self.did = {}
return return
self.get_mode() self.get_mode()
@@ -212,7 +216,7 @@ class BasePlugin:
Domoticz.Error(f"Cannot get Heatzy Token: {error_message} ({error_code})\n{response}") Domoticz.Error(f"Cannot get Heatzy Token: {error_message} ({error_code})\n{response}")
self.token = "" self.token = ""
self.token_expire_at = 0 self.token_expire_at = 0
self.did = "" self.did = {}
#Decrease retry #Decrease retry
self.retry = self.retry - 1 self.retry = self.retry - 1
@@ -248,10 +252,11 @@ class BasePlugin:
devices = response['devices'] devices = response['devices']
unit = 1 unit = 1
for device in devices: for device in devices:
if "dev_alias" in device and "did" in device: if "dev_alias" in device and "did" in device and "product_key" in device:
product_key = device['product_key']
alias = device['dev_alias'] alias = device['dev_alias']
did = device['did'] did = device['did']
self.did[alias] = {"did":did, "unit":unit, "last_update":0} self.did[product_key] = {"did":did, "alias":alias, "last_update":0}
Domoticz.Status(f"Devide Id from Heatzy API: {alias} - {did}") Domoticz.Status(f"Devide Id from Heatzy API: {alias} - {did}")
unit = unit + 1 unit = unit + 1
@@ -263,7 +268,7 @@ class BasePlugin:
response = "" response = ""
self.token, self.token_expire_at = self.get_token(Parameters["Username"], Parameters["Password"]) self.token, self.token_expire_at = self.get_token(Parameters["Username"], Parameters["Password"])
self.did = self.get_heatzy_devices() #self.did = self.get_heatzy_devices() #Not really needed
if self.retry<0: if self.retry<0:
return "" return ""
@@ -274,10 +279,10 @@ class BasePlugin:
'X-Gizwits-Application-Id': 'c70a66ff039d41b4a220e198b0fcc8b3', 'X-Gizwits-Application-Id': 'c70a66ff039d41b4a220e198b0fcc8b3',
} }
for device_name in self.did: for deviceid in self.did:
device = self.did[device_name] device = self.did[deviceid]
did = device["did"] did = device["did"]
unit = device["unit"] alias = device["alias"]
url = f"https://euapi.gizwits.com/app/devdata/{did}/latest" url = f"https://euapi.gizwits.com/app/devdata/{did}/latest"
try: try:
@@ -308,39 +313,39 @@ class BasePlugin:
if 'attr' in response and 'mode' in response['attr']: if 'attr' in response and 'mode' in response['attr']:
mode = HEATZY_MODE[response['attr']['mode']] mode = HEATZY_MODE[response['attr']['mode']]
Domoticz.Debug(f"Current Heatzy Mode: {HEATZY_MODE_NAME[mode]} ({self.get_name(unit)})") Domoticz.Debug(f"Current Heatzy Mode: {HEATZY_MODE_NAME[mode]} ({alias})")
#Reset retry counter #Reset retry counter
self.retry = self.max_retry self.retry = self.max_retry
if Devices["Mode"].Units[unit].nValue != HEATZY_MODE_VALUE[mode]: if Devices[deviceid].Units[HeatzyUnit.SELECTOR].nValue != HEATZY_MODE_VALUE[mode]:
Domoticz.Status(f"New Heatzy Mode: {HEATZY_MODE_NAME[mode]} ({self.get_name(unit)})") Domoticz.Status(f"New Heatzy Mode: {HEATZY_MODE_NAME[mode]} ({alias})")
Devices["Mode"].Units[unit].nValue = HEATZY_MODE_VALUE[mode] Devices[deviceid].Units[HeatzyUnit.SELECTOR].nValue = HEATZY_MODE_VALUE[mode]
Devices["Mode"].Units[unit].sValue = str(HEATZY_MODE_VALUE[mode]) Devices[deviceid].Units[HeatzyUnit.SELECTOR].sValue = str(HEATZY_MODE_VALUE[mode])
Devices["Mode"].Units[unit].Update() Devices[deviceid].Units[HeatzyUnit.SELECTOR].Update()
if not self.bug: if not self.bug:
if mode == 'OFF' and Devices["Control"].Units[unit].nValue != 0: if mode == 'OFF' and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue != 0:
Devices["Control"].Units[unit].nValue = 0 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 0
Devices["Control"].Units[unit].sValue = "Off" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "Off"
elif mode != 'OFF' and Devices["Control"].Units[unit].nValue == 0: elif mode != 'OFF' and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue == 0:
Devices["Control"].Units[unit].nValue = 1 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 1
Devices["Control"].Units[unit].sValue = "On" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "On"
else: else:
if mode in ('OFF', 'FROSTFREE') and Devices["Control"].Units[unit].nValue != 0: if mode in ('OFF', 'FROSTFREE') and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue != 0:
Devices["Control"].Units[unit].nValue = 0 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 0
Devices["Control"].Units[unit].sValue = "Off" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "Off"
elif mode not in ('OFF', 'FROSTFREE') and Devices["Control"].Units[unit].nValue == 0: elif mode not in ('OFF', 'FROSTFREE') and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue == 0:
Devices["Control"].Units[unit].nValue = 1 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 1
Devices["Control"].Units[unit].sValue = "On" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "On"
Devices["Control"].Units[unit].Update() Devices[deviceid].Units[HeatzyUnit.CONTROL].Update()
else: else:
#Decrease retry #Decrease retry
self.retry = self.retry - 1 self.retry = self.retry - 1
error_code = "Unknown" if 'error_code' not in response else response['error_code'] error_code = "Unknown" if 'error_code' not in response else response['error_code']
error_message = "Unknown" if 'error_message' not in response else response['error_message'] error_message = "Unknown" if 'error_message' not in response else response['error_message']
Domoticz.Error(f"Cannot get Heatzy Mode: {error_message} ({error_code})\n{response}\nToken: {self.token}\nDeviceId: {self.did}") Domoticz.Error(f"Cannot get Heatzy Mode: {error_message} ({error_code})\n{response}\nToken: {self.token}\nDeviceId: {did}")
if error_code == 9004: if error_code == 9004:
#Invalid token #Invalid token
self.token = "" self.token = ""
@@ -348,17 +353,17 @@ class BasePlugin:
elif 'attr' in response and len(response["attr"]) == 0: elif 'attr' in response and len(response["attr"]) == 0:
#attr is empty... #attr is empty...
Domoticz.Status("We force a setMode to try to get the correct mode at the next try...") Domoticz.Status("We force a setMode to try to get the correct mode at the next try...")
self.set_mode(unit, HEATZY_MODE_VALUE['FROSTFREE']) self.set_mode(deviceid, HEATZY_MODE_VALUE['FROSTFREE'])
return "" return ""
# If mode = OFF and bug, then mode = FROSTFREE # If mode = OFF and bug, then mode = FROSTFREE
if self.bug and mode == 'OFF': if self.bug and mode == 'OFF':
Domoticz.Log(f"Switch to FROSTFREE because of the OFF bug...({device})") Domoticz.Log(f"Switch to FROSTFREE because of the OFF bug...({device})")
self.set_mode(unit, HEATZY_MODE_VALUE['FROSTFREE']) self.set_mode(deviceid, HEATZY_MODE_VALUE['FROSTFREE'])
def set_mode(self, unit, mode): def set_mode(self, deviceid, mode):
"Set the device mode using the Heatzy API" "Set the device mode using the Heatzy API"
if Devices["Mode"].Units[unit].nValue != mode: if Devices[deviceid].Units[HeatzyUnit.SELECTOR].nValue != mode:
mode_str = { mode_str = {
HEATZY_MODE_VALUE['NORMAL']: 0, #'[1,1,0]', HEATZY_MODE_VALUE['NORMAL']: 0, #'[1,1,0]',
HEATZY_MODE_VALUE['ECONOMY']: 1, #'[1,1,1]', HEATZY_MODE_VALUE['ECONOMY']: 1, #'[1,1,1]',
@@ -373,8 +378,7 @@ class BasePlugin:
} }
#data = '{"raw": '+mode_str[mode]+'}' #data = '{"raw": '+mode_str[mode]+'}'
data = '{"attrs": {"mode":' + str(mode_str[mode]) + '}}' data = '{"attrs": {"mode":' + str(mode_str[mode]) + '}}'
device_name = self.get_name(unit) did = self.did[deviceid]["did"]
did = self.did[device_name]["did"]
url = f"https://euapi.gizwits.com/app/control/{did}" url = f"https://euapi.gizwits.com/app/control/{did}"
try: try:
response = requests.post(url, headers=headers, data=data, timeout=3).json() response = requests.post(url, headers=headers, data=data, timeout=3).json()
@@ -389,29 +393,30 @@ class BasePlugin:
if response is not None: if response is not None:
mode_str = HEATZY_MODE_VALUE_INV[mode] mode_str = HEATZY_MODE_VALUE_INV[mode]
Devices["Mode"].Units[unit].nValue = int(mode) Devices[deviceid].Units[HeatzyUnit.SELECTOR].nValue = int(mode)
Devices["Mode"].Units[unit].sValue = str(mode) Devices[deviceid].Units[HeatzyUnit.SELECTOR].sValue = str(mode)
Devices["Mode"].Units[unit].Update() Devices[deviceid].Units[HeatzyUnit.SELECTOR].Update()
Domoticz.Status(f"New Heatzy Mode: {HEATZY_MODE_NAME[mode_str]} ({self.get_name(unit)})") alias = self.did[deviceid]["alias"]
Domoticz.Status(f"New Heatzy Mode: {HEATZY_MODE_NAME[mode_str]} ({alias})")
if not self.bug: if not self.bug:
if mode_str == 'OFF' and Devices["Control"].Units[unit].nValue != 0: if mode_str == 'OFF' and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue != 0:
Devices["Control"].Units[unit].nValue = 0 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 0
Devices["Control"].Units[unit].sValue = "Off" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "Off"
elif mode_str != 'OFF' and Devices["Control"].Units[unit].nValue == 0: elif mode_str != 'OFF' and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue == 0:
Devices["Control"].Units[unit].nValue = 1 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 1
Devices["Control"].Units[unit].sValue = "On" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "On"
else: else:
if mode_str in ('OFF', 'FROSTFREE') and Devices["Control"].Units[unit].nValue != 0: if mode_str in ('OFF', 'FROSTFREE') and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue != 0:
Devices["Control"].Units[unit].nValue = 0 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 0
Devices["Control"].Units[unit].sValue = "Off" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "Off"
elif mode_str not in ('OFF', 'FROSTFREE') and Devices["Control"].Units[unit].nValue == 0: elif mode_str not in ('OFF', 'FROSTFREE') and Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue == 0:
Devices["Control"].Units[unit].nValue = 1 Devices[deviceid].Units[HeatzyUnit.CONTROL].nValue = 1
Devices["Control"].Units[unit].sValue = "On" Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue = "On"
Devices["Control"].Units[unit].Update() Devices[deviceid].Units[HeatzyUnit.CONTROL].Update()
else: else:
error_code = "Unknown" if 'error_code' not in response else response['error_code'] error_code = "Unknown" if 'error_code' not in response else response['error_code']
error_message = "Unknown" if 'error_message' not in response else response['error_message'] error_message = "Unknown" if 'error_message' not in response else response['error_message']
Domoticz.Error(f"Cannot set Heatzy Mode: {error_message} ({error_code})\n{response}\nToken: {self.token}\nDeviceId: {self.did}") Domoticz.Error(f"Cannot set Heatzy Mode: {error_message} ({error_code})\n{response}\nToken: {self.token}\nDeviceId: {did}")
if error_code == 9004: if error_code == 9004:
#Invalid token #Invalid token
self.token = "" self.token = ""
@@ -421,24 +426,17 @@ class BasePlugin:
#Device is correctly running ==> we reset the retry counter #Device is correctly running ==> we reset the retry counter
self.retry = self.max_retry self.retry = self.max_retry
def on_off(self, unit, command): def on_off(self, deviceid, command):
"""Toggle device on/off""" """Toggle device on/off"""
if Devices["Control"].Units[unit].sValue != command: if Devices[deviceid].Units[HeatzyUnit.CONTROL].sValue != command:
if command == "On": if command == "On":
self.set_mode(unit, HEATZY_MODE_VALUE['NORMAL']) self.set_mode(deviceid, HEATZY_MODE_VALUE['NORMAL'])
else: else:
if not self.bug: if not self.bug:
self.set_mode(unit, HEATZY_MODE_VALUE['OFF']) self.set_mode(deviceid, HEATZY_MODE_VALUE['OFF'])
else: else:
#Because of issue with the equipment (Off do not work...) #Because of issue with the equipment (Off do not work...)
self.set_mode(unit, HEATZY_MODE_VALUE['FROSTFREE']) self.set_mode(deviceid, HEATZY_MODE_VALUE['FROSTFREE'])
def get_name(self, unit):
"""get device name form unit"""
for device_name in self.did:
if self.did[device_name]["unit"] == unit:
return device_name
return "Not found"
_plugin = BasePlugin() _plugin = BasePlugin()