def encode_field(self, value, mb_type='unit16'):
     builder = BinaryPayloadBuilder(endian=self.endian)
     if mb_type == 'bit' or mb_type == 'bits':
         builder.add_bits(value)
     elif mb_type == 'uint8':
         builder.add_8bit_uint(value)
     elif mb_type == 'uint16':
         builder.add_16bit_uint(value)
     elif mb_type == 'uint32':
         builder.add_32bit_uint(value)
     elif mb_type == 'uint64':
         builder.add_64bit_uint(value)
     elif mb_type == 'int8':
         builder.add_8bit_int(value)
     elif mb_type == 'int16':
         builder.add_16bit_int(value)
     elif mb_type == 'int32':
         builder.add_32bit_int(value)
     elif mb_type == 'int64':
         builder.add_64bit_int(value)
     elif mb_type == 'float32':
         builder.add_32bit_float(value)
     elif mb_type == 'float64':
         builder.add_64bit_float(value)
     elif mb_type == 'string' or mb_type == 'str':
         builder.add_string(value)
     else:
         log.warn('Not supported DataType: "%s"' % mb_type)
     return builder.build()
Exemplo n.º 2
0
def run_payload_server():
    # ----------------------------------------------------------------------- #
    # build your payload
    # ----------------------------------------------------------------------- #
    builder = BinaryPayloadBuilder(byteorder=Endian.Little,
                                   wordorder=Endian.Little)
    builder.add_string('abcdefgh')
    builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
    builder.add_8bit_int(-0x12)
    builder.add_8bit_uint(0x12)
    builder.add_16bit_int(-0x5678)
    builder.add_16bit_uint(0x1234)
    builder.add_32bit_int(-0x1234)
    builder.add_32bit_uint(0x12345678)
    builder.add_16bit_float(12.34)
    builder.add_16bit_float(-12.34)
    builder.add_32bit_float(22.34)
    builder.add_32bit_float(-22.34)
    builder.add_64bit_int(-0xDEADBEEF)
    builder.add_64bit_uint(0x12345678DEADBEEF)
    builder.add_64bit_uint(0xDEADBEEFDEADBEED)
    builder.add_64bit_float(123.45)
    builder.add_64bit_float(-123.45)

    
    # ----------------------------------------------------------------------- #
    # use that payload in the data store
    # ----------------------------------------------------------------------- #
    # Here we use the same reference block for each underlying store.
    # ----------------------------------------------------------------------- #
    
    block = ModbusSequentialDataBlock(1, builder.to_registers())
    store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block)
    context = ModbusServerContext(slaves=store, single=True)
    
    # ----------------------------------------------------------------------- #
    # initialize the server information
    # ----------------------------------------------------------------------- #
    # If you don't set this or any fields, they are defaulted to empty strings.
    # ----------------------------------------------------------------------- #
    identity = ModbusDeviceIdentification()
    identity.VendorName = 'Pymodbus'
    identity.ProductCode = 'PM'
    identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
    identity.ProductName = 'Pymodbus Server'
    identity.ModelName = 'Pymodbus Server'
    identity.MajorMinorRevision = version.short()
    # ----------------------------------------------------------------------- #
    # run the server you want
    # ----------------------------------------------------------------------- #
    StartTcpServer(context, identity=identity, address=("localhost", 5020))
Exemplo n.º 3
0
def run_payload_server():
    # ----------------------------------------------------------------------- #
    # build your payload
    # ----------------------------------------------------------------------- #
    builder = BinaryPayloadBuilder(byteorder=Endian.Little,
                                   wordorder=Endian.Little)
    builder.add_string('abcdefgh')
    builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
    builder.add_8bit_int(-0x12)
    builder.add_8bit_uint(0x12)
    builder.add_16bit_int(-0x5678)
    builder.add_16bit_uint(0x1234)
    builder.add_32bit_int(-0x1234)
    builder.add_32bit_uint(0x12345678)
    builder.add_32bit_float(22.34)
    builder.add_32bit_float(-22.34)
    builder.add_64bit_int(-0xDEADBEEF)
    builder.add_64bit_uint(0x12345678DEADBEEF)
    builder.add_64bit_uint(0xDEADBEEFDEADBEED)
    builder.add_64bit_float(123.45)
    builder.add_64bit_float(-123.45)

    
    # ----------------------------------------------------------------------- #
    # use that payload in the data store
    # ----------------------------------------------------------------------- #
    # Here we use the same reference block for each underlying store.
    # ----------------------------------------------------------------------- #
    
    block = ModbusSequentialDataBlock(1, builder.to_registers())
    store = ModbusSlaveContext(di=block, co=block, hr=block, ir=block)
    context = ModbusServerContext(slaves=store, single=True)
    
    # ----------------------------------------------------------------------- #
    # initialize the server information
    # ----------------------------------------------------------------------- #
    # If you don't set this or any fields, they are defaulted to empty strings.
    # ----------------------------------------------------------------------- #
    identity = ModbusDeviceIdentification()
    identity.VendorName = 'Pymodbus'
    identity.ProductCode = 'PM'
    identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
    identity.ProductName = 'Pymodbus Server'
    identity.ModelName = 'Pymodbus Server'
    identity.MajorMinorRevision = '1.5'
    # ----------------------------------------------------------------------- #
    # run the server you want
    # ----------------------------------------------------------------------- #
    StartTcpServer(context, identity=identity, address=("localhost", 5020))
Exemplo n.º 4
0
 def testBigEndianPayloadBuilder(self):
     ''' Test basic bit message encoding/decoding '''
     builder = BinaryPayloadBuilder(endian=Endian.Big)
     builder.add_8bit_uint(1)
     builder.add_16bit_uint(2)
     builder.add_32bit_uint(3)
     builder.add_64bit_uint(4)
     builder.add_8bit_int(-1)
     builder.add_16bit_int(-2)
     builder.add_32bit_int(-3)
     builder.add_64bit_int(-4)
     builder.add_32bit_float(1.25)
     builder.add_64bit_float(6.25)
     builder.add_string(b'test')
     builder.add_bits(self.bitstring)
     self.assertEqual(self.big_endian_payload, builder.to_string())
 def testLittleEndianPayloadBuilder(self):
     ''' Test basic bit message encoding/decoding '''
     builder = BinaryPayloadBuilder(endian=Endian.Little)
     builder.add_8bit_uint(1)
     builder.add_16bit_uint(2)
     builder.add_32bit_uint(3)
     builder.add_64bit_uint(4)
     builder.add_8bit_int(-1)
     builder.add_16bit_int(-2)
     builder.add_32bit_int(-3)
     builder.add_64bit_int(-4)
     builder.add_32bit_float(1.25)
     builder.add_64bit_float(6.25)
     builder.add_string('test')
     builder.add_bits(self.bitstring)
     self.assertEqual(self.little_endian_payload, str(builder))
Exemplo n.º 6
0
 def testLittleEndianPayloadBuilder(self):
     ''' Test basic bit message encoding/decoding '''
     builder = BinaryPayloadBuilder(endian=Endian.Little)
     builder.add_8bit_uint(1)
     builder.add_16bit_uint(2)
     builder.add_32bit_uint(3)
     builder.add_64bit_uint(4)
     builder.add_8bit_int(-1)
     builder.add_16bit_int(-2)
     builder.add_32bit_int(-3)
     builder.add_64bit_int(-4)
     builder.add_32bit_float(1.25)
     builder.add_64bit_float(6.25)
     builder.add_string('test')
     builder.add_bits(self.bitstring)
     self.assertEqual(self.little_endian_payload, str(builder))
Exemplo n.º 7
0
    def write_register(self,register_name,value, unit=None):
        """
        :param register_name: register key from holding register dictionary
            generated by yaml config
        :param value: value to write to register
        :returns: -- Nothing
        """
        # TODO add the ability to discern which settings will be appropriate for
        # the device that is being written to
        if (unit is None):
            unit = self.UNIT_ID
        '''
        builder = BinaryPayloadBuilder(byteorder=self.BYTE_ORDER,
            wordorder=self.WORD_ORDER_DICT[unit])
        '''
        builder = BinaryPayloadBuilder(byteorder=self.BYTE_ORDER_DICT[unit],
            wordorder=self.WORD_ORDER_DICT[unit])
        # This will change depending on the device that is being connected
        # potentially so it has to be correleated to the device ID

        if (self.holding_register_dict[register_name][1] == '8int'):
            builder.add_8bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '8uint'):
            builder.add_8bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '16int'):
            builder.add_16bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '16uint'):
            builder.add_16bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '32int'):
            builder.add_32bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '32uint'):
            builder.add_32bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '32float'):
            builder.add_32bit_float(value)
        elif (self.holding_register_dict[register_name][1] == '64int'):
            builder.add_64bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '64uint'):
            builder.add_64bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '64float'):
            builder.add_64bit_float(value)
        else:
            print("Bad type")
            exit()
        payload = builder.build()
        self.client.write_registers(self.holding_register_dict[register_name][0],
            payload, skip_encode=True, unit = self.UNIT_ID)
Exemplo n.º 8
0
 def testLittleEndianPayloadBuilder(self):
     """ Test basic bit message encoding/decoding """
     builder = BinaryPayloadBuilder(byteorder=Endian.Little,
                                    wordorder=Endian.Little)
     builder.add_8bit_uint(1)
     builder.add_16bit_uint(2)
     builder.add_32bit_uint(3)
     builder.add_64bit_uint(4)
     builder.add_8bit_int(-1)
     builder.add_16bit_int(-2)
     builder.add_32bit_int(-3)
     builder.add_64bit_int(-4)
     builder.add_32bit_float(1.25)
     builder.add_64bit_float(6.25)
     builder.add_16bit_uint(1)      # placeholder
     builder.add_string(b'test')
     builder.add_bits(self.bitstring)
     self.assertEqual(self.little_endian_payload, builder.to_string())
Exemplo n.º 9
0
 def testLittleEndianPayloadBuilder(self):
     """ Test basic bit message encoding/decoding """
     builder = BinaryPayloadBuilder(byteorder=Endian.Little,
                                    wordorder=Endian.Little)
     builder.add_8bit_uint(1)
     builder.add_16bit_uint(2)
     builder.add_32bit_uint(3)
     builder.add_64bit_uint(4)
     builder.add_8bit_int(-1)
     builder.add_16bit_int(-2)
     builder.add_32bit_int(-3)
     builder.add_64bit_int(-4)
     builder.add_32bit_float(1.25)
     builder.add_64bit_float(6.25)
     builder.add_16bit_uint(1)      # placeholder
     builder.add_string(b'test')
     builder.add_bits(self.bitstring)
     self.assertEqual(self.little_endian_payload, builder.to_string())
Exemplo n.º 10
0
 def set_value(self, value):
     if value is not None:
         builder = BinaryPayloadBuilder(byteorder=self.byteorder,
                                        wordorder=self.wordorder)
         if self.encoding in ['int8', 'uint8']:
             builder.add_8bit_int(
                 value
             ) if self.encoding == 'int8' else builder.add_8bit_uint(
                 value)
         elif self.encoding in ['int16', 'uint16']:
             builder.add_16bit_int(
                 value
             ) if self.encoding == 'int16' else builder.add_16bit_uint(
                 value)
         elif self.encoding in ['int32', 'uint32']:
             builder.add_32bit_int(
                 value
             ) if self.encoding == 'int32' else builder.add_32bit_uint(
                 value)
         elif self.encoding in ['float32', 'float64']:
             builder.add_32bit_float(
                 value
             ) if self.encoding == 'float32' else builder.add_64bit_float(
                 value)
         elif self.encoding in ['int64', 'uint64']:
             builder.add_64bit_int(
                 value
             ) if self.encoding == 'int64' else builder.add_64bit_uint(
                 value)
         elif self.encoding == 'boolean':
             builder.add_16bit_uint(value)
         elif self.encoding == 'string':
             builder.add_string(value)
         else:
             log.error("Unhandled encoding exception {enc}".format(
                 enc=self.encoding))
         payload = builder.to_registers()
         log.info(
             "Setting {type} {addr} to {enc} {val} as {list}".format(
                 type=self.type,
                 addr=self.address,
                 enc=self.encoding,
                 val=value,
                 list=str(payload)))
         self.parent.context.setValues(self.get_function_code(),
                                       self.address, payload)
         self.value = value
     else:
         log.warning(
             "Attempt to set {type} {addr} to None (default={default})".
             format(type=self.type,
                    addr=self.address,
                    default=self.default))
Exemplo n.º 11
0
    def write_register(self,register_name,value, unit=None):
        """
        :param register_name: register key from holding register dictionary
            generated by yaml config
        :param value: value to write to register
        :returns: -- Nothing
        """
        if (unit is None):
            unit = self.UNIT_ID

        builder = BinaryPayloadBuilder(byteorder=self.BYTE_ORDER,
            wordorder=self.WORD_ORDER)
        if (self.holding_register_dict[register_name][1] == '8int'):
            builder.add_8bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '8uint'):
            builder.add_8bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '16int'):
            builder.add_16bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '16uint'):
            builder.add_16bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '32int'):
            builder.add_32bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '32uint'):
            builder.add_32bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '32float'):
            builder.add_32bit_float(value)
        elif (self.holding_register_dict[register_name][1] == '64int'):
            builder.add_64bit_int(value)
        elif (self.holding_register_dict[register_name][1] == '64uint'):
            builder.add_64bit_uint(value)
        elif (self.holding_register_dict[register_name][1] == '64float'):
            builder.add_64bit_float(value)
        else:
            print("Bad type")
            exit()
        payload = builder.build()
        self.client.write_registers(self.holding_register_dict[register_name][0], payload, skip_encode=True, unit = self.UNIT_ID)
Exemplo n.º 12
0
    def convert(self, config, data):
        byte_order = config["byteOrder"] if config.get("byteOrder") else "LITTLE"
        if byte_order == "LITTLE":
            builder = BinaryPayloadBuilder(byteorder=Endian.Little)
        elif byte_order == "BIG":
            builder = BinaryPayloadBuilder(byteorder=Endian.Big)
        else:
            log.warning("byte order is not BIG or LITTLE")
            return
        reg_count = config.get("registerCount", 1)
        value = config["value"]
        if config.get("tag") is not None:
            tags = (findall('[A-Z][a-z]*', config["tag"]))
            if "Coil" in tags:
                builder.add_bits(value)
            elif "String" in tags:
                builder.add_string(value)
            elif "Double" in tags:
                if reg_count == 4:
                    builder.add_64bit_float(value)
                else:
                    log.warning("unsupported amount of registers with double type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            elif "Float" in tags:
                if reg_count == 2:
                    builder.add_32bit_float(value)
                else:
                    log.warning("unsupported amount of registers with float type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            elif "Integer" in tags or "DWord" in tags or "DWord/Integer" in tags or "Word" in tags:
                if reg_count == 1:
                    builder.add_16bit_int(value)
                elif reg_count == 2:
                    builder.add_32bit_int(value)
                elif reg_count == 4:
                    builder.add_64bit_int(value)
                else:
                    log.warning("unsupported amount of registers with integer/word/dword type for device %s in Downlink converter",
                                self.__config["deviceName"])
                    return
            else:
                log.warning("unsupported hardware data type for device %s in Downlink converter",
                            self.__config["deviceName"])

        if config.get("bit") is not None:
            bits = [0 for _ in range(8)]
            bits[config["bit"]-1] = int(value)
            log.debug(bits)
            builder.add_bits(bits)
            return builder.to_string()

        if config["functionCode"] in [5, 15]:
            return builder.to_coils()
        elif config["functionCode"] in [6, 16]:
            return builder.to_registers()
        else:
            log.warning("Unsupported function code,  for device %s in Downlink converter",
                        self.__config["deviceName"])
        return
Exemplo n.º 13
0
def run_binary_payload_ex():
    # ----------------------------------------------------------------------- #
    # We are going to use a simple client to send our requests
    # ----------------------------------------------------------------------- #
    client = ModbusClient('127.0.0.1', port=5020)
    client.connect()
    
    # ----------------------------------------------------------------------- #
    # If you need to build a complex message to send, you can use the payload
    # builder to simplify the packing logic.
    #
    # Here we demonstrate packing a random payload layout, unpacked it looks
    # like the following:
    #
    # - a 8 byte string 'abcdefgh'
    # - a 32 bit float 22.34
    # - a 16 bit unsigned int 0x1234
    # - another 16 bit unsigned int 0x5678
    # - an 8 bit int 0x12
    # - an 8 bit bitstring [0,1,0,1,1,0,1,0]
    # - an 32 bit uint 0x12345678
    # - an 32 bit signed int -0x1234
    # - an 64 bit signed int 0x12345678

    # The packing can also be applied to the word (wordorder) and bytes in each
    # word (byteorder)

    # The wordorder is applicable only for 32 and 64 bit values
    # Lets say we need to write a value 0x12345678 to a 32 bit register

    # The following combinations could be used to write the register

    # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
    # Word Order - Big                      Byte Order - Big
    # word1 =0x1234 word2 = 0x5678

    # Word Order - Big                      Byte Order - Little
    # word1 =0x3412 word2 = 0x7856

    # Word Order - Little                   Byte Order - Big
    # word1 = 0x5678 word2 = 0x1234

    # Word Order - Little                   Byte Order - Little
    # word1 =0x7856 word2 = 0x3412
    # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #

    # ----------------------------------------------------------------------- #
    builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                   wordorder=Endian.Little)
    builder.add_string('abcdefgh')
    builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
    builder.add_8bit_int(-0x12)
    builder.add_8bit_uint(0x12)
    builder.add_16bit_int(-0x5678)
    builder.add_16bit_uint(0x1234)
    builder.add_32bit_int(-0x1234)
    builder.add_32bit_uint(0x12345678)
    builder.add_32bit_float(22.34)
    builder.add_32bit_float(-22.34)
    builder.add_64bit_int(-0xDEADBEEF)
    builder.add_64bit_uint(0x12345678DEADBEEF)
    builder.add_64bit_uint(0x12345678DEADBEEF)
    builder.add_64bit_float(123.45)
    builder.add_64bit_float(-123.45)
    payload = builder.to_registers()
    print("-" * 60)
    print("Writing Registers")
    print("-" * 60)
    print(payload)
    print("\n")
    payload = builder.build()
    address = 0
    # Can write registers
    # registers = builder.to_registers()
    # client.write_registers(address, registers, unit=1)

    # Or can write encoded binary string
    client.write_registers(address, payload, skip_encode=True, unit=1)
    # ----------------------------------------------------------------------- #
    # If you need to decode a collection of registers in a weird layout, the
    # payload decoder can help you as well.
    #
    # Here we demonstrate decoding a random register layout, unpacked it looks
    # like the following:
    #
    # - a 8 byte string 'abcdefgh'
    # - a 32 bit float 22.34
    # - a 16 bit unsigned int 0x1234
    # - another 16 bit unsigned int which we will ignore
    # - an 8 bit int 0x12
    # - an 8 bit bitstring [0,1,0,1,1,0,1,0]
    # ----------------------------------------------------------------------- #
    address = 0x0
    count = len(payload)
    result = client.read_holding_registers(address, count,  unit=1)
    print("-" * 60)
    print("Registers")
    print("-" * 60)
    print(result.registers)
    print("\n")
    decoder = BinaryPayloadDecoder.fromRegisters(result.registers,
                                                 byteorder=Endian.Little,
                                                 wordorder=Endian.Little)

    decoded = OrderedDict([
        ('string', decoder.decode_string(8)),
        ('bits', decoder.decode_bits()),
        ('8int', decoder.decode_8bit_int()),
        ('8uint', decoder.decode_8bit_uint()),
        ('16int', decoder.decode_16bit_int()),
        ('16uint', decoder.decode_16bit_uint()),
        ('32int', decoder.decode_32bit_int()),
        ('32uint', decoder.decode_32bit_uint()),
        ('32float', decoder.decode_32bit_float()),
        ('32float2', decoder.decode_32bit_float()),
        ('64int', decoder.decode_64bit_int()),
        ('64uint', decoder.decode_64bit_uint()),
        ('ignore', decoder.skip_bytes(8)),
        ('64float', decoder.decode_64bit_float()),
        ('64float2', decoder.decode_64bit_float()),
    ])

    print("-" * 60)
    print("Decoded Data")
    print("-" * 60)
    for name, value in iteritems(decoded):
        print("%s\t" % name, hex(value) if isinstance(value, int) else value)
    
    # ----------------------------------------------------------------------- #
    # close the client
    # ----------------------------------------------------------------------- #
    client.close()
Exemplo n.º 14
0
def run_binary_payload_ex():
    # ----------------------------------------------------------------------- #
    # We are going to use a simple client to send our requests
    # ----------------------------------------------------------------------- #
    client = ModbusClient('127.0.0.1', port=5020)
    client.connect()
    
    # ----------------------------------------------------------------------- #
    # If you need to build a complex message to send, you can use the payload
    # builder to simplify the packing logic.
    #
    # Here we demonstrate packing a random payload layout, unpacked it looks
    # like the following:
    #
    # - a 8 byte string 'abcdefgh'
    # - a 32 bit float 22.34
    # - a 16 bit unsigned int 0x1234
    # - another 16 bit unsigned int 0x5678
    # - an 8 bit int 0x12
    # - an 8 bit bitstring [0,1,0,1,1,0,1,0]
    # - an 32 bit uint 0x12345678
    # - an 32 bit signed int -0x1234
    # - an 64 bit signed int 0x12345678

    # The packing can also be applied to the word (wordorder) and bytes in each
    # word (byteorder)

    # The wordorder is applicable only for 32 and 64 bit values
    # Lets say we need to write a value 0x12345678 to a 32 bit register

    # The following combinations could be used to write the register

    # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #
    # Word Order - Big                      Byte Order - Big
    # word1 =0x1234 word2 = 0x5678

    # Word Order - Big                      Byte Order - Little
    # word1 =0x3412 word2 = 0x7856

    # Word Order - Little                   Byte Order - Big
    # word1 = 0x5678 word2 = 0x1234

    # Word Order - Little                   Byte Order - Little
    # word1 =0x7856 word2 = 0x3412
    # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #

    # ----------------------------------------------------------------------- #
    combos = [(wo, bo) for wo in [Endian.Big, Endian.Little] for bo in [Endian.Big, Endian.Little]]
    for wo, bo in combos:
        print("-" * 60)
        print("Word Order: {}".format(ORDER_DICT[wo]))
        print("Byte Order: {}".format(ORDER_DICT[bo]))
        print()
        builder = BinaryPayloadBuilder(byteorder=bo,
                                       wordorder=wo)
        strng = "abcdefgh"
        builder.add_string(strng)
        builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
        builder.add_8bit_int(-0x12)
        builder.add_8bit_uint(0x12)
        builder.add_16bit_int(-0x5678)
        builder.add_16bit_uint(0x1234)
        builder.add_32bit_int(-0x1234)
        builder.add_32bit_uint(0x12345678)
        builder.add_16bit_float(12.34)
        builder.add_16bit_float(-12.34)
        builder.add_32bit_float(22.34)
        builder.add_32bit_float(-22.34)
        builder.add_64bit_int(-0xDEADBEEF)
        builder.add_64bit_uint(0x12345678DEADBEEF)
        builder.add_64bit_uint(0x12345678DEADBEEF)
        builder.add_64bit_float(123.45)
        builder.add_64bit_float(-123.45)
        payload = builder.to_registers()
        print("-" * 60)
        print("Writing Registers")
        print("-" * 60)
        print(payload)
        print("\n")
        payload = builder.build()
        address = 0
        # Can write registers
        # registers = builder.to_registers()
        # client.write_registers(address, registers, unit=1)

        # Or can write encoded binary string
        client.write_registers(address, payload, skip_encode=True, unit=1)
        # ----------------------------------------------------------------------- #
        # If you need to decode a collection of registers in a weird layout, the
        # payload decoder can help you as well.
        #
        # Here we demonstrate decoding a random register layout, unpacked it looks
        # like the following:
        #
        # - a 8 byte string 'abcdefgh'
        # - a 32 bit float 22.34
        # - a 16 bit unsigned int 0x1234
        # - another 16 bit unsigned int which we will ignore
        # - an 8 bit int 0x12
        # - an 8 bit bitstring [0,1,0,1,1,0,1,0]
        # ----------------------------------------------------------------------- #
        address = 0x0
        count = len(payload)
        result = client.read_holding_registers(address, count,  unit=1)
        print("-" * 60)
        print("Registers")
        print("-" * 60)
        print(result.registers)
        print("\n")
        decoder = BinaryPayloadDecoder.fromRegisters(result.registers,
                                                     byteorder=bo,
                                                     wordorder=wo)

        assert decoder._byteorder == builder._byteorder, \
                "Make sure byteorder is consistent between BinaryPayloadBuilder and BinaryPayloadDecoder"

        assert decoder._wordorder == builder._wordorder, \
                "Make sure wordorder is consistent between BinaryPayloadBuilder and BinaryPayloadDecoder"


        decoded = OrderedDict([
            ('string', decoder.decode_string(len(strng))),
            ('bits', decoder.decode_bits()),
            ('8int', decoder.decode_8bit_int()),
            ('8uint', decoder.decode_8bit_uint()),
            ('16int', decoder.decode_16bit_int()),
            ('16uint', decoder.decode_16bit_uint()),
            ('32int', decoder.decode_32bit_int()),
            ('32uint', decoder.decode_32bit_uint()),
            ('16float', decoder.decode_16bit_float()),
            ('16float2', decoder.decode_16bit_float()),
            ('32float', decoder.decode_32bit_float()),
            ('32float2', decoder.decode_32bit_float()),
            ('64int', decoder.decode_64bit_int()),
            ('64uint', decoder.decode_64bit_uint()),
            ('ignore', decoder.skip_bytes(8)),
            ('64float', decoder.decode_64bit_float()),
            ('64float2', decoder.decode_64bit_float()),
        ])

        print("-" * 60)
        print("Decoded Data")
        print("-" * 60)
        for name, value in iteritems(decoded):
            print("%s\t" % name, hex(value) if isinstance(value, int) else value)
    
    # ----------------------------------------------------------------------- #
    # close the client
    # ----------------------------------------------------------------------- #
    client.close()
Exemplo n.º 15
0
 def write(self, name, value):
     client = self.mbclient(host=self.host,
                            port=self.port,
                            retries=self.retries,
                            backoff=self.backoff,
                            timeout=self.timeout,
                            framer=self.mbframer,
                            retry_on_empty=True,
                            retry_on_invalid=True)
     if not client.connect():
         logger.error("Cannot connect to bridge %s" % (self.host))
         return False
     row = list(filter(lambda r: r[0] == name, self.mapping))
     if len(row):
         (name, descr, unit, datatype, rw, scale, offset, register) = row[0]
         if not rw:
             logger.error(
                 "Error writing to bridge %s slave %d register %d: read only"
                 % (self.host, self.slaveid, register))
             client.close()
             return False
         register = int(register)
         try:
             builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                            wordorder=self.endian)
             if datatype == 'b':
                 builder.add_8bit_int(value)
             if datatype == 'B':
                 builder.add_8bit_uint(value)
             if datatype == 'h':
                 builder.add_16bit_int(value)
             if datatype == 'H':
                 builder.add_16bit_uint(value)
             if datatype == 'i':
                 builder.add_32bit_int(value)
             if datatype == 'I':
                 builder.add_32bit_uint(value)
             if datatype == 'q':
                 builder.add_64bit_int(value)
             if datatype == 'Q':
                 builder.add_64bit_uint(value)
             if datatype == 'f':
                 builder.add_32bit_float(value)
             if datatype == 'd':
                 builder.add_64bit_float(value)
             if re.match(r'^s(\d*)$', datatype):
                 builder.add_string(value)
             registers = builder.to_registers()
         except (AttributeError, ValueError, struct.error) as e:
             logger.error(
                 "Error writing to bridge %s slave %d register %d: %s" %
                 (self.host, self.slaveid, register, str(e)))
             client.close()
             return False
         try:
             if register > 40000:
                 addr = register - 40001
                 if len(registers) > 1:
                     result = client.write_registers(addr,
                                                     registers,
                                                     unit=self.slaveid)
                 else:
                     result = client.write_register(addr,
                                                    value,
                                                    unit=self.slaveid)
             else:
                 addr = register - 1
                 result = client.write_coil(addr,
                                            bool(value),
                                            unit=self.slaveid)
         except ConnectionException as e:
             logger.error(
                 "Error writing to bridge %s slave %d register %d: %s" %
                 (self.host, self.slaveid, register, str(e)))
             client.close()
             return False
         if type(result) == ExceptionResponse:
             logger.error(
                 "Error writing to bridge %s slave %d register %d: %s" %
                 (self.host, self.slaveid, register, result))
             client.close()
             return False
         if result.isError():
             logger.error(
                 "Error writing to bridge %s slave %d register %d" %
                 (self.host, self.slaveid, register))
             client.close()
             return False
         logger.debug(
             'Modbus bridge: %s slave: %s register: %s (%s) value: %s' %
             (self.host, self.slaveid, register, name, value))
     client.close()
     return True
Exemplo n.º 16
0
    def __write_Registers(self, regPara, value):
        objectType = regPara['objectType']
        address = regPara['regAddr']
        slaveUnit = regPara['slaveUnit']
        bo = regPara['byteOrder']
        wo = regPara['wordOrder']
        dataTypeStr = regPara['dataType']
        dataType = ''.join(
            filter(str.isalpha, dataTypeStr
                   ))  # vom dataType die Ziffen entfernen z.B. uint16 = uint
        registerCount = 0  # Anzahl der zu schreibenden Register (Words)

        try:
            bits = int(''.join(filter(
                str.isdigit,
                dataTypeStr)))  # bit-Zahl aus aus dataType z.B. uint16 = 16
        except:
            bits = 16

        if dataType.lower() == 'string':
            registerCount = int(
                bits / 2
            )  # bei string: bits = bytes !! string16 -> 16Byte - 8 registerCount
        else:
            registerCount = int(bits / 16)

        if regPara['factor'] != 1:
            #self.logger.debug("value {0} divided by: {1}".format(value, regPara['factor']))
            value = value * (1 / regPara['factor'])

        self.logger.debug(
            "write {0} to {1}.{2}.{3} (address.slaveUnit) dataType:{4}".format(
                value, objectType, address, slaveUnit, dataTypeStr))
        builder = BinaryPayloadBuilder(byteorder=bo, wordorder=wo)

        if dataType.lower() == 'uint':
            if bits == 16:
                builder.add_16bit_uint(int(value))
            elif bits == 32:
                builder.add_32bit_uint(int(value))
            elif bits == 64:
                builder.add_64bit_uint(int(value))
            else:
                self.logger.error(
                    "Number of bits or datatype not supportet : {0}".format(
                        typeStr))
        elif dataType.lower() == 'int':
            if bits == 16:
                builder.add_16bit_int(int(value))
            elif bits == 32:
                builder.add_32bit_int(int(value))
            elif bits == 64:
                builder.add_64bit_int(int(value))
            else:
                self.logger.error(
                    "Number of bits or datatype not supportet : {0}".format(
                        typeStr))
        elif dataType.lower() == 'float':
            if bits == 32:
                builder.add_32bit_float(value)
            if bits == 64:
                builder.add_64bit_float(value)
            else:
                self.logger.error(
                    "Number of bits or datatype not supportet : {0}".format(
                        typeStr))
        elif dataType.lower() == 'string':
            builder.add_string(value)
        elif dataType.lower() == 'bit':
            if objectType == 'Coil' or objectType == 'DiscreteInput':
                if not type(value) == type(True):  # test is boolean
                    self.logger.error(
                        "Value is not boolean: {0}".format(value))
                    return
            else:
                if set(bitstr).issubset({
                        '0', '1'
                }) and bool(bitstr):  # test is bit-string '00110101'
                    builder.add_bits(value)
                else:
                    self.logger.error(
                        "Value is not a bitstring: {0}".format(value))
        else:
            self.logger.error(
                "Number of bits or datatype not supportet : {0}".format(
                    typeStr))
            return None

        if objectType == 'Coil':
            result = self._Mclient.write_coil(address, value, unit=slaveUnit)
        elif objectType == 'HoldingRegister':
            registers = builder.to_registers()
            result = self._Mclient.write_registers(address,
                                                   registers,
                                                   unit=slaveUnit)
        elif objectType == 'DiscreteInput':
            self.logger.warning(
                "this object type cannot be written {0}:{1} slaveUnit:{2}".
                format(objectType, address, slaveUnit))
            return
        elif objectType == 'InputRegister':
            self.logger.warning(
                "this object type cannot be written {0}:{1} slaveUnit:{2}".
                format(objectType, address, slaveUnit))
            return
        else:
            return
        if result.isError():
            self.logger.error(
                "write error: {0} {1}.{2}.{3} (address.slaveUnit)".format(
                    result, objectType, address, slaveUnit))
            return None

        if 'write_dt' in regPara:
            regPara['last_write_dt'] = regPara['write_dt']
            regPara['write_dt'] = datetime.now()
        else:
            regPara.update({'write_dt': datetime.now()})

        if 'write_value' in regPara:
            regPara['last_write_value'] = regPara['write_value']
            regPara['write_value'] = value
        else:
            regPara.update({'write_value': value})