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)
Example #2
0
 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 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)
Example #4
0
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
Example #5
0
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
Example #6
0
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
Example #8
0
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
Example #9
0
        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
Example #10
0
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
Example #11
0
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]))
Example #12
0
    # 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)
Example #13
0
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)
Example #14
0
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)
Example #15
0
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
Example #16
0
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
Example #17
0
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
Example #18
0
#!/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))
Example #20
0
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))
Example #21
0
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))
Example #22
0
		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)
Example #23
0
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
Example #24
0
File: w106.py Project: shtir/PQA
    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")