class blower(): #_____________________________________________________________________________ def __init__(self, machine, name): builder.SetDeviceName(name) self.com = ModbusClient(host=machine, port=4000, auto_open=True) #4000 self.com.mode(constants.MODBUS_RTU) stat = self.com.open() self.pv_stat = builder.aIn("stat") self.pv_stat.PREC = 1 self.pv_stat.LOPR = 0 self.pv_stat.HOPR = 100 self.pv_temp = builder.aIn("temp") self.pv_temp.PREC = 1 self.pv_temp.LOPR = 0 self.pv_temp.HOPR = 100 self.pv_humi = builder.aIn("humidity") self.pv_humi.PREC = 1 self.pv_humi.LOPR = 0 self.pv_humi.HOPR = 100 self.pv_humi.HSV = "MINOR" self.pv_humi.HHSV = "MAJOR" self.pv_humi.HIGH = 45 self.pv_humi.HIHI = 50 self.pv_flow = builder.aIn("flow") self.pv_flow.PREC = 0 self.pv_flow.LOPR = 0 self.pv_flow.HOPR = 600 self.pv_flow.LOLO = 250 self.pv_flow.LOW = 300 self.pv_flow.HIGH = 480 self.pv_flow.HIHI = 520 self.pv_flow.LSV = "MINOR" self.pv_flow.LLSV = "MAJOR" self.pv_flow.HSV = "MINOR" self.pv_flow.HHSV = "MAJOR" self.stat_pv = builder.boolIn("status", ZNAM="off", ONAM="on", DESC=name) self.stat_pv.ZSV = "MAJOR" self.pv_on = builder.boolOut("on", ZNAM="0", ONAM="1", HIGH=0.1, on_update=self.turnOn) self.pv_off = builder.boolOut("off", ZNAM="0", ONAM="1", HIGH=0.1, on_update=self.turnOff) self.busy = False self.pv_act = builder.boolOut("activity", ZNAM="0", ONAM="1", HIGH=1) self.pv_was_on = builder.boolOut("was_on", ZNAM="0", ONAM="1", HIGH=1.5) self.pv_was_off = builder.boolOut("was_off", ZNAM="0", ONAM="1", HIGH=1.5) self.id_temp = 0 self.id_stat = 1 #_____________________________________________________________________________ def start_monit_loop(self): t = threading.Thread(target=self.monitor_loop) t.daemon = True t.start() #_____________________________________________________________________________ def monitor_loop(self): while True: time.sleep(2) try: if self.busy == False: self.read_YOGOGAWA() except TypeError: print "monitor_loop: reading skipped due to external write, busy:", self.busy self.busy = False #_____________________________________________________________________________ def get_1dig(self, i): #print i return float(i) * 0.1 #_____________________________________________________________________________ def read_YOGOGAWA(self): self.busy = True self.com.unit_id(1) resp = self.com.read_holding_registers(1, 2) self.pv_stat.set(self.get_1dig(resp[self.id_stat])) self.pv_temp.set(self.get_1dig(resp[self.id_temp])) #self.pv_stat.set(resp[0]) #self.pv_temp.set(resp[1]) #self.get_1dig(resp[0]) #self.get_1dig(resp[1]) self.com.unit_id(2) resp = self.com.read_holding_registers(1, 1)[0] self.pv_humi.set(self.get_1dig(resp)) self.com.unit_id(3) self.pv_flow.set(get_2comp(self.com.read_holding_registers(1, 1)[0])) self.busy = False self.pv_act.set(1) #_____________________________________________________________________________ def turnOn(self, val): if val == 0: return while self.busy == True: print "turnOn: waiting for busy to clear" time.sleep(0.2) self.busy = True self.com.unit_id(5) self.com.write_single_coil(0, True) self.busy = False #print("funtion turnOn done") self.pv_was_on.set(1) #_____________________________________________________________________________ def turnOff(self, val): if val == 0: return while self.busy == True: print "turnOff: waiting for busy to clear" time.sleep(0.2) self.busy = True self.com.unit_id(5) self.com.write_single_coil(1, True) self.busy = False #print("function turnOff done") self.pv_was_off.set(1)
from pyModbusTCP.client import ModbusClient from pyModbusTCP.constants import MODBUS_RTU from config.modbus import * from time import sleep ### MODBUS INITIALIZATION c = ModbusClient() c.mode(MODBUS_RTU) # enable MODBUS_RTU mode c.timeout(1) c.debug(True) c.auto_open(True) c.auto_close(True) reg_value={'dum':None} # DUMMY FOR RECORDING REGISTRY LISTS ### END MODBUS INITIALIZATION ### INTERNAL FUNCTIONS def loc_id(loc): device=loc.split('.') modmap,conn_id = MODBUS_MAP[device[2]],CONNECTIONS[device[0]][device[1]] return modmap,conn_id # [slave_id,reg_values],[IP_addr,port,slave_id_modifier] def reg_add(modmap,color): reg=[0x0,0x0,0x0] for cl in COLOR_LIST[color]: mapcol=modmap[1][cl] # [0xXXXX,0xXXXX,0xXXXX] for i in range(0,3): reg[i]+=mapcol[i] return reg def open_comm(): # MODBUS AUTO-RECONNECT
class MitsubishiAirConditioner: # 自上次读取一次新信息起经过了多久 lastRefreshTimestamp = time.time() client = None messageQueue = None messageThread = None # 待发送的需要等待回复的命令,成员格式为:{"code":"XX", "cmd":"XXXXXXX", "type": "query", "timestamp": timestamp} arrayCmdNeedWait = [] # 正在等待回应的命令 dicCmdWaiting = None # 存储各个空调控制器的dic, key:字符串表示的控制器模块编码(HEX) value:LJAircon对象 dicAircon = {} # nValue/sValue至寄存器Payload的map - 开关 mapVPPowerOn = None # 寄存器Payload至nValue/sValue的map - 开关 mapPVPowerOn = None # nValue/sValue至寄存器Payload的map - 运行模式 mapVPMode = None # 寄存器Payload至nValue/sValue的map - 运行模式 mapPVMode = None # nValue/sValue至寄存器Payload的map - 风速 mapVPFanSpeed = None # 寄存器Payload至nValue/sValue的map - 风速 mapPVFanSpeed = None # nValue/sValue至寄存器Payload的map - 目标温度 mapVPSetPoint = None # 寄存器Payload至nValue/sValue的map - 目标温度 mapPVSetPoint = None # nValue/sValue至寄存器Payload的map - 室温 mapVPRoomPoint = None # 寄存器Payload至nValue/sValue的map - 室温 mapPVRoomPoint = None # nValue/sValue至寄存器Payload的map - 风向 mapVPFanDirect = None # 寄存器Payload至nValue/sValue的map - 风向 mapPVFanDirect = None def __init__(self): self.messageQueue = queue.Queue() self.messageThread = threading.Thread( name="QueueThread", target=MitsubishiAirConditioner.handleMessage, args=(self, )) # 0:关1:开 self.mapVPPowerOn = {0: 0, 1: 1} self.mapPVPowerOn = self.revertDic(self.mapVPPowerOn) # 0:自动,1:制冷,2:送风,3:除湿,4:制热 self.mapVPMode = {'10': 0, '20': 1, '30': 2, '40': 3, '50': 4} self.mapPVMode = self.revertDic(self.mapVPMode) # 0:自动,2:低,3:中2,5:中1,6:高 self.mapVPFanSpeed = {'10': 0, '20': 2, '30': 3, '40': 5, '50': 6} self.mapPVFanSpeed = self.revertDic(self.mapVPFanSpeed) # 16~31°C (x10),最小单位0.5°C self.mapPVSetPoint = {} for i in range(190, 300, 5): self.mapPVSetPoint[i] = str((int((i - 190) / 5) + 1) * 10) self.mapVPSetPoint = self.revertDic(self.mapPVSetPoint) # 10~38°C (x10),最小单位1°C self.mapPVRoomPoint = {} for i in range(100, 385, 5): if i % 10 == 0: self.mapPVRoomPoint[i] = str(i // 10) elif i % 5 == 0: self.mapPVRoomPoint[i] = str(float(i) / 10) self.mapVPRoomPoint = self.revertDic(self.mapPVRoomPoint) # 0:自动,1~5:位置1~5 7:摆风 self.mapVPFanDirect = { '10': 0, '20': 1, '30': 2, '40': 3, '50': 4, '60': 5, '70': 7 } self.mapPVFanDirect = self.revertDic(self.mapVPFanDirect) return def onStart(self): Domoticz.Heartbeat(5) if Parameters["Mode2"] == "Debug": Domoticz.Debugging(1) else: Domoticz.Debugging(0) # 从Domoticz重新加载硬件和设备信息 self.reloadFromDomoticz() debug = False if Parameters["Mode2"] == "Debug": debug = True if self.client and self.client.is_open(): self.client.close() self.client = ModbusClient(host=Parameters["Address"], port=Parameters["Port"], auto_open=True, auto_close=False, timeout=1) self.messageThread.start() self.client.mode(2) self.messageQueue.put({ "Type": "Log", "Text": "Heartbeat test message" }) def onStop(self): # signal queue thread to exit self.messageQueue.put(None) Domoticz.Log("Clearing message queue...") self.messageQueue.join() # Wait until queue thread has exited Domoticz.Log("Threads still active: " + str(threading.active_count()) + ", should be 1.") while (threading.active_count() > 1): for thread in threading.enumerate(): if (thread.name != threading.current_thread().name): Domoticz.Log( "'" + thread.name + "' is still running, waiting otherwise Domoticz will abort on plugin exit." ) time.sleep(0.1) return def onConnect(self, Connection, Status, Description): return def onMessage(self, Connection, Data): return def clientConnected(self): if not self.client: return False if self.client.is_open(): return True elif not self.client.open(): Domoticz.Log('Warning: Modbus connect failed') return False def handleMessage(self): try: Domoticz.Debug("Entering message handler") while True: Message = self.messageQueue.get(block=True) if Message is None: Domoticz.Debug("Exiting message handler") self.messageQueue.task_done() break self.queryStatus() self.messageQueue.task_done() except Exception as err: Domoticz.Error("handleMessage: " + str(err)) def queryStatus(self): if not self.clientConnected(): for aircon in self.dicAircon.values(): aircon.goOffline() return for aircon in self.dicAircon.values(): #if not aircon.online: #continue # 设备已连接才发送查询指令 dicOptions = aircon.devicePowerOn.Options if not dicOptions or 'LJCode' not in dicOptions or 'LJShift' not in dicOptions: return self.client.unit_id(int(dicOptions['LJCode'], 16)) time.sleep(0.2) regs = self.client.read_holding_registers(0, 7) if not regs or regs is None: Domoticz.Log('Warning: Reading Regs Fail! 0x' + dicOptions['LJCode']) aircon.goOffline() continue elif len(regs) != 7: Domoticz.Log( 'Warning: Reading Regs Fail! 0x{}, recevied:{}'.format( dicOptions['LJCode'], str(regs))) aircon.goOffline() continue aircon.goOnline() Domoticz.Debug('Receive Regs:' + str(regs)) if aircon.devicePowerOn and regs[0] in self.mapPVPowerOn: nValue = self.mapPVPowerOn[regs[0]] sValue = aircon.devicePowerOn.sValue device = aircon.devicePowerOn UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceMode and regs[1] in self.mapPVMode: nValue = 1 sValue = self.mapPVMode[regs[1]] device = aircon.deviceMode UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceFanSpeed and regs[2] in self.mapPVFanSpeed: nValue = 1 sValue = self.mapPVFanSpeed[regs[2]] device = aircon.deviceFanSpeed UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceSetPoint and regs[3] in self.mapPVSetPoint: nValue = 1 sValue = self.mapPVSetPoint[regs[3]] device = aircon.deviceSetPoint UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceRoomPoint and regs[4] in self.mapPVRoomPoint: nValue = 1 sValue = self.mapPVRoomPoint[regs[4]] device = aircon.deviceRoomPoint UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceFanDirect and regs[5] in self.mapPVFanDirect: nValue = 1 sValue = self.mapPVFanDirect[regs[5]] device = aircon.deviceFanDirect UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) if aircon.deviceFaultCode: nValue = 1 hexText = str(hex(regs[6])) if len(hexText) >= 4 and hexText[-4:] == '8000': sValue = '运行正常' else: sValue = '错误!故障代码: ' + hexText device = aircon.deviceFaultCode UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=sValue, TimedOut=0) def onCommand(self, Unit, Command, Level, Hue): if not self.clientConnected(): Domoticz.Log('Modbus connect failed!') for aircon in self.dicAircon.values(): aircon.goOffline() return Domoticz.Log("onCommand called for Unit " + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level)) Command = Command.strip() action, sep, params = Command.partition(' ') action = action.capitalize() params = params.capitalize() device = Devices[Unit] options = device.Options if not options or 'LJCode' not in options or 'LJShift' not in options or 'LJUnit' not in options: return code = device.Options['LJCode'] shift = device.Options['LJShift'] if not code or code not in self.dicAircon or not shift or int( shift) < 0 or int(shift) > 6: return aircon = self.dicAircon[code] #if not aircon.online: #return if shift == '00': # 开关 if action == 'On': nValue = 1 elif action == 'Off': nValue = 0 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, nValue) elif shift == '01': # 模式 if action == 'Set' and params == 'Level': if aircon.devicePowerOn.nValue == 0: # 关机状态,先开机 #TODO测试连续写 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, 1) self.sendCmdBySValue(aircon, self.mapVPMode, aircon.deviceMode, str(Level)) elif shift == '02': # 风速 if action == 'Set' and params == 'Level': if aircon.devicePowerOn.nValue == 0: # 关机状态,先开机 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, 1) self.sendCmdBySValue(aircon, self.mapVPFanSpeed, aircon.deviceFanSpeed, str(Level)) elif shift == '03': # 温度 if action == 'Set' and params == 'Level': if aircon.devicePowerOn.nValue == 0: # 关机状态,先开机 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, 1) self.sendCmdBySValue(aircon, self.mapVPSetPoint, aircon.deviceSetPoint, str(Level)) elif shift == '04': # 室温 if action == 'Set' and params == 'Level': if aircon.devicePowerOn.nValue == 0: # 关机状态,先开机 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, 1) self.sendCmdBySValue(aircon, self.mapVPRoomPoint, aircon.deviceRoomPoint, str(Level)) elif shift == '05': # 风向 if action == 'Set' and params == 'Level': if aircon.devicePowerOn.nValue == 0: # 关机状态,先开机 self.sendCmdByNValue(aircon, self.mapVPPowerOn, aircon.devicePowerOn, 1) self.sendCmdBySValue(aircon, self.mapVPFanDirect, aircon.deviceFanDirect, str(Level)) # 从sValue取值,找Payload,并写寄存器 def sendCmdBySValue(self, aircon, mapVP, device, sValue): if not self.clientConnected(): return Domoticz.Log('sendCmdBySValue\(mapVP={}, device={}, sValue={}'.format( mapVP, device, sValue)) # TODO if not device or not mapVP or sValue not in mapVP: return None registerText = device.Options['LJShift'] self.client.unit_id(int(device.Options['LJCode'], 16)) if (self.client.write_single_register(int(registerText, 16), mapVP[str(sValue)])): Domoticz.Log('write_single_register\(0x{}, {}\) success!'.format( registerText, mapVP[sValue])) # TODO timedOut = 0 result = True else: Domoticz.Log('write_single_register\(0x{}, {}\) failed!'.format( registerText, mapVP[sValue])) # TODO timedOut = 1 result = False aircon.goOffline() sValue = device.sValue UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=device.nValue, sValue=str(sValue), TimedOut=timedOut) return result # 从nValue取值,找Payload,并写寄存器 def sendCmdByNValue(self, aircon, mapVP, device, nValue): if not self.clientConnected(): return Domoticz.Log('sendCmdByNValue\(mapVP={}, device={}, nValue={}'.format( mapVP, device, nValue)) # TODO if not device or not mapVP or nValue not in mapVP: return None registerText = device.Options['LJShift'] self.client.unit_id(int(device.Options['LJCode'], 16)) if (self.client.write_single_register(int(registerText, 16), mapVP[nValue])): Domoticz.Log('write_single_register\(0x{}, {}\) success!'.format( registerText, mapVP[nValue])) # TODO timedOut = 0 result = True else: Domoticz.Log('write_single_register\(0x{}, {}\) failed!'.format( registerText, mapVP[nValue])) # TODO timedOut = 1 result = False aircon.goOffline() nValue = device.nValue UpdateDevice(Unit=int(device.Options['LJUnit']), nValue=nValue, sValue=str(device.sValue), TimedOut=timedOut) return result def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile): Domoticz.Log("Notification: " + Name + "," + Subject + "," + Text + "," + Status + "," + str(Priority) + "," + Sound + "," + ImageFile) def onDisconnect(self, Connection): Domoticz.Log("onDisconnect called") def onHeartbeat(self): # Domoticz.Log('onHeartbeat Called ---------------------------------------') # 如果没连接则尝试重新连接 if not self.clientConnected(): for aircon in self.dicAircon.values(): aircon.goOffline() return # 查询空调状态 self.messageQueue.put({ "Type": "Log", "Text": "Heartbeat test message" }) def reloadFromDomoticz(self): self.dicAircon = {} strListCode = Parameters["Mode1"] strListCode = strListCode.replace(',', '') strListCode = strListCode.replace('|', '') strListCode = strListCode.replace(' ', '') strListCode = strListCode.replace('0X', '0x') strListCode = strListCode.replace('X', '0x') setCode = set(strListCode.split('0x')) setCode2 = set([]) for tmp in setCode: if not tmp: continue setCode2.add(tmp.upper()) for tmp2 in setCode2: if not tmp2: continue if len(tmp2) > 2: tmp2 = tmp2[-2:] tmp2 = '{:0>2}'.format(tmp2) Domoticz.Log('Detected Code:' + tmp2) self.dicAircon[tmp2] = LJAircon(tmp2) # 记录已有的unit setUnit = set([]) # 待删除的device对应的unit setUnitDel = set([]) # 所有的Unit集合 setUnitAll = set(range(1, 256)) # 将Device放入对应的控制器对象中,多余的device删除 for unit in Devices: device = Devices[unit] dicOptions = device.Options Domoticz.Log("DEVICE FROM PANEL " + descDevice(device=device, unit=unit)) shouldDelete = False if dicOptions and 'LJCode' in dicOptions and 'LJShift' in dicOptions and dicOptions[ 'LJCode'] in self.dicAircon: # 有匹配的控制器,赋值 aircon = self.dicAircon[dicOptions['LJCode']] if dicOptions['LJShift'] == '00': # 开关 if aircon.devicePowerOn: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have devicePowerOn, add to delete list. ' + device.Name) shouldDelete = True else: aircon.devicePowerOn = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '01': # 运行模式 if aircon.deviceMode: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceMode, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceMode = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '02': # 风速 if aircon.deviceFanSpeed: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceFanSpeed, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceFanSpeed = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '03': # 目标温度 if aircon.deviceSetPoint: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceSetPoint, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceSetPoint = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '04': # 室温 if aircon.deviceRoomPoint: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceRoomPoint, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceRoomPoint = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '05': # 风向 if aircon.deviceFanDirect: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceFanDirect, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceFanDirect = device aircon.dicDevice[unit] = device elif dicOptions['LJShift'] == '06': # 状态 if aircon.deviceFaultCode: #已经有现成的设备,加入待删除 Domoticz.Log( 'Already have deviceFaultCode, add to delete list. ' + device.Name) shouldDelete = True else: aircon.deviceFaultCode = device aircon.dicDevice[unit] = device else: shouldDelete = True else: shouldDelete = True if shouldDelete: setUnitDel.add(unit) else: setUnit.add(unit) Domoticz.Log("DELETE DEVICES IN UNIT: " + str(setUnitDel)) # 删除多余的Device for unit in setUnitDel: Devices[unit].Delete() # Check if images are in database #if "LJCountDown" not in Images: # Domoticz.Image("LJCountDown.zip").Create() #image = Images["LJCountDown"].ID # 遍历控制器,补全控制器对应的device for aircon in self.dicAircon.values(): setAvariable = setUnitAll.difference(setUnit) if not setAvariable or len(setAvariable) == 0: continue if not aircon.devicePowerOn: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '00' } name = '0x{} 开关'.format(aircon.code) aircon.devicePowerOn = Domoticz.Device(Name=name, Unit=newUnit, Type=244, Subtype=73, Switchtype=0, Options=optionsCustom) aircon.devicePowerOn.Create() aircon.dicDevice[newUnit] = aircon.devicePowerOn Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.devicePowerOn, unit=newUnit)) if not aircon.deviceMode and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '01' } levelNames = 'Off|自动|制冷|送风|除湿|制热' optionsGradient = { 'LevelActions': '|' * levelNames.count('|'), 'LevelNames': levelNames, 'LevelOffHidden': 'true', 'SelectorStyle': '0' } name = '0x{} 模式'.format(aircon.code) aircon.deviceMode = Domoticz.Device(Name=name, Unit=newUnit, TypeName="Selector Switch", Switchtype=18, Image=0, Options=dict( optionsCustom, **optionsGradient)) aircon.deviceMode.Create() aircon.dicDevice[newUnit] = aircon.deviceMode Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceMode, unit=newUnit)) if not aircon.deviceFanSpeed and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '02' } levelNames = 'Off|自动|低|中2|中1|高' optionsGradient = { 'LevelActions': '|' * levelNames.count('|'), 'LevelNames': levelNames, 'LevelOffHidden': 'true', 'SelectorStyle': '0' } name = '0x{} 风速'.format(aircon.code) aircon.deviceFanSpeed = Domoticz.Device( Name=name, Unit=newUnit, TypeName="Selector Switch", Switchtype=18, Image=0, Options=dict(optionsCustom, **optionsGradient)) aircon.deviceFanSpeed.Create() aircon.dicDevice[newUnit] = aircon.deviceFanSpeed Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceFanSpeed, unit=newUnit)) if not aircon.deviceSetPoint and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '03' } levelNames = 'Off' for i in range(190, 300, 5): if i % 10 == 0: levelNames += '|' + str(i // 10) + '℃' elif i % 5 == 0: levelNames += '|' + str(float(i) / 10) + '℃' optionsGradient = { 'LevelActions': '|' * levelNames.count('|'), 'LevelNames': levelNames, 'LevelOffHidden': 'true', 'SelectorStyle': '1' } name = '0x{} 设定温度'.format(aircon.code) aircon.deviceSetPoint = Domoticz.Device( Name=name, Unit=newUnit, TypeName="Selector Switch", Switchtype=18, Image=0, Options=dict(optionsCustom, **optionsGradient)) aircon.deviceSetPoint.Create() aircon.dicDevice[newUnit] = aircon.deviceSetPoint Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceSetPoint, unit=newUnit)) if not aircon.deviceRoomPoint and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '04' } name = '0x{} 室温'.format(aircon.code) aircon.deviceRoomPoint = Domoticz.Device( Name=name, Unit=newUnit, TypeName="Temperature", Options=optionsCustom) aircon.deviceRoomPoint.Create() aircon.dicDevice[newUnit] = aircon.deviceRoomPoint Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceRoomPoint, unit=newUnit)) if not aircon.deviceFanDirect and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '05' } levelNames = 'Off|自动|位置1|位置2|位置3|位置4|位置5|摆风' optionsGradient = { 'LevelActions': '|' * levelNames.count('|'), 'LevelNames': levelNames, 'LevelOffHidden': 'true', 'SelectorStyle': '0' } name = '0x{} 风向'.format(aircon.code) aircon.deviceFanDirect = Domoticz.Device( Name=name, Unit=newUnit, TypeName="Selector Switch", Switchtype=18, Image=0, Options=dict(optionsCustom, **optionsGradient)) aircon.deviceFanDirect.Create() aircon.dicDevice[newUnit] = aircon.deviceFanDirect Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceFanDirect, unit=newUnit)) if not aircon.deviceFaultCode and len(setAvariable) > 0: newUnit = setAvariable.pop() setUnit.add(newUnit) optionsCustom = { "LJUnit": str(newUnit), 'LJCode': aircon.code, 'LJShift': '06' } name = '0x{} 状态'.format(aircon.code) aircon.deviceRoomPoint = Domoticz.Device(Name=name, Unit=newUnit, TypeName="Text", Image=17, Options=optionsCustom) aircon.deviceRoomPoint.Create() aircon.dicDevice[newUnit] = aircon.deviceRoomPoint Domoticz.Log( 'ADD DEVICE :' + descDevice(device=aircon.deviceRoomPoint, unit=newUnit)) def revertDic(self, dic): if dic: return {v: k for k, v in dic.items()} return None