def test_unit_id(self): # test valid/invalid cases for debug() c = ModbusClient() self.assertEqual(c.unit_id(), 1, 'default unit_id is 1') self.assertEqual(c.unit_id(42), 42) self.assertEqual(c.unit_id(0), 0) self.assertEqual(c.unit_id(420), None)
def __init__(self, address, port): c = ModbusClient() c.host(address) c.port(port) c.unit_id(1) c.open() data = c.read_holding_registers(130, 12) self.data=data c.close() if data: self.LowT1Start = format(data[0], 'x') self.LowT1Stop = format(data[1], 'x') self.LowT2Start = format(data[2], 'x') self.LowT2Stop = format(data[3], 'x') self.NormT1Start = format(data[4], 'x') self.NormT1Stop = format(data[5], 'x') self.NormT2Start = format(data[6], 'x') self.NormT2Stop = format(data[7], 'x') self.PeakT1Start = format(data[8], 'x') self.PeakT1Stop = format(data[9], 'x') self.PeakT2Start = format(data[10], 'x') self.PeakT2Stop = format(data[11], 'x') else: print("Read Volt And Amper ERROR")
def make_summary(): SERVER_HOST = "192.168.43.239" SERVER_PORT = 502 SERVER_UNIT_ID = 2 c = ModbusClient() c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_UNIT_ID) if not c.is_open(): if not c.open(): print("cannot connect ....") if c.is_open(): # read 54 registers at address 0, store result in regs list regs = c.read_input_registers(0,54) # if success change register value to float if regs: abc = [utils.decode_ieee(f) for f in utils.word_list_to_long(regs)] data = { "Power KWH" : "%0.3f"%abc[0], "Power KVAH" : "%0.3f"%abc[1], "Power KVArP" : "%0.3f"%abc[2], "Power KVArN" : "%0.3f"%abc[3], "Line Voltages V RY" : "%0.3f"%abc[4], "Line Voltages V YB" : "%0.3f"%abc[5], "Line Voltages V BR" : "%0.3f"%abc[6], "Line Current IR" : "%0.3f"%abc[7], "Line Current IY" : "%0.3f"%abc[8], "Line Current IB" : "%0.3f"%abc[9], "Active Power Consumed" : "%0.3f"%abc[10], "Reactive Power Consumed" : "%0.3f"%abc[11], "Apparent Power Consumed" : "%0.3f"%abc[12], "Phase Voltages VRN" : "%0.3f"%abc[13], "Phase Voltages VYN" : "%0.3f"%abc[14], "Phase Voltages VBN" : "%0.3f"%abc[15], "Power Factor" : "%0.3f"%abc[16], "Frequency" : "%0.3f"%abc[17], "Real Power on R" : "%0.3f"%abc[18], "Real Power on Y" : "%0.3f"%abc[19], "Real Power on B" : "%0.3f"%abc[20], "Reactive Power on R" : "%0.3f"%abc[21], "Reactive Power on Y" : "%0.3f"%abc[22], "Reactive Power on B" : "%0.3f"%abc[23], "Apparent Power on R" : "%0.3f"%abc[24], "Apparent Power on Y" : "%0.3f"%abc[25], "Apparent Power on B" : "%0.3f"%abc[26] } mydate = datetime.datetime.now() date=datetime.datetime.strftime(mydate,'%Y/%m/%d--%H:%M:%S') abc.insert(27,date) myfile = open('data.csv','a') with myfile: writer = csv.writer(myfile, delimiter=',', quoting=csv.QUOTE_ALL) writer.writerow(abc) return data
def importFromGrid(setPoint, SOCDischarge, SOCCharge): log.write('%02d, %02d, %02d, ' % (setPoint, SOCDischarge, SOCCharge)) #log.write(str(setPoint)+', '+str(SOCDischarge)+', '+str(SOCCharge)+', ') hub4 = ModbusClient() hub4.host(farmIP) hub4.port(hub4Port) hub4.unit_id(hub4Id) inverter = ModbusClient() inverter.host(farmIP) inverter.port(invPort) inverter.unit_id(invId) success = False if inverter.open(): r = inverter.read_input_registers(30, 1) soc = r[0] / 10.0 # convert to a percentage log.write('%.1f, inverter, ' % (soc)) print 'SOC=', (soc) else: log.write('failed to open inverter coms') #sort the chargeing if hub4.open(): success = True if soc < SOCCharge: #allow chargeing at max power set point log.write('charging, ') success = success & hub4.write_single_register(2700, setPoint) else: #battery sufficiently charged set charging power to 0 log.write('not charging, ') success = success & hub4.write_single_register(2700, 0) if soc > SOCDischarge: #allow battery to discharge log.write('discharging, ') success = success & hub4.write_single_register(2702, 100) else: #disallow discharge log.write('not discharging, ') success = success & hub4.write_single_register(2702, 0) hub4.close() log.write('hub4, ') else: log.write('hub4 failed to open hub4 comms') return success
def getModbusData(host, port, unit_id, start_register, end_register): # Returns a list containing the data from each Modbus register between #...and including the start and end register # Depending on the format of any particular value you want, its data may be distributed #...over multiple registers and will require further formatting to be human-readable. # This function only returns the data directly taken from the device's Modbus registers. # Setting up the client #---------------------------------------------------- client = ModbusClient() # Creates a Modbus client opject client.host(host) # Assigns the specified host (IP) address to the client client.port(port) # Assigns the specified port to the client client.unit_id(unit_id=unit_id) start_register -= 2 # The Modbus registers listed in the Shark200 User's manual end_register -= 2 #...are all offset by 2 from their actual values, #...so we account for that here. num_of_registers = end_register - start_register + 1 # Since the registers are taken as integers, we can take the range between the start and end #...registers and add 1 to get the total number of registers to query. #---------------------------------------------------- # Reading the device's Modbus registers #---------------------------------------------------- client.open() # Opens the connection response = client.read_holding_registers(start_register, num_of_registers) # This function returns a list of values, one for each of the Modbus registers specified. # It works even if some of the registers queried have data stored in different formats, #...so be careful not to automatically treat all data the same. client.close() # Closes the connection #---------------------------------------------------- return response
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
class HeatPump(): def __init__(self, ipOrHostName, portNumber, unitId, code): self.code = code self.registers = HeatPumpRegisters() self.mbClient = ModbusClient() self.mbClient.host(ipOrHostName) self.mbClient.port(portNumber) self.mbClient.unit_id(unitId) self.mbClient.open() self.outsideTemperature = HeatPumpConstants.NAN_VALUE self.currentRoomTemperature = HeatPumpConstants.NAN_VALUE self.currentExhaustFanSpeed = HeatPumpConstants.NAN_VALUE self.currentSupplyFanSpeed = HeatPumpConstants.NAN_VALUE self.airingLevelDay = HeatPumpConstants.NAN_VALUE self.airingLevelNight = HeatPumpConstants.NAN_VALUE self.powerConsumptionHeatingDay = HeatPumpConstants.NAN_VALUE self.powerConsumptionWarmWaterDay = HeatPumpConstants.NAN_VALUE return def setAiringLevelDay(self, airingLevel, code): return self._setAiringLevel(self.registers.AIRING_LEVEL_DAY.Address, airingLevel, code) def setAiringLevelNight(self, airingLevel, code): return self._setAiringLevel(self.registers.AIRING_LEVEL_NIGHT.Address, airingLevel, code) def _setAiringLevel(self, registerAddress, airingLevel, code): if int(code) != self.code: return (False, "Invalid security code") if not self.mbClient.is_open() and not self.mbClient.open(): return (False, "Unable to connect to {}:{}".format(self.mbClient.host(), self.mbClient.port())) if type(airingLevel) == str: try: airingLevel = int(airingLevel) except: raise TypeError("Could not convert {} to type 'int'".format(airingLevel)) retVal = self.mbClient.write_single_register(registerAddress, airingLevel) if not retVal: return (False, "Failed to set airing level") else: return (True, "Setting airing level successful") def readCurrentValues(self): if not self.mbClient.is_open() and not self.mbClient.open(): print ("Unable to connect to {}:{}".format(self.mbClient.host(), self.mbClient.port())) return False regVal_outsideTemperature = self.mbClient.read_input_registers(self.registers.OUTSIDE_TEMPERATURE.Address, self.registers.OUTSIDE_TEMPERATURE.SequenceSize) regVal_currentRoomTemperature = self.mbClient.read_input_registers(self.registers.CURRENT_ROOM_TEMPERATURE.Address, self.registers.CURRENT_ROOM_TEMPERATURE.SequenceSize) regVal_currentExhaustFanSpeed = self.mbClient.read_input_registers(self.registers.CURRENT_EXHAUST_FAN_SPEED.Address, self.registers.CURRENT_EXHAUST_FAN_SPEED.SequenceSize) regVal_currentSupplyFanSpeed = self.mbClient.read_input_registers(self.registers.CURRENT_SUPPLY_FAN_SPEED.Address, self.registers.CURRENT_SUPPLY_FAN_SPEED.SequenceSize) regVal_airingLevelDay = self.mbClient.read_holding_registers(self.registers.AIRING_LEVEL_DAY.Address, self.registers.AIRING_LEVEL_DAY.SequenceSize) regVal_airingLevelNight = self.mbClient.read_holding_registers(self.registers.AIRING_LEVEL_NIGHT.Address, self.registers.AIRING_LEVEL_NIGHT.SequenceSize) regVal_powerConsumptionHeatingDay = self.mbClient.read_input_registers(self.registers.POWER_CONSUMPTION_HEATING_DAY.Address, self.registers.POWER_CONSUMPTION_HEATING_DAY.SequenceSize) regVal_powerConsumptionWarmWaterDay = self.mbClient.read_input_registers(self.registers.POWER_CONSUMPTION_WARMWATER_DAY.Address, self.registers.POWER_CONSUMPTION_WARMWATER_DAY.SequenceSize) outsideTemperature = self.registers.shiftValue(regVal_outsideTemperature, self.registers.OUTSIDE_TEMPERATURE.SequenceSize) # outsideTemperature can be less than zero self.outsideTemperature = self.registers.convertSignedValue(outsideTemperature, HeatPumpConstants.MBREG_BITWIDTH) * 0.1 self.currentRoomTemperature = self.registers.shiftValue(regVal_currentRoomTemperature, self.registers.CURRENT_ROOM_TEMPERATURE.SequenceSize) * 0.1 self.currentExhaustFanSpeed = self.registers.shiftValue(regVal_currentExhaustFanSpeed, self.registers.CURRENT_EXHAUST_FAN_SPEED.SequenceSize) self.currentSupplyFanSpeed = self.registers.shiftValue(regVal_currentSupplyFanSpeed, self.registers.CURRENT_SUPPLY_FAN_SPEED.SequenceSize) self.airingLevelDay = self.registers.shiftValue(regVal_airingLevelDay, self.registers.AIRING_LEVEL_DAY.SequenceSize) self.airingLevelNight = self.registers.shiftValue(regVal_airingLevelNight, self.registers.AIRING_LEVEL_NIGHT.SequenceSize) self.powerConsumptionHeatingDay = self.registers.shiftValue(regVal_powerConsumptionHeatingDay, self.registers.POWER_CONSUMPTION_HEATING_DAY.SequenceSize) self.powerConsumptionWarmWaterDay = self.registers.shiftValue(regVal_powerConsumptionWarmWaterDay, self.registers.POWER_CONSUMPTION_WARMWATER_DAY.SequenceSize) return True
print("Load:") print("\tReal Power on R: ",abc[18],"KW") print("\tReal Power on Y: ",abc[19],"KW") print("\tReal Power on B: ",abc[20],"KW") print("\tReactive Power on R: ",abc[21],"KVAr") print("\tReactive Power on Y: ",abc[22],"KVAr") print("\tReactive Power on B: ",abc[23],"KVAr") print("\tApparent Power on R: ",abc[24],"KVA") print("\tApparent Power on Y: ",abc[25],"KVA") print("\tApparent Power on B: ",abc[26],"KVA") ''' # define modbus server host, port c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_UNIT_ID) while True: # open or reconnect TCP to server if not c.is_open(): if not c.open(): print("unable to connect to " + SERVER_HOST + ":" + str(SERVER_PORT)) # if open() is ok, read register (modbus function 0x03) if c.is_open(): mydate = datetime.datetime.now() print(str(mydate)) # read 54 registers at address 0, store result in regs list
def send_data(): SERVER_HOST = "169.254.0.12" SERVER_PORT = 502 #this has to be 502 for tcp/ip modbus SERVER_UNIT_ID = 100 #slave id is 100 for schneider powerlogic ion 7650 #default value for ionmeter #subnet mask= 255.240.0.0 #gateway= 0.0.0.0 #Required Registers to be read :- #Va= 40166 2 registers ie. c.read_input_registers(40166,2) #power kw a = 40198 2 registers #kVAR a= 40208 2 registers #kVA a= 40218 2 registers #frequency = 40159 1 register #Ia= 40150 1 register #this function reads the float value for address and number of bits (not required) #def read_float( address, number=1): # reg_l = c.read_holding_registers(address, number ) #can change to read_input_registers just to check # if reg_l: # return [utils.decode_ieee(f) for f in utils.word_list_to_long(reg_l)] # else: # return None c = ModbusClient() c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_UNIT_ID) #default slave id for schneider is 100 if not c.is_open(): if not c.open(): print("cannot connect ....") if c.is_open(): #read_holding_registers has an offset of 4000 to begin with while True: voltage_a = c.read_holding_registers( 166, 1) #list output for integer take voltage_a[0] voltage_a = voltage_a[0] #print voltage_a #current_a=c.read_holding_registers(150,1) k = state_val.count(1) current_a = random.uniform( state_val.count(1) * cur_val, state_val.count(1) * cur_val + 0.05) if k != 0 else 0 #current_a=current_a[0] #print current_a real_power_a = c.read_holding_registers(208, 1) #real_power_a=real_power_a[0] #print real_power_a reactive_power_a = c.read_holding_registers(218, 1) #reactive_power_a=reactive_power_a[0] #print reactive_power_a apparent_power_a = c.read_holding_registers(218, 1) #apparent_power_a=apparent_power_a[0] #print apparent_power_a freq = c.read_holding_registers(159, 1) freq = freq[0] / 10 #move this part to decision in case of load scheduling #set_priority() #print_priority() #print freq np.array(voltage_a, dtype=float) np.array(current_a, dtype=float) np.array(real_power_a, dtype=float) np.array(reactive_power_a, dtype=float) np.array(apparent_power_a, dtype=float) np.array(freq, dtype=float) data = { "voltage_reading": '%.2f' % voltage_a, "current_reading": '%.2f' % current_a, "frequency_reading": '%.2f' % freq, "load_0_status": "ON" if state_val[0] == 1 else "OFF", "load_1_status": "ON" if state_val[1] == 1 else "OFF", "load_2_status": "ON" if state_val[2] == 1 else "OFF", "load_3_status": "ON" if state_val[3] == 1 else "OFF", "bpi_0": '%.2f' % bpi[0], "bpi_1": '%.2f' % bpi[1], "bpi_2": '%.2f' % bpi[2], "bpi_3": '%.2f' % bpi[3], "sv0": state_val[0], "sv1": state_val[1], "sv2": state_val[2], "sv3": state_val[3] } print(data) decision(data) return data
class ModbusTCP(): def __init__(self, ip, name_well, name_compressors, host_mqtt, topic_data, topic_actions=None, ip_br20=None, puerto=502, scanrate=0.1, id_plc1=None, id_br20=None, id_plc2=None, id_ptp=1, id_ptr=2, id_pld=3, id_ttp=4, br20_unique=True, tout=5, get_etm=False): self.cliente = ModbusClient(host=ip, port=puerto, timeout=tout) # if id_plc1 != id_br20 and id_br20 != id_plc2 and id_plc2 != id_plc1: if len(name_compressors) == 1: self._flg_plc1 = True if id_plc1 != None and name_compressors[ 0] != None else False self._flg_plc2 = True if self._flg_plc1 == False else False elif len(name_compressors) == 2: self._flg_plc1 = True if id_plc1 != None and name_compressors[ 0] != None else False self._flg_plc2 = True if id_plc2 != None and name_compressors[ 1] != None else False self._flg_br20 = True if id_br20 != None else False if self._flg_plc1: # self._tcp_plc1 = ModbusClient(host=ip, port=puerto, unit_id=id_plc1, timeout=tout) self.id_plc1 = id_plc1 self.tries_plc1 = 0 self._name_compressor1 = str(name_compressors[0]) if self._flg_br20: if ip_br20 == None: self._tcp_br2 = ModbusClient(host=ip, port=puerto, unit_id=id_br20, timeout=tout) else: self._tcp_br2 = ModbusClient(host=ip_br20, port=puerto, unit_id=id_br20, timeout=tout) # self.ip_br20 = ip_br20 if ip_br20 != None else None # if ip_br20 != None: # self._tcp_br2 = ModbusClient(host=ip_br20, port=puerto, unit_id=id_br20, timeout=tout) # else: # self.id_br20 = id_br20 self._flg_unique = br20_unique self.tries_br20 = 0 if self._flg_plc2: # self._tcp_plc2 = ModbusClient( host=ip, port=puerto, unit_id=id_plc2, timeout=tout) self.id_plc2 = id_plc2 self.tries_plc2 = 0 if self._flg_plc1: self._name_compressor2 = str(name_compressors[1]) else: self._name_compressor2 = str(name_compressors[0]) self._ip = ip self._scanrate = scanrate self._hostmqtt = host_mqtt self._topic = topic_data self._actions = topic_actions self.tries_radio = 0 self.how_many_null = 100 self.json_ok = None self.status = [False] * 15 self.sensors = 0 self.sensors += 1 if id_ptp != None else 0 self.sensors += 1 if id_ptr != None else 0 self.sensors += 1 if id_pld != None else 0 self.sensors += 1 if id_ttp != None else 0 self._name = name_well.lower().replace("-", " ").replace(" ", "_") self._errors = list() self.__create_table() self._ecd = EncodeToJson(self._name, plc1=self._flg_plc1, br20=self._flg_br20, plc2=self._flg_plc2, ptp=id_ptp, ptr=id_ptr, pld=id_pld, ttp=id_ttp, onETM=get_etm) # Thread(name='Actions {}'.format(self._name), target=self.__subscribe_mqtt).start() Thread(name='Backup {}'.format(self._name), target=self.__save_data_daily).start() def __create_table(self): db = sqlite3.connect(Address.DATABASE_FOLDER, ) c = db.cursor() sql = """CREATE TABLE IF NOT EXISTS {}('id' INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,'name' TEXT NOT NULL,'time' NUMERIC,'date' NUMERIC, 'ptp' NUMERIC, 'ptr' NUMERIC,'pld' NUMERIC,'ttp' NUMERIC, 'namecompresor_1' TEXT, 'etm_1' NUMERIC,'pr_1' NUMERIC, 'rpmp_1' NUMERIC, 'fep_1'NUMERIC,'ttdp_1' NUMERIC,'prdp_1' NUMERIC, 'ptsp_1' NUMERIC,'pttrp_1' NUMERIC,'pttpp_1' NUMERIC,'tagc_1' NUMERIC, 'tad_1' NUMERIC, 'fegc_1' NUMERIC,'fcgc_1' NUMERIC,'vgi_1' NUMERIC, 'fcd_1' NUMERIC,'tgc_1' NUMERIC,'pegc_1' NUMERIC,'pdgc_1' NUMERIC, 'td_1' NUMERIC, 'ped_1' NUMERIC,'pdd_1' NUMERIC,'tpv_1' NUMERIC,'pld2_1' NUMERIC, 'pts_1' NUMERIC,'tts_1' NUMERIC,'di_1' NUMERIC, 'pc_1' NUMERIC,'df_1' NUMERIC, 'namecompresor_2' TEXT, 'etm_2' NUMERIC, 'pr_2' NUMERIC,'rpmp_2' NUMERIC,'fep_2' NUMERIC,'ttdp_2' NUMERIC, 'prdp_2' NUMERIC,'ptsp_2' NUMERIC, 'pttrp_2' NUMERIC,'pttpp_2' NUMERIC,'tagc_2' NUMERIC,'tad_2' NUMERIC,'fegc_2' NUMERIC,'fcgc_2' NUMERIC, 'vgi_2' NUMERIC,'fcd_2' NUMERIC, 'tgc_2' NUMERIC, 'pegc_2' NUMERIC,'pdgc_2' NUMERIC, 'td_2' NUMERIC,'ped_2' NUMERIC,'pdd_2' NUMERIC,'tpv_2' NUMERIC, 'pld2_2' NUMERIC, 'pts_2' NUMERIC, 'tts_2' NUMERIC,'di_2' NUMERIC, 'pc_2' NUMERIC,'df_2' NUMERIC)""".format( self._name) c.execute(sql) if self._flg_plc1: sql = """INSERT INTO time_operation(name, limitTime, onlineTime, startTime, actualTime, isOnline) SELECT * FROM (SELECT '{0}', 0, 0, {1}, 0, 0) AS tmp WHERE NOT EXISTS ( SELECT name FROM time_operation WHERE name = '{0}') LIMIT 1;""".format( self._name + '_{}'.format(self._name_compressor1), int(time.time() - 6 * 3600)) c.execute(sql) if self._flg_plc2: sql = """INSERT INTO time_operation(name, limitTime, onlineTime, startTime, actualTime, isOnline) SELECT * FROM (SELECT '{0}', 0, 0, {1}, 0, 0) AS tmp WHERE NOT EXISTS ( SELECT name FROM time_operation WHERE name = '{0}') LIMIT 1;""".format( self._name + '_{}'.format(self._name_compressor2), int(time.time() - 6 * 3600)) c.execute(sql) sql = """INSERT INTO connection_status(name, ip) SELECT * FROM (SELECT '{0}', '{1}') AS tmp WHERE NOT EXISTS ( SELECT name FROM connection_status WHERE name = '{0}') LIMIT 1;""".format( self._name, self._ip) c.execute(sql) db.commit() db.close() def __routine_plc(self, plc, id): # if id == 1: # plc.unit_id(self.id_plc1) # elif id == 2: # plc.unit_id(self.id_plc2) if not plc.is_open(): if not plc.open(): # Title: error self._errors.append( ("PLC{} Connection".format(id), plc.last_except())) plc.close() self.tries_radio += 1 return [None] * 13, [None] * 15, [None] * 8, None, [None] * 3 if plc.is_open(): self.tries_radio = 0 plc4 = plc.read_discrete_inputs(0, 3) if plc4 != None: fl_bp = False for i in range(0, len(plc4)): plc4[i] = 1 if plc4[i] else 0 else: fl_bp = True # Title: error self._errors.append( ("PLC{} Booleans Package".format(id), plc.last_except())) plc4 = [None] * 3 # plc4 = [None]*3 fl_bp = True time.sleep(0.1) # plc3 = plc.read_holding_registers(0, 4) # if plc3 != None: # fl_hp = False # else: # fl_hp = True # # Title: error # self._errors.append( # ("PLC{} Holding Package".format(id), plc.last_except())) # plc3 = None plc3 = None fl_hp = True # time.sleep(0.1) tmp = plc.read_input_registers(148, 2) if tmp != None: tmp = decimal_list_to_float_litEndian(tmp) else: tmp = [None] time.sleep(0.1) # plc2 = plc.read_input_registers(134, 16) plc2 = plc.read_input_registers(134, 14) if plc2 != None: fl_ip1 = False plc2 = decimal_list_to_float_litEndian(plc2) else: fl_ip1 = True # Title: error self._errors.append( ("PLC{} Inputs Package 1".format(id), plc.last_except())) # plc2 = [None]*8 plc2 = [None] * 7 plc2.extend(tmp) time.sleep(0.1) plc1_1 = plc.read_input_registers(0, 26) if plc1_1 != None: fl_ip2 = False plc1_1 = decimal_list_to_float_litEndian(plc1_1) else: fl_ip2 = True # Title: error self._errors.append( ("PLC{} Inputs Package 2".format(id), plc.last_except())) plc1_1 = [None] * 13 time.sleep(0.1) plc1_2 = plc.read_input_registers(26, 30) if plc1_2 != None: fl_ip3 = False plc1_2 = decimal_list_to_float_litEndian(plc1_2) else: fl_ip3 = True # Title: error self._errors.append( ("PLC{} Inputs Package 3".format(id), plc.last_except())) plc1_2 = [None] * 15 if id == 1: self.status[4] = fl_bp self.status[5] = fl_hp self.status[6] = fl_ip1 self.status[7] = fl_ip2 self.status[8] = fl_ip3 elif id == 2: self.status[9] = fl_bp self.status[10] = fl_hp self.status[11] = fl_ip1 self.status[12] = fl_ip2 self.status[13] = fl_ip3 if fl_bp and fl_hp and fl_ip1 and fl_ip2 and fl_ip3: if id == 1: self.tries_plc1 += 1 elif id == 2: self.tries_plc2 += 1 else: if id == 1: self.tries_plc1 = 0 elif id == 2: self.tries_plc2 = 0 return plc1_1, plc1_2, plc2, plc3, plc4 def __routine_br20(self, br20): count = 0 rb_devices = None rb_info = None while rb_devices == None and count <= 3: # print('Asking br20 of '+self._name) if not br20.is_open(): if not br20.open(): self._errors.append( ("BR20 Connection", br20.last_except())) # br20.close() count += 1 time.sleep(0.3) self.tries_radio += 1 if br20.is_open(): self.tries_radio = 0 rb_info = None # rb_info = br20.read_holding_registers(0, 10) # if rb_info == None: # # Title: error # self._errors.append(("BR20 Info", br20.last_except())) # rb_info = [None]*10 if self._flg_unique == None: rb_devices = br20.read_holding_registers( 10, self.sensors * 10) elif self._flg_unique: # Lee todos # TODO: Que se lean por el numero de sensores y no fijo rb_devices = br20.read_holding_registers(10, 60) elif not self._flg_unique: # Leera en el texto try: with open( Address.DATA_FOLDER + 'br20_ip{}.txt'.format( self._ip.replace('.', '')), 'r+') as f: a = str(f.read()) a = a.replace('[', '').replace(']', '').split(',') for i in range(0, len(a)): try: a[i] = float( a[i]) if a[i] != ' None' and a[ i] != 'None' else None except ValueError: a[i] = None rb_devices = a + [None] * 10 except IOError: rb_devices = [None] * 20 return rb_info, rb_devices if rb_devices != None and (self._flg_unique or self._flg_unique == None): fl_br20 = False rb_devices = decimal_list_to_float_bigEndian(rb_devices) rb_devices += [None] * (20 - len(rb_devices)) else: # Title: error count += 1 fl_br20 = True self._errors.append(("BR20 Sensors", br20.last_except())) # rb_devices = [None]*20 self.status[14] = fl_br20 if fl_br20: if self._flg_unique or self._flg_unique == None: self.tries_br20 += 1 elif rb_devices == [None] * 20: self.tries_br20 += 1 else: self.tries_br20 = 0 # print('Data br20: {} Count: {}'.format(rb_devices, count)) if count >= 3 or rb_devices == None: rb_info, rb_devices = [None] * 10, [None] * 20 if len(rb_devices) > 20: with open( Address.DATA_FOLDER + 'br20_ip{}.txt'.format(self._ip.replace('.', '')), 'w+') as f: f.write(str(rb_devices[20:])) time.sleep(0.1) return rb_info, rb_devices def run_once(self): self.fecha, self.tiempo = dt.today().isoformat().split('T') t0 = time.time() # Title: BR20 if self._flg_br20: rb_info, rb_devices = self.__routine_br20(self._tcp_br2) # if self.ip_br20 != None: # rb_info, rb_devices = self.__routine_br20(self._tcp_br2) # else: # self.cliente.unit_id(self.id_br20) # rb_info, rb_devices = self.__routine_br20(self.cliente) self._ecd.set_well(rb_devices, self.fecha, self.tiempo) else: self._ecd.set_well(None, self.fecha, self.tiempo) t1 = time.time() # Title: PLC1 if self._flg_plc1: # plc1_1, plc1_2, plc2, plc3, plc4 = self.__routine_plc(self._tcp_plc1, 1) self.cliente.unit_id(self.id_plc1) plc1_1, plc1_2, plc2, plc3, plc4 = self.__routine_plc( self.cliente, 1) self._ecd.set_compressor_1(self._name_compressor1, plc1_1, plc1_2, plc2, plc3, plc4) t2 = time.time() # Title: PLC2 if self._flg_plc2: # plc1_1, plc1_2, plc2, plc3, plc4 = self.__routine_plc(self._tcp_plc2, 2) self.cliente.unit_id(self.id_plc2) plc1_1, plc1_2, plc2, plc3, plc4 = self.__routine_plc( self.cliente, 2) self._ecd.set_compressor_2(self._name_compressor2, plc1_1, plc1_2, plc2, plc3, plc4) self._ecd.set_realtime(True) t3 = time.time() # -- ERRORES self.sync_errors() # Title: Create json self._ecd.set_code_errors(self.status) data_dict, data_json = self._ecd.get_dict() # self.print_nice(self.status) self.update_status_connection() # Title: Base de datos self.__save_in_db(self._name) # Title: Mqtt t4 = time.time() self.__publish_mqtt(data_json) # self.__save_data(data_json) t5 = time.time() #print(data_json) # Title: Save in log if len(self._errors) > 0: self.__save_log( self._ecd.get_system_errors(self._errors, self.fecha, self.tiempo)) self._errors[:] = [] t6 = time.time() self.__save_times([t1 - t0, t2 - t1, t3 - t2, t5 - t4, t6 - t0]) self.__validate_data(data_dict) def run_loop(self): while True: self.run_once() time.sleep(self._scanrate) def print_nice(self, errors): os.system('cls') for i in range(0, len(names)): print("{1} --- {0}".format(names[i], errors[i])) print('Radio {} - PLC1 {} - PLC2 {} - BR20 {}'.format( self.tries_radio, self.tries_plc1, self.tries_plc2, self.tries_br20)) # print('Radio {} - PLC1 {} - BR20 {}'.format(self.tries_radio, self.tries_plc1, self.tries_br20)) time.sleep(0.5) def sync_errors(self): # PLCs if self._flg_plc1: self.status[1] = True if self.tries_plc1 >= 3 else False if self.status[1]: self.status[4] = False self.status[5] = False self.status[6] = False self.status[7] = False self.status[8] = False if self._flg_plc2: self.status[2] = True if self.tries_plc2 >= 3 else False if self.status[2]: self.status[9] = False self.status[10] = False self.status[11] = False self.status[12] = False self.status[13] = False if self._flg_br20: self.status[3] = True if self.tries_br20 >= 2 * 3 else False if self.status[3]: self.status[14] = False if self._flg_plc1 and self._flg_plc2 and self._flg_br20: # FIXME: se suma mas 6 por las dos vueltas del br20, hacer mejor calculo self.status[0] = True if self.tries_radio > 9 + 6 else False elif (self._flg_plc1 or self._flg_plc2) and self._flg_br20: self.status[0] = True if self.tries_radio > 6 + 6 else False if self.status[0]: for i in range(1, len(self.status)): self.status[i] = False def update_status_connection(self): try: db = sqlite3.connect(Address.DATABASE_FOLDER, ) c = db.cursor() tmp = list() for bit in self.status: bit = 1 if bit == True else 0 tmp.append(bit) sql = """UPDATE connection_status SET isConnected={}, isOnPLC1={}, isOnPLC2={}, isOnBR20={}, isOkCoil1={}, isOkHold1={}, isOkInputs1_1={}, isOkInputs1_2={}, isOkInputs1_3={}, isOkCoil2={}, isOkHold2={}, isOkInputs2_1={}, isOkInputs2_2={}, isOkInputs2_3={}, isOkSensors={}""".format( *tmp) sql = sql + " WHERE name='{}';".format(self._name) c.execute(sql) db.commit() db.close() time.sleep(0.1) except sqlite3.Error as e: print(self._name, 'DB - updating connection', e) def __save_in_db(self, table): try: db = sqlite3.connect(Address.DATABASE_FOLDER, ) c = db.cursor() data = self._ecd.get_lineal_dict() var = tuple(data.keys()) values = list() for i in range(0, len(var)): values.append(data[var[i]]) sql = "INSERT INTO {}{} VALUES({}?)".format( table, var, '?,' * (len(var) - 1)) c.execute(sql, values) db.commit() db.close() except Exception as e: print(self._name, 'DB - saving data', e) pass def __publish_mqtt(self, data): try: publish.single(self._topic, payload=data, keepalive=5, hostname=self._hostmqtt) # publish.single(self._topic, payload=data, keepalive=5, hostname="187.189.81.116") except socket.error as e: print(self._name, 'MQTT - sending data', e) self.__save_data(data) def __on_action_recive(self, client, userdata, message): print('Action recived') print(message.payload) def __subscribe_mqtt(self): try: # subscribe.simple(self._actions, hostname=self._hostmqtt, keepalive=5) subscribe.callback(self.__on_action_recive, self._actions, hostname=self._hostmqtt, keepalive=5) # TODO: El formato y las acciones a tomar. except Exception as e: print(self._name, 'MQTT - Subscription', e) def __validate_data(self, data): nulls = 0 if "compressor_1" in data: for value in data["compressor_1"].values(): if value == None: nulls += 1 if "compressor_2" in data: for value in data["compressor_2"].values(): if value == None: nulls += 1 if "well_1" in data: for value in data["well_1"].values(): if value == None: nulls += 1 if nulls < self.how_many_null: self.how_many_null = nulls self.json_ok = data def __save_data(self, data): with open(Address.DATA_FOLDER + 'data_{}.txt'.format(self._name), 'a+') as f: f.write(str(data) + '\n') def __save_data_daily(self): while True: time.sleep(5 * 60) if self.json_ok != None: self.json_ok = json.dumps(self.json_ok) with open( Address.BACKUP_DAILY_FOLDER + 'bc{}_{}.txt'.format( self.fecha.replace('-', ''), self._name), 'a+') as f: f.write(str(self.json_ok) + '\n') self.how_many_null = 100 self.json_ok = None def __save_log(self, data): with open(Address.LOGS_FOLDER + 'log_{}.txt'.format(self._name), 'a+') as f: f.write(str(data) + '\n') def __isEnableWifi(self): arg = "if netcat -z google.com 80; then echo \"Ok\"; else echo \"Noup\"; fi" p = Popen(arg, shell=True, stdout=PIPE) data = p.communicate()[0].split('\n')[0] if data == "Ok": return True else: return False def __save_times(self, data): with open(Address.LOGS_FOLDER + 'time_{}.txt'.format(self._name), 'a+') as f: f.write( 'FECHA {} {} | PLC1: {:.4f} | BR20: {:.4f} | PLC2: {:.4f} | Mqtt: {:.4f} | TOTAL: {:.4f}\n' .format(self.fecha, self.tiempo, data[0], data[1], data[2], data[3], data[4]))
# Convert the string to IEEE-754 s = "".join([binascii.a2b_hex(s) for s in hxstr.split()]) v = struct.unpack(">f", s)[0] return v try: c = ModbusClient(host="75.149.4.70", port=502) except ValueError: print "Error with host or port params" sys.exit() # The eGauge meter is set to ID 3 c.unit_id(3) # Turn on debug c.debug(True) # Try opening the TCP port c.open() # Try reading out line voltages if c.is_open(): # Read out 8 registers at once, this will pull out L1, L2, L1-L2 (L1-L2 is the measured RMS between L1 and L2 which is 240VAC) # Referring to the generated register map L1 RMS starts at address 500, L2 at 502 and L1-L2 at 506 # This will use Modbus function code 4 to read out mulitple input registers reg = c.read_input_registers(500, 8)
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)
import time SERVER_HOST = "localhost" SERVER_PORT = 50001 UTR = 10 c = ModbusClient() # Descomente para ver o TX - RX #c.debug(True) # Define modbus server host, porta c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(UTR) while True: # Conectando com MODBUS TCP if not c.is_open(): if not c.open(): print("Não foi possivel conectar com "+SERVER_HOST+":"+str(SERVER_PORT)+":"+str(UTR)) #(modbus function 0x03) if c.is_open(): regs = c.read_holding_registers(0,10) if regs: print("Registradores: "+str(regs)) # sleep 2s para o próximo polling time.sleep(2)
class SunnyBoy(): def __init__(self, ipOrHostName, portNumber): self.registers = SunnyBoyRegisters() self.mbClient = ModbusClient() self.mbClient.host(ipOrHostName) self.mbClient.port(portNumber) # Initialize with '1' and determine the correct Id by reading input register 42109 (see 'getSunnyBoyUnitID'). self.mbClient.unit_id(1) self.mbClient.open() getSunnyBoyUnitID(self.mbClient) self.dayYield = 0 self.totalYield = 0 self.currentOutput = 0 self.maxPeakOutputDay = 0 self.internalTemperature = 0 self.currentState = SunnyBoyConstants.STATE_UNKNOWN def shiftValue(self, regVal, sequenceSize): if regVal is None: return 0 if len(regVal) != sequenceSize: return 0 val = 0 for i in range(0, sequenceSize, 1): val |= regVal[i] if i < sequenceSize - 1: val <<= SunnyBoyConstants.MBREG_BITWIDTH if val == SunnyBoyConstants.NAN_VALUE: val = 0 return val def readCurrentValues(self): if not self.mbClient.is_open() and not self.mbClient.open(): print("Unable to connect to {}:{}".format(self.mbClient.host(), self.mbClient.port())) return False regVal_DayYield = self.mbClient.read_input_registers( self.registers.DAY_YIELD.Address, self.registers.DAY_YIELD.SequenceSize) regVal_TotalYield = self.mbClient.read_input_registers( self.registers.TOTAL_YIELD.Address, self.registers.TOTAL_YIELD.SequenceSize) regVal_CurrentOutput = self.mbClient.read_input_registers( self.registers.CURRENT_OUTPUT.Address, self.registers.CURRENT_OUTPUT.SequenceSize) regVal_InternalTemperature = self.mbClient.read_input_registers( self.registers.INTERNAL_TEMPERATURE.Address, self.registers.INTERNAL_TEMPERATURE.SequenceSize) regVal_CurrentState = self.mbClient.read_input_registers( self.registers.CURRENT_STATE.Address, self.registers.CURRENT_STATE.SequenceSize) self.dayYield = self.shiftValue(regVal_DayYield, self.registers.DAY_YIELD.SequenceSize) self.totalYield = self.shiftValue( regVal_TotalYield, self.registers.TOTAL_YIELD.SequenceSize) self.currentOutput = self.shiftValue( regVal_CurrentOutput, self.registers.CURRENT_OUTPUT.SequenceSize) self.internalTemperature = self.shiftValue( regVal_InternalTemperature, self.registers.INTERNAL_TEMPERATURE.SequenceSize) * 0.1 self.currentState = self.shiftValue( regVal_CurrentState, self.registers.CURRENT_STATE.SequenceSize) return True
class AcuvimIITCPMODBUS: def __init__(self, server_host, port, unit_id): self.c = ModbusClient() self.c.host(server_host) self.c.port(port) self.c.unit_id(unit_id) self.map = self.__import_map() def __import_map(self): with open('map.json') as json_file: return json.load(json_file) def __read_16_bit(self, address): if not self.c.is_open(): self.c.open() return self.c.read_holding_registers(address, 1)[0] def __read_32_bit(self, address, number=1): if not self.c.is_open(): self.c.open() reg_l = self.c.read_holding_registers(address, number * 2) if reg_l: return [ utils.decode_ieee(f) for f in utils.word_list_to_long(reg_l) ][0] else: return None def __what_is_the_access_property(self, dict): if dict['Access Property'] == 'R': return 0 if dict['Access Property'] == 'W': return 2 else: return 1 def __get_registry(self, dict): if dict['Data Type'] == 'Word': return (self.__read_16_bit(dict["Address(D)"])) elif dict['Data Type'] == 'Float': return (self.__read_32_bit(dict["Address(D)"])) elif dict['Data Type'] == 'Dword': return (self.__read_32_bit(dict["Address(D)"])) elif dict['Data Type'] == 'int': return (self.__read_16_bit(dict["Address(D)"])) elif dict['Data Type'] == 'Bit': return (self.__read_16_bit(dict["Address(D)"])) def get_clock(self): if not self.c.is_open(): self.c.open() read_datetime = self.c.read_holding_registers(4159, 7) return datetime.datetime(read_datetime[1], read_datetime[2], read_datetime[3], read_datetime[4], read_datetime[5], read_datetime[6]) def read_value(self, parameter=None, address=None): if parameter is not None: temp_dict = list( filter(lambda d: d['Parameter'] == parameter, self.map)) if not len(temp_dict) == 0 and self.__what_is_the_access_property( temp_dict[0]) <= 1: return (self.__get_registry(temp_dict[0])) elif address is not None: temp_dict = list( filter(lambda d: d['Address(D)'] == address, self.map)) if not len(temp_dict) == 0 and self.__what_is_the_access_property( temp_dict) <= 1: return (self.__get_registry(temp_dict[0])) else: return None
class modbusTCP_Slave: # Working Modes RESULT_MODE__RETURN_ALL_VALUES__RAW = 0 RESULT_MODE__RETURN_ALL_VALUES__FORMATTED = 1 RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW = 2 RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED = 3 def __init__(self, _jsonFile, _resultMode=0): # JSON object with the information of the Modbus Master device self.deviceHost = _jsonFile["host"] self.devicePort = _jsonFile["port"] self.deviceData = _jsonFile["data"] # Result Mode self.resultMode = int(_resultMode) # For Polling Process self.deviceData_LastValues = "" self.deviceData_CurrentValues = "" # Connect with Modbus Server def SetupPollingProcess(self): # Initialize deviceData values for data_point in self.deviceData: data_point["value"] = 0 try: # Create Client self.client = ModbusClient() self.client.host(self.deviceHost) self.client.port(self.devicePort) self.client.unit_id(1) except ValueError as e: # Problems accessing Modbus Server return -1 # Initialize copies of data self.deviceData_LastValues = copy.deepcopy(self.deviceData) self.deviceData_CurrentValues = copy.deepcopy(self.deviceData) # Setup process OK return 0 # Poll data from Modbus Master device def PollDataFromDevice(self): # Open or reconnect TCP to server if not self.client.is_open(): if not self.client.open(): return -1 if self.client.is_open(): # Go through data and act correspondingly for data_point in self.deviceData_CurrentValues: addr = data_point["address"] if data_point["type"] == "coil": read_data = self.client.read_coils(addr, 1) if read_data != None: data_point["value"] = read_data elif data_point["type"] == "register": read_data = self.client.read_holding_registers(addr, 1) if read_data != None: data_point["value"] = read_data ### Process Data and return it depending on Working Mode # RESULT_MODE__RETURN_ALL_VALUES__RAW ==> 0 # RESULT_MODE__RETURN_ALL_VALUES__FORMATTED ==> 0 # RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW ==> 0 # RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED ==> 0 ################################################################## if (self.resultMode == self.RESULT_MODE__RETURN_ALL_VALUES__RAW): # All data - RAW return self.deviceData_CurrentValues elif (self.resultMode == self.RESULT_MODE__RETURN_ALL_VALUES__FORMATTED): # All data - FORMATTED return self.__formatDataValue(self.deviceData_CurrentValues) else: # Check for new values newValues = self.__checkForNewValues( self.deviceData_LastValues, self.deviceData_CurrentValues) # Copy of the latest received data self.deviceData_LastValues = copy.deepcopy( self.deviceData_CurrentValues) # Process new values, if there is any if (newValues != []): # RAW or FORMATTED? if (self.resultMode == self.RESULT_MODE__RETURN_ONLY_NEW_VALUES__RAW): return newValues elif (self.resultMode == self.RESULT_MODE__RETURN_ONLY_NEW_VALUES__FORMATTED): return self.__formatDataValue(newValues) else: return [] # Format RAW data according to this template # [ 07/16/20 @ 12:48:06 - 126 ] ---> localhost @ Port: 11503 ==> Value: False from coil at address: 1520 def __formatDataValue(self, values): # Prepare timestamp temp = datetime.datetime.now() x = temp.strftime("%x") y = temp.strftime("%X") z = temp.strftime("%f") timestamp = "[ " + x + " @ " + y + " - " + z[:3] + " ]" result = [] for data_point in values: # Prepare value value = str(data_point["value"][0]).rjust(5) # Format information formattedValue = (str(timestamp) + " ---> " + str(self.deviceHost) + " @ Port: " + str(self.devicePort) + " ==> Value: " + value + " from " + (data_point["type"]).rjust(8) + " at address: " + str(data_point["address"])) result.append(formattedValue) return result # Check if latest polled data is new # Only new data will be taken into account def __checkForNewValues(self, lastValues, currentValues): # Temp array newValues = [] for current_DP in currentValues: # Check if the value changed for last_DP in lastValues: if (last_DP["type"] == current_DP["type"]) and ( last_DP["address"] == current_DP["address"]) and ( last_DP["value"] != current_DP["value"]): # --- New value newValues.append(current_DP) return newValues
#!/usr/bin/python2.7 from pyModbusTCP.client import ModbusClient import rrdtool import time # some consts RRD_REFRESH = 1.0 # refresh RRD every 1s RRD_POS = "/home/pi/rrd/pos.rrd" RRD_FLOW = "/home/pi/rrd/flow.rrd" RRD_SP = "/home/pi/rrd/setpoint.rrd" c=ModbusClient() #c.debug(1) c.host("163.111.184.31") c.unit_id(33) while(True): # keep TCP link open if not c.is_open(): c.open() if c.is_open(): # loop start time start = time.time() # #20506 r = c.read_holding_registers(20506) if r: ret = rrdtool.update(RRD_POS, 'N:%d' % r[0]) # #20492 r = c.read_holding_registers(20492) if r:
SERVER_HOST = "192.168.1.20" SERVER_PORT = 502 SERVER_U_ID = 1 c = ModbusClient() c2 = ModbusClient() # uncomment this line to see debug message # c.debug(True) # define modbus server host, port and unit_id c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_U_ID) c2.host("192.168.1.30") c2.port(502) c2.unit_id(1) c2.open() c2.close() cmds = ["config switch physical-port", "edit port4", "set status down", "end"] exec_ssh_cmds(cmds) # open or reconnect TCP to server if not c.is_open(): if not c.open(): print("unable to connect to " + SERVER_HOST + ":" + str(SERVER_PORT))
class Modbus(): def __init__(self, smarthome, gateway_ip, gateway_port=502, gateway_id=1, update_cycle=60): logger.info("Modbus: init plugin") self._sh = smarthome self._gateway_id = int(gateway_id) self._update_cycle = int(update_cycle) self._keylist = {} #self._client = ModbusTcpClient(gateway_ip,port=gateway_port) self._client = ModbusClient(host=gateway_ip, port=gateway_port, auto_open=True, auto_close=True) self._client.unit_id(2) self._client.debug(True) if not self._client.is_open(): if not self._client.open(): logger.error("Modbus: connection to gateway can not be established") else: logger.info("Modbus: connection to gateway established") self._client.close() def run(self): self.alive = True self._sh.scheduler.add('MODBUS', self._update_values, prio=5, cycle=self._update_cycle) def stop(self): self.alive = False self._sh.scheduler.remove('MODBUS') def parse_item(self, item): if 'modbus_gateway_id' in item.conf: gateid = int(item.conf['modbus_gateway_id']) else: gateid = 1 if gateid != self._gateway_id: #logger.debug("Modbus: parse item error (gateway_id is not configured as plugin): {0}".format(item)) return None if 'modbus_cmd' not in item.conf: #logger.debug("Modbus: parse item error (modbus_cmd missing): {0}".format(item)) return None if 'modbus_scaling' not in item.conf: #logger.debug("Modbus: parse item error (modbus_scaling missing): {0}".format(item)) return None if 'modbus_register' in item.conf: logger.debug("Modbus: parse item: {0}".format(item)) register = item.conf['modbus_register'] if not register in self._keylist: self._keylist[register] = {'items': [item], 'logics': []} else: self._keylist[register]['items'].append(item) return None # return self.update_item #else: # return None def parse_logic(self, logic): pass def _update_values(self): for register in self._keylist: for item in self._keylist[register]['items']: if int(item.conf['modbus_cmd']) == 4: reg_list = self._client.read_input_registers(int(item.conf['modbus_register'])-30001, 1) logger.info("Modbus: Plain value: {}".format(str(reg_list[0]))) if reg_list is None: return None if len(reg_list) > 0: phys_value = reg_list[0] / (int(item.conf['modbus_scaling']))# * pow(10, int(item.conf['modbus_decimal'])) logger.info("Modbus: Physical value: {0}".format(phys_value)) item(phys_value, 'MODBUS', ' {0}'.format(phys_value)) elif int(item.conf['modbus_cmd']) == 6: sendvalue = int(item()*int(item.conf['modbus_scaling'])) reg_list = self._client.write_single_register(int(item.conf['modbus_register'])-40001, sendvalue) if not reg_list: logger.info("Modbus: Error writing register") def update_item(self, item, caller=None, source=None, dest=None): if caller != 'MODBUS': logger.info("update item: {0}".format(item.id())) if int(item.conf['modbus_cmd']) == 4: reg_list = self._client.read_input_registers(int(item.conf['modbus_register'])-30001, 1) logger.info("Modbus: Plain value: {}".format(str(reg_list[0]))) if reg_list is None: return None if len(reg_list) > 0: phys_value = reg_list[0] / (int(item.conf['modbus_scaling']))# * pow(10, int(item.conf['modbus_decimal'])) logger.info("Modbus: Physical value: {0}".format(phys_value)) item(phys_value, 'MODBUS', ' {0}'.format(phys_value))
from pyModbusTCP.client import ModbusClient import time SERVER_HOST = "localhost" SERVER_PORT = 502 SERVER_U_ID = 1 c = ModbusClient() # uncomment this line to see debug message # c.debug(True) # define modbus server host, port and unit_id c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_U_ID) while True: # open or reconnect TCP to server if not c.is_open(): if not c.open(): print("unable to connect to " + SERVER_HOST + ":" + str(SERVER_PORT)) # if open() is ok, read coils (modbus function 0x01) if c.is_open(): # read 10 bits at address 0, store result in regs list bits = c.read_coils(0, 10) # if success display registers if bits: print("bit ad #0 to 9: " + str(bits))
change_state(bpi_sorted[1])#second least imp load else if(f<49.1 or v<0.91) change_state(bpi_sorted[2])#third least imp load else if(f<48.8 pt v<0.88) change_state(bpi_sorted[3])#third least imp load or most imp load else state_val=[1,1,1,1] #engage all loads inteface_relay() return #Decision code ends----------------------------------------------------------------------------------------------- #schneider sensor interface code begins--------------------------------------------------------------------------- c = ModbusClient() c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_UNIT_ID) #default slave id for schneider is 100 if not c.is_open(): if not c.open(): print("cannot connect ....") if c.is_open(): #read_holding_registers has an offset of 4000 to begin with while True: voltage_a=c.read_holding_registers(166,1)#list output for integer take voltage_a[0] voltage_a=voltage_a[0] current_a=c.read_holding_registers(150,1) current_a=current_a[0] real_power_a=c.read_holding_registers(198,1) real_power_a=real_power_a[0] reactive_power_a=c.read_holding_registers(208,1)
def send_data(): SERVER_HOST = "169.254.0.12" SERVER_PORT = 502 #this has to be 502 for tcp/ip modbus SERVER_UNIT_ID = 100 #slave id is 100 for schneider powerlogic ion 7650 #default value for ionmeter #subnet mask= 255.240.0.0 #gateway= 0.0.0.0 #Required Registers to be read :- #Va= 40166 2 registers ie. c.read_input_registers(40166,2) #power kw a = 40198 2 registers #kVAR a= 40208 2 registers #kVA a= 40218 2 registers #frequency = 40159 1 register #Ia= 40150 1 register #this function reads the float value for address and number of bits (not required) #def read_float( address, number=1): # reg_l = c.read_holding_registers(address, number ) #can change to read_input_registers just to check # if reg_l: # return [utils.decode_ieee(f) for f in utils.word_list_to_long(reg_l)] # else: # return None c = ModbusClient() c.host(SERVER_HOST) c.port(SERVER_PORT) c.unit_id(SERVER_UNIT_ID) #default slave id for schneider is 100 if not c.is_open(): if not c.open(): print("cannot connect ....") if c.is_open(): #read_holding_registers has an offset of 4000 to begin with while True: voltage_a=c.read_holding_registers(166,1)#list output for integer take voltage_a[0] #voltage_a=voltage_a[0] #print voltage_a current_a=c.read_holding_registers(150,1) #current_a=current_a[0] #print current_a real_power_a=c.read_holding_registers(208,1) #real_power_a=real_power_a[0] #print real_power_a reactive_power_a=c.read_holding_registers(218,1) #reactive_power_a=reactive_power_a[0] #print reactive_power_a apparent_power_a=c.read_holding_registers(218,1) #apparent_power_a=apparent_power_a[0] #print apparent_power_a freq=c.read_holding_registers(159,1) freq=freq[0]/10 #print freq np.array(voltage_a,dtype=float) np.array(current_a,dtype=float) np.array(real_power_a,dtype=float) np.array(reactive_power_a,dtype=float) np.array(apparent_power_a,dtype=float) np.array(freq,dtype=float) data = { "voltage_reading" : voltage_a, "current_reading" : current_a, "real_power_rating" : real_power_a, "reactive_power_rating" : reactive_power_a, "apparent_power_rating" : apparent_power_a, "frequency_reading" : freq } print (data) return data
def __init__(self, address, port, mode): c = ModbusClient() c.host(address) c.port(port) c.unit_id(1) c.open() if (mode == "volt"): voltAmper = c.read_input_registers(0, 55) c.close() if voltAmper: self.v1 = (voltAmper[0] << 16 | voltAmper[1]) / 10 self.v2 = (voltAmper[2] << 16 | voltAmper[3]) / 10 self.v3 = (voltAmper[4] << 16 | voltAmper[5]) / 10 self.vavg = (voltAmper[6] << 16 | voltAmper[7]) / 10 self.vun = (voltAmper[8] << 16 | voltAmper[9]) / 10 self.v12 = (voltAmper[10] << 16 | voltAmper[11]) / 10 self.v23 = (voltAmper[12] << 16 | voltAmper[13]) / 10 self.v31 = (voltAmper[14] << 16 | voltAmper[15]) / 10 self.i1 = (voltAmper[16] << 16 | voltAmper[17]) / 10 self.i2 = (voltAmper[18] << 16 | voltAmper[19]) / 10 self.i3 = (voltAmper[20] << 16 | voltAmper[21]) / 10 self.iavg = (voltAmper[22] << 16 | voltAmper[23]) / 10 self.inut = (voltAmper[24] << 16 | voltAmper[25]) / 10 self.ptot = (voltAmper[44] << 16 | voltAmper[45]) / 10 self.qtot = (voltAmper[46] << 16 | voltAmper[47]) / 10 self.stot = (voltAmper[48] << 16 | voltAmper[49]) / 10 self.temperature = (voltAmper[54]) / 10 self.error = False else: print("Read Volt And Amper ERROR") if (mode == "counter"): Counter = c.read_input_registers(70, 36) print(dbname + ":") c.close() if Counter: self.peakA1 = (Counter[0] << 32 | Counter[1] << 16 | Counter[2]) self.peakP1 = (Counter[3] << 32 | Counter[4] << 16 | Counter[5]) self.peakA2 = (Counter[6] << 32 | Counter[7] << 16 | Counter[8]) self.peakP2 = (Counter[9] << 32 | Counter[10] << 16 | Counter[11]) self.normalA1 = (Counter[12] << 32 | Counter[13] << 16 | Counter[14]) self.normalP1 = (Counter[15] << 32 | Counter[16] << 16 | Counter[17]) self.normalA2 = (Counter[18] << 32 | Counter[19] << 16 | Counter[20]) self.normalP2 = (Counter[21] << 32 | Counter[22] << 16 | Counter[23]) self.lowA1 = (Counter[24] << 32 | Counter[25] << 16 | Counter[26]) self.lowP1 = (Counter[27] << 32 | Counter[28] << 16 | Counter[29]) self.lowA2 = (Counter[30] << 32 | Counter[31] << 16 | Counter[32]) self.lowP2 = (Counter[33] << 32 | Counter[34] << 16 | Counter[35]) self.CounterA1 = self.peakA1 + self.normalA1 + self.lowA1 self.CounterP1 = self.peakP1 + self.normalP1 + self.lowP1 self.CounterA2 = self.peakA2 + self.normalA2 + self.lowA2 self.CounterP2 = self.peakP2 + self.normalP2 + self.lowP2 self.error = False else: self.error = True print("Read Counter ERROR")