From b0bbc8c8c0be844d6f6d01548892b4bff4efc974 Mon Sep 17 00:00:00 2001 From: Francois JUMELLE Date: Sun, 15 Dec 2024 22:38:11 +0100 Subject: [PATCH] Add support of DomoticzEx --- DomoticzEx.py | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++ run.py | 7 +- 2 files changed, 229 insertions(+), 1 deletion(-) create mode 100644 DomoticzEx.py diff --git a/DomoticzEx.py b/DomoticzEx.py new file mode 100644 index 0000000..4641921 --- /dev/null +++ b/DomoticzEx.py @@ -0,0 +1,223 @@ +"""Module simulating Domoticz""" +#pylint: disable=invalid-name, missing-function-docstring, missing-class-docstring, redefined-outer-name +from datetime import datetime + +Images = {} +Devices = {} + +################### +class ImageObj(object): + ID = 0 + def __init__(self, obj): + pass + +class DzImage(object): + __name = None + def __init__(self, name): + if name[-4:].lower() != ".zip": + raise ValueError + self.__name = name[:-4] + + def Create(self): + Images[self.__name] = ImageObj(self) + +################### +class DeviceObj(object): + DeviceID = None + TimedOut = 0 + Units = {} + + def __init__(self, DeviceID=None): + self.DeviceID = DeviceID + + def __repr__(self): + res = "" + for attrib, value in self.__dict__.items(): + res = res + f"{attrib:20} : {value}" + return res + + def Refresh(self): + """Refreshes the values for the current Unit from the Domoticz database""" + raise RuntimeError("Not supported yet") + + def Touch(self): + """Updates the Unit's 'last seen' time in the database and nothing else""" + raise RuntimeError("Not supported yet") + +class DzDevice(object): + __data=None + + def __init__(self, **kwargs): + self.__data = kwargs + + def Create(self): + Devices[self.__data["DeviceID"]] = DeviceObj(**self.__data) + +################### +class UnitObj(object): + ID = None + Unit = None + Name=None + nValue = 0 + sValue = "" + SignalLevel = 0 + BatteryLevel = 0 + Image = None + Type = None + SubType = None + SwitchType = None + Used = 0 + Options = {} + LastLevel = 0 + LastUpdate = 0 + Description = "" + Color = 0 + Adjustement = 0 + Multiplier = 0 + Parent = None + + def __init__(self, Name=None, DeviceID=None, Unit=None, TypeName=None, Type=None, Subtype=None, Switchtype=None, Image=None, Options=None, Used=None, Description = None): + self.Name = Name + self.ID = DeviceID + self.Unit = Unit + self.Type = Type + self.SubType = Subtype + self.SwitchType = Switchtype + self.Image = Image + self.Options = Options + self.Used = Used + self.Description = Description + + match TypeName: + case "Switch": + self.Type = 244 + self.SubType = 73 + # self.SwitchType = ... + case "Selector Switch": + self.Type = 244 + self.SubType = 62 + # self.SwitchType = ... + case _: + raise RuntimeError(f"TypeName '{TypeName}' not supported yet") + + def __repr__(self): + res = "" + for attrib, value in self.__dict__.items(): + res = res + f"{attrib:20} : {value}" + return res + + def Update(self, Log=False, TypeName=None, UpdateProperties=False, UpdateOptions=False, SuppressTriggers=False): + """Applies the Unit's current values to the Domoticz database""" + + def Delete(self): + """Deletes the device""" + del Devices[self.ID].Units[self.Unit] + + def Refresh(self): + """Refreshes the values for the current Unit from the Domoticz database""" + + def Touch(self): + """Updates the Unit's 'last seen' time in the database and nothing else""" + +class DzUnit(object): + __data=None + + def __init__(self, **kwargs): + self.__data = kwargs + + def Create(self): + device_id = self.__data["DeviceID"] + if device_id not in Devices: + Devices[device_id] = DzDevice(DeviceID=device_id) + Devices[device_id].Create() + Devices[device_id].Units[self.__data["Unit"]] = UnitObj(**self.__data) + +################### +class BaseDomoticz(object): + __debuglevel = 0 + __heartbeat = 30 + + def __init__(self): + pass + + @staticmethod + def __print(message): + print(datetime.now().strftime("%d/%m/%Y %H:%M:%S"), "-", message) + + @staticmethod + def Image(name): + return DzImage(name) + + # @staticmethod + # def Device(**kwargs): + # return DzDevice(**kwargs) + + @staticmethod + def Unit(**kwargs): + return DzUnit(**kwargs) + + def Debugging(self, level): + self.__debuglevel = int(level) + + def Debug(self, message): + if self.__debuglevel > 0: + self.__print("[DEBUG] "+message) + + def Log(self, message): + self.__print("[LOG] "+message) + + def Status(self, message): + self.__print("[STATUS] "+message) + + def Error(self, message): + self.__print("[ERROR] "+message) + + def Heartbeat(self, duration): + self.__heartbeat = duration + + def GetHeartbeat(self): + return self.__heartbeat + +domo = BaseDomoticz() + +################### + +def Debugging(level): + """Debugging""" + domo.Debugging(level) + +def Debug(message): + """Debug""" + domo.Debug(message) + +def Log(message): + """Debugging""" + domo.Log(message) + +def Status(message): + """Status""" + domo.Status(message) + +def Error(message): + """Error""" + domo.Error(message) + +def Heartbeat(duration): + """Heartbeat""" + domo.Heartbeat(duration) + +def DomoticzImage(name): + """Image""" + return domo.Image(name) + +# def Device(*args, **kwargs): +# """Device""" +# return domo.Device(**kwargs) + +def Unit(*args, **kwargs): #pylint: disable=unused-argument + """Unit""" + if len(args) != 0: + raise RuntimeError("'args' not supported yet") + return domo.Unit(**kwargs) + +################### diff --git a/run.py b/run.py index 7935313..d87a6ea 100644 --- a/run.py +++ b/run.py @@ -3,6 +3,7 @@ import os import time import Domoticz +import DomoticzEx def function_read_properties(filename:str, sep:str='=', comment_char:str='#')->dict: """Convert a .properties file into a dictionary""" @@ -35,6 +36,7 @@ Parameters = function_read_properties(os.path.join(os.path.dirname(__file__), "p Images = Domoticz.Images Devices = Domoticz.Devices +DomoticzEx.Devices = Devices #Domoticz and DomoticsEx share the same "Devices" with open("./plugin.py", 'rb') as fileobj: exec(compile(fileobj.read(), "plugin.py", 'exec'), globals(), globals()) #pylint: disable=exec-used @@ -47,4 +49,7 @@ try: onHeartbeat() #pylint: disable=undefined-variable # type: ignore time.sleep(Domoticz.domo.GetHeartbeat()) finally: - onStop() #pylint: disable=undefined-variable # type: ignore + try: + onStop() #pylint: disable=undefined-variable # type: ignore + except NameError: + pass