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 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.º 3
0
def make_block(section, test_val, test_params):
    #print("Format", section)
    builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                   wordorder=Endian.Big)
    # TYPES TO BE ADDED
    value = 0
    data_size = 0
    for s in section:
        field_name = test_params["field_name"].format(source=s[4], block=s[5], field=s[6] )
        #print(field_name, test_val[field_name], s)
        print("Add: ", data_size, s, end="")
        value = test_val[field_name]
        #value += 1
        if s[0] == "float16":
            builder.add_16bit_uint(round(value) ) 
            data_size +=1
        elif s[0] == "uint16":
            #print(value, float(value), s[2] , s[3] )
            #print("values:", s, value)
            val = int( ( float(value) - float(s[3])) / float(s[2]) )
            #print("values:", s, value, val)
            builder.add_16bit_uint(val)
            data_size+=1
        elif s[0] == "uint32":
            val = int(float(value) / float(s[2]) - float(s[3]) )
            builder.add_32bit_uint(val)
            data_size += 2
        elif s[0] in ["int32", "sint32"]:
            val = int(float(value) / float(s[2]) - float(s[3]) )
            builder.add_32bit_int(val)
            data_size +=2
        elif s[0] == "float32":
            val = float(value)  / float(s[2]) - float(s[3]) 
            builder.add_32bit_float(val)
            data_size +=2
        elif s[0] == "bit16":
            builder.add_bits([0, 0, 0, 0, 0, 0, 0, 0] )
            builder.add_bits([0, 0, 0, 0, 0, 0, 0, 0] )
            val = 0
            data_size += 1
        elif s[0][:3] == "str":
            data_length = int(s[1])
            val = " " * (data_length - len(str(value))) + str(value)
            builder.add_string(val)
            data_size += data_length/2
        else:
            print(" ------ ", s) 
        print(val)
        #value += 1

    block = ModbusSequentialDataBlock(1, builder.to_registers())
    return block
Exemplo n.º 4
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.º 5
0
    def _write(self, value):

        builder = BinaryPayloadBuilder(byteorder='>', wordorder='<')
        builder.add_16bit_uint(value)
        payload = builder.to_registers()

        try:
            with ModbusTcpClient(self.host, self.port) as client:
                result = client.write_registers(self.COMMAND_ADDRESS, payload)
        except ConnectionException as e:
            raise ttypes.LesediException(str(e))

        if result.isError():
            raise ttypes.LesediException(str(result))
Exemplo n.º 6
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.º 7
0
    def push_buffer(self, buff):
        builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                       wordorder=Endian.Little)

        [builder.add_8bit_uint(i) for i in buff]
        builder.add_16bit_uint(self.calc_crc(buff))
        payload = builder.build()
        rq = self.client.write_registers(self.MB_STREAM_REG, payload, skip_encode=True, unit=self.id)
        #logging.info(f"Push {binascii.hexlify(buff)}")
        # logging.info(rq.isError())
        if not rq.isError():
            return True
        else:
            logging.warning(f"Can't write stream data")
            return False
Exemplo n.º 8
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.º 10
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.º 11
0
    def write_small_buff(self, buff):
        if len(buff) == self.mb_transfer_size:
            self.reset_state() # reset error state
            builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                           wordorder=Endian.Little)

            [builder.add_16bit_uint(i) for i in buff]
            builder.add_16bit_uint(self.calc_crc(buff))
            payload = builder.build()
            #print(payload)
            self.client.write_registers(self.MB_START_STREAM, payload, skip_encode=True, unit=self.id)
            if self.update_state() == 0: #check errors
                self.client.write_register(self.MB_ACTION_REG, self.MB_ACTION_WRITE, unit=self.id)
                if self.update_state() == 0:
                    return True
        return False
Exemplo n.º 12
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.º 13
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.º 14
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())
    def setUp(self):
        '''
        Initializes the test environment and builds request/result
        encoding pairs
        '''
        self.value  = 0xabcd
        self.values = [0xa, 0xb, 0xc]
        builder = BinaryPayloadBuilder(endian=Endian.Big)
        builder.add_16bit_uint(0x1234)
        self.payload = builder.build()
        self.write  = {
            WriteSingleRegisterRequest(1, self.value)       : b'\x00\x01\xab\xcd',
            WriteSingleRegisterResponse(1, self.value)      : b'\x00\x01\xab\xcd',
            WriteMultipleRegistersRequest(1, self.values)   : b'\x00\x01\x00\x03\x06\x00\n\x00\x0b\x00\x0c',
            WriteMultipleRegistersResponse(1, 5)            : b'\x00\x01\x00\x05',

            WriteSingleRegisterRequest(1, self.payload[0], skip_encode=True): b'\x00\x01\x12\x34',
            WriteMultipleRegistersRequest(1, self.payload, skip_encode=True): b'\x00\x01\x00\x01\x02\x12\x34',
        }
    def setUp(self):
        '''
        Initializes the test environment and builds request/result
        encoding pairs
        '''
        self.value  = 0xabcd
        self.values = [0xa, 0xb, 0xc]
        builder = BinaryPayloadBuilder(byteorder=Endian.Big)
        builder.add_16bit_uint(0x1234)
        self.payload = builder.build()
        self.write  = {
            WriteSingleRegisterRequest(1, self.value)       : b'\x00\x01\xab\xcd',
            WriteSingleRegisterResponse(1, self.value)      : b'\x00\x01\xab\xcd',
            WriteMultipleRegistersRequest(1, self.values)   : b'\x00\x01\x00\x03\x06\x00\n\x00\x0b\x00\x0c',
            WriteMultipleRegistersResponse(1, 5)            : b'\x00\x01\x00\x05',

            WriteSingleRegisterRequest(1, self.payload[0], skip_encode=True): b'\x00\x01\x12\x34',
            WriteMultipleRegistersRequest(1, self.payload, skip_encode=True): b'\x00\x01\x00\x01\x02\x12\x34',
        }
Exemplo n.º 17
0
class PayloadHandler:
    """
    encodes/decodes values according to the way it is stored in registry
    SCALE stands for multiplying/dividing by a scaling factor
    COMB stands for storing the value of one field in two registers
    if none of those provided encodes only based on the type
    """
    def __init__(self, env, store):
        self.byte_order = env["byte_order"]
        self.word_order = env["word_order"]
        self.d_s_factor = env["default_scaling_factor"]
        self.battery_store = store
        self.builder = BinaryPayloadBuilder(byteorder=self.byte_order,
                                            wordorder=self.word_order)

    def encode(self, value, encoding):
        self.builder.reset()
        encode_type = {
            INT8: lambda x: self.builder.add_8bit_int(x),
            UINT8: lambda x: self.builder.add_8bit_uint(x),
            INT16: lambda x: self.builder.add_16bit_int(x),
            UINT16: lambda x: self.builder.add_16bit_uint(x),
            INT32: lambda x: self.builder.add_32bit_int(x),
            UINT32: lambda x: self.builder.add_32bit_uint(x),
            FLOAT32: lambda x: self.builder.add_32bit_float(x),
        }
        if 'e_type' not in encoding or encoding['e_type'] == COMB:
            encode_type[encoding['d_type']](value)
        else:
            encode_type[encoding['d_type']](round(
                value * encoding.get('s_factor', self.d_s_factor)))
        return self.builder.to_registers()

    def decode(self, fx, addr, encoding):
        encoded_value = self.battery_store.getValues(fx, addr, 2)
        decoder = BinaryPayloadDecoder.fromRegisters(encoded_value,
                                                     byteorder=self.byte_order,
                                                     wordorder=self.word_order)
        decode_type = {
            INT8: lambda: decoder.decode_8bit_int(),
            UINT8: lambda: decoder.decode_8bit_uint(),
            INT16: lambda: decoder.decode_16bit_int(),
            UINT16: lambda: decoder.decode_16bit_uint(),
            INT32: lambda: decoder.decode_32bit_int(),
            UINT32: lambda: decoder.decode_32bit_uint(),
            FLOAT32: lambda: decoder.decode_32bit_float(),
        }
        if 'e_type' not in encoding or encoding['e_type'] == COMB:
            return decode_type[encoding['d_type']]()
        else:
            return decode_type[encoding['d_type']]() / encoding.get(
                's_factor', self.d_s_factor)
Exemplo n.º 18
0
    def run(self) -> None:
        builder = BinaryPayloadBuilder(byteorder=self.endian,
                                       wordorder=self.endian)
        builder.add_32bit_uint(42)
        builder.add_16bit_uint(12)
        builder.add_32bit_int(64)
        builder.add_16bit_int(128)
        builder.add_32bit_float(256)

        store = ModbusSlaveContext(
            di=ModbusSequentialDataBlock(18476, builder.to_registers()),
            co=ModbusSequentialDataBlock(18476, builder.to_registers()),
            hr=ModbusSequentialDataBlock(18476, builder.to_registers()),
            ir=ModbusSequentialDataBlock(18476, builder.to_registers()),
            zero_mode=True
        )

        slaves = {
            0x01: store,
            0x02: store,
            0x03: store,
            0x04: store,
        }

        # context = ModbusServerContext(slaves=store, single=True)
        context = ModbusServerContext(slaves=slaves, single=False)

        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 = '2.3.0'

        framer = ModbusSocketFramer

        self.server = ModbusTcpServer(context, framer, identity, address=("127.0.0.1", self.port))
        self.server.serve_forever()
Exemplo n.º 19
0
    def build_args(self, arg, kwargs):
        builder = BinaryPayloadBuilder(
            byteorder=Endian.Big)  #, wordorder=Endian.Big)
        if 'arg_type' in kwargs:
            if kwargs['arg_type'] == 'float': builder.add_32bit_float(arg)
            elif kwargs['arg_type'] == 'uint64': builder.add_64bit_uint(arg)
            elif kwargs['arg_type'] == 'int64': builder.add_64bit_int(arg)
            elif kwargs['arg_type'] == 'uint32': builder.add_32bit_uint(arg)
            elif kwargs['arg_type'] == 'int32': builder.add_32bit_int(arg)
            elif kwargs['arg_type'] == 'uint16': builder.add_16bit_uint(arg)
            elif kwargs['arg_type'] == 'int16': builder.add_16bit_int(arg)
            elif kwargs['arg_type'] == 'int8': builder.add_8bit_int(arg)
            elif kwargs['arg_type'] == 'uint8': builder.add_8bit_uint(arg)
            elif kwargs['arg_type'] == 'string': builder.add_string(arg)
            else:
                raise Exception("unknown parameter type given: %s" %
                                (kwargs['arg_type']))
        else:
            builder.add_16bit_uint(arg)

        val = builder.build()
        return val
Exemplo n.º 20
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.º 21
0
    def write(self):
        try: 
            lb = 00000000
            hb = 00000000
            #### byte besteht immer aus 16 bits
            for byte in self._db['out']:
                for bit in sorted(self._db['out'][byte]):  
                    if bit in self._db['out'][byte]:
                        bitpos =    bit[0]                                                          #startbit/bitposition des binärwertes
                        type =      bit[1]
                        value =     bit[2]
                        name =      bit[3]
                        bit[2] =    bit[3]()                                                        ##aktueller wert des items abrufen und value updaten!
                        builder = BinaryPayloadBuilder(endian=Endian.Little)

                        ##unterscheidung dateityp
                        if type == '5' or type == '5.001' or type == '6' :                          ##8bit uint / int
                            length = 8
                            if bitpos < 8:  #lb
                                lb = value
                            else:           #hb
                                hb = value
                                
                            if type == '5':
                                builder.add_8bit_uint(lb)
                                builder.add_8bit_uint(hb)
                                #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) 
                            elif type == '5.001':                            ##0-100 in 0-255 umwandeln!
                                #print(dpts.en5001(lb))
                                #print(dpts.en5001(hb))
                                
                                lb = self.de5001(lb)
                                hb = self.de5001(hb)
                                #print("lb geschrieben", lb )
                                #print("hb geschrieben", hb )
                                builder.add_8bit_uint(lb)
                                builder.add_8bit_uint(hb)
                                #logger.debug('MODBUS: 8bit uint {0} ; {1}'.format(lb,hb)) 
                            elif type == '6':
                                if lb > 127:
                                    lb = 127
                                elif lb < -128:
                                    lb = -128
                                if hb > 127:
                                    hb = 127
                                elif hb < -128:
                                    hb = -128
                                builder.add_8bit_int(lb)
                                builder.add_8bit_int(hb)
                                #logger.debug('MODBUS: 8bit int {0} ; {1}'.format(lb.hb)) 
                        elif type == '7' or type == '8':                                            #16bit uint / int
                            length = 16
                            if type == '7':                                                         #0...65535
                                builder.add_16bit_uint(value)
                                #logger.debug('MODBUS: 16bit uint {0} '.format(value)) 
                            else:                                                                   #-32768...32767
                                builder.add_16bit_int(value)   
                                #logger.debug('MODBUS: 16bit int {0}'.format(value)) 
                            
                        elif type == '1':
                            length = 1
                                                                                                    #nur pro byte einmal die bits wandeln
                            if bitpos < 8:  #lb
                                lb  = lb | int(value) << bitpos
                                #logger.debug('MODBUS: 8bit int{0}'.format(lb)) 
                                
                            else:           #hb
                                hb  = hb | int(value) << bitpos
                                #logger.debug('MODBUS: 8bit int{0}'.format(hb)) 
                                
                            builder.add_8bit_uint(lb)
                            builder.add_8bit_uint(hb)
                            
                payload = builder.build()
                logger.debug('MODBUS: write to PLC: WORD {0} set to {1} '.format(byte,payload)) 
                self._modbuspy.write_registers(byte, payload, skip_encode=True)
                builder.reset()        
        except Exception as e:
            logger.error('MODBUS: Could not write an OutWord, because {}'.format(e))
            self._lock.release()
            return None
Exemplo n.º 22
0
#---------------------------------------------------------------------------#
# configure the service logging
#---------------------------------------------------------------------------#
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#---------------------------------------------------------------------------#
# build your payload
#---------------------------------------------------------------------------#
builder = BinaryPayloadBuilder(endian=Endian.Little)
builder.add_string('abcdefgh')
builder.add_32bit_float(22.34)
builder.add_16bit_uint(0x1234)
builder.add_8bit_int(0x12)
builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])

#---------------------------------------------------------------------------#
# 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
Exemplo n.º 23
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})
Exemplo n.º 24
0
def on_message(client, userdata, message):

    global gatewayID

    newDev = 1
    i = 0
    date_array = [0, 0, 0, 0, 0, 0, 0]

    modbus_client = ModbusClient(host="localhost", port=502)

    #Get the JSON message as a string
    jsonStr = str(message.payload.decode('utf-8'))

    #Get the topic
    gatewayTopic = message.topic

    #Check if message is uplink
    if ((gatewayTopic.find("event/up") != -1)):

        #get devEUI
        devEUI_str = gatewayTopic.split('/', 6)[3]
        #encode devEUI to hex
        devEUI_hex = int(devEUI_str, 16)

        #Check if message devEUI has a matching address in MODBUS table
        for dev in devEUItab:
            #print ("device tab EUI: " + dev)
            #print ("device message EUI : " + devEUI_str)
            if (dev == devEUI_str):
                #print("Uplink received - devEUI : " + devEUItab[i]  + " - devADR : " + str(devADRtab[i]))
                logging.info('Uplink received - devEUI : %s - devADR : %s',
                             devEUItab[i], str(devADRtab[i]))
                newDev = 0
                break
            i = i + 1

#If there is no match in MODBUS table
        if (newDev == 1):
            #Add new device to device file
            #print("Adding new device in list :" + devEUI_str)
            logging.info('New device %s added in list', devEUI_str)
            devices = open("/home/ogate/MODBUS/modbus.dev", "a")
            devices.write(devEUI_str + ',,\n')
            devices.close()
            #And update MODBUS table once device added to list
            makeTab()

        #Parse the json to get loRa uplink message payload
        jsonDat = json.loads(jsonStr)
        #Encode Chirpstack default base64 payload to hexadecimal
        loraPayload_bytes = base64.b64decode(jsonDat['data'])
        #Get payload byte number
        bytesNumber = len(loraPayload_bytes)

        #Create array of 0 bytes to fill the 32 bytes gap
        zeroArray = bytearray(32 - bytesNumber)

        #Convert to hex
        #loraPayload_hex = int.from_bytes(loraPayload_bytes, "big")

        #Get timestamp with format below
        #[----byte1][----byte2]...
        #[--Century][-----Year]...
        now_tm = datetime.datetime.now()
        date_array[0] = int(now_tm.year / 100)  #century
        date_array[1] = now_tm.year % 100
        date_array[2] = now_tm.month
        date_array[3] = now_tm.day
        date_array[4] = now_tm.hour
        date_array[5] = now_tm.minute
        date_array[6] = now_tm.second

        #Prepare the content to be stored in MODBUS table

        #Format below is set for MODBUS table register (10 bytes per device) :
        #[byte #1-2][byte #3-4][byte #5-6][byte #7-8][byte #9-10][byte #11-12][byte #13-14][byte #15-16][byte #13-14][byte #15-16][byte #17-18][byte #19-20][byte #21-22][byte #23-24][byte #25-26][byte #27-28]
        #[------------------------------------devEUI][----------------------------------------Timestamp][--------------------------------------------------------------------------------------------------------------------

        #Use builder to format MODBUS table content
        builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                       wordorder=Endian.Big)
        #First 4 bytes are used to store devEUI
        builder.add_64bit_uint(devEUI_hex)
        #Then 8 bytes are used to store timestamp
        builder.add_16bit_uint(date_array[0])
        builder.add_8bit_uint(date_array[1])
        builder.add_8bit_uint(date_array[2])
        builder.add_8bit_uint(date_array[3])
        builder.add_8bit_uint(date_array[4])
        builder.add_8bit_uint(date_array[5])
        builder.add_8bit_uint(date_array[6])

        #Add the zero bytes to fill the 32 bytes field
        for id1 in range(0, len(zeroArray)):
            builder.add_8bit_uint(zeroArray[id1])

        #Add the payload bytes
        for id2 in range(0, bytesNumber):
            builder.add_8bit_uint(loraPayload_bytes[id2])

        content = builder.build()

        #Write to corresponding register
        result = modbus_client.write_registers(devADRtab[i],
                                               content,
                                               skip_encode=True)

        if result:
            #print('Uplink stored in register address: ' + str(devADRtab[i]))
            logging.info('Uplink stored in register address: %s',
                         str(devADRtab[i]))
        else:
            #print('Problem storing uplink message in register')
            logging.error('Problem storing uplink message in register')

        #Get devices file content
        devices = open("/home/ogate/MODBUS/modbus.dev", "r")
        devicesLines = devices.readlines()
        devices.close()

        #Update the device file with new content and new date
        devices = open("/home/ogate/MODBUS/modbus.dev", "w")
        payloadStr = loraPayload_bytes.hex()
        payloadLen = len(payloadStr)

        #Prepare timestamp string
        date_str = "00"
        for k in range(0, 7):
            if (len(hex(date_array[k])) <= 3):
                date_str = date_str + '0'
            date_str = date_str + hex(date_array[k])[2:]

        print("Date string : " + date_str)

        #Fill the payload string with 0 if necessary (to get 16 bits)
        for i in range(payloadLen, 64):
            payloadStr = '0' + payloadStr

        for line in devicesLines:
            if (line.split(',')[0] == devEUI_str):
                devices.write(devEUI_str + ',' + devEUI_str + date_str +
                              payloadStr + ',' + str(now_tm) + '\n')
            else:
                devices.write(line)

        devices.close()
def run_binary_payload_ex():
    # ----------------------------------------------------------------------- #
    # We are going to use a simple client to send our requests
    # ----------------------------------------------------------------------- #
    client = ModbusClient('127.0.0.1', port=5440)
    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.Little,
                                   wordorder=Endian.Big)
    builder.add_string('abcdefgh')
    builder.add_32bit_float(22.34)
    builder.add_16bit_uint(0x1234)
    builder.add_16bit_uint(0x5678)
    builder.add_8bit_int(0x12)
    builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
    builder.add_32bit_uint(0x12345678)
    builder.add_32bit_int(-0x1234)
    builder.add_64bit_int(0x1234567890ABCDEF)
    payload = builder.build()
    address = 0
    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 = 0x00
    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.Big)
    decoded = {
        'string': decoder.decode_string(8),
        'float': decoder.decode_32bit_float(),
        '16uint': decoder.decode_16bit_uint(),
        'ignored': decoder.skip_bytes(2),
        '8int': decoder.decode_8bit_int(),
        'bits': decoder.decode_bits(),
        "32uints": decoder.decode_32bit_uint(),
        "32ints": decoder.decode_32bit_int(),
        "64ints": decoder.decode_64bit_int(),
    }
    
    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.º 26
0
class MbVariable:
    def __init__(self, name, var_type, encoding, scale, offset):
        self.name = name
        # do not allow invalid encoding
        if encoding not in [
                "BB", "LB", "BL", "LL", "ABCD", "CDAB", "BADC", "DCBA"
        ]:
            logging.error("invalid Encoding:" + encoding + " For " + name)
            raise KeyError
        self.encoding = encoding
        self.type, self.size = compute_size(var_type)
        self.value = 0
        self.bpb = None
        self.bpd = None
        self.scale = float(scale)
        self.offset = float(offset)
        self.registers = [0] * self.size
        self.set_builder()
        self.register = None

    def __str__(self):
        return self.name

    def set_var_register(self, reg):
        # print("decoding ", self.name, self.type, reg)
        if self.encoding in ['BB', 'ABCD']:
            self.bpd = BinaryPayloadDecoder.fromRegisters(reg,
                                                          byteorder=Endian.Big,
                                                          wordorder=Endian.Big)
        elif self.encoding in ['BL', 'CDAB']:
            self.bpd = BinaryPayloadDecoder.fromRegisters(
                reg, byteorder=Endian.Big, wordorder=Endian.Little)
        elif self.encoding in ['LL', 'DCBA']:
            self.bpd = BinaryPayloadDecoder.fromRegisters(
                reg, byteorder=Endian.Little, wordorder=Endian.Little)
        elif self.encoding in ['LB', 'BADC']:
            self.bpd = BinaryPayloadDecoder.fromRegisters(
                reg, byteorder=Endian.Little, wordorder=Endian.Big)
        else:
            raise KeyError
        self.register = reg

        if self.type == "uint16":
            val = self.bpd.decode_16bit_uint() * self.scale + int(self.offset)
        elif self.type in ["sint16", "int16"]:
            val = self.bpd.decode_16bit_int() * self.scale + int(self.offset)
        elif self.type in ["uint32"]:
            val = self.bpd.decode_32bit_uint() * self.scale + int(self.offset)
        elif self.type in ["sint32", "int32"]:
            val = self.bpd.decode_32bit_int() * self.scale + int(self.offset)
        elif self.type in ["float32"]:
            val = self.bpd.decode_32bit_float() * self.scale + int(self.offset)
        elif self.type == "str":
            val1 = self.bpd.decode_string(self.size)
            val = val1.decode()
        else:
            logging.error("Unknown data type" + self.type)
            raise KeyError
        if math.isnan(val):
            self.value = 0
        else:
            self.value = val

    def set_builder(self):
        if self.encoding in ['BB', 'ABCD']:
            self.bpb = BinaryPayloadBuilder(byteorder=Endian.Big,
                                            wordorder=Endian.Big)
        elif self.encoding in ['BL', 'CDAB']:
            self.bpb = BinaryPayloadBuilder(byteorder=Endian.Big,
                                            wordorder=Endian.Little)
        elif self.encoding in ['LL', 'DCBA']:
            self.bpb = BinaryPayloadBuilder(byteorder=Endian.Little,
                                            wordorder=Endian.Little)
        elif self.encoding in ['LB', 'BADC']:
            self.bpb = BinaryPayloadBuilder(byteorder=Endian.Little,
                                            wordorder=Endian.Big)
        else:
            raise KeyError

    def set_value(self, value):
        self.set_builder()
        self.set_reg_value(value)
        self.value = value

    def set_reg_value(self, value):
        if self.type == "uint16":
            v_raw = int((float(value) - self.offset) / self.scale)
            if v_raw < 0:
                logging.warning("Negative value for " + self.name + ":" +
                                str(v_raw))
                v_raw = 0
            self.bpb.add_16bit_uint(v_raw)
        elif self.type == "int16":
            self.bpb.add_16bit_int(
                int((float(value) - self.offset) / self.scale))
        elif self.type == "uint32":
            v_raw = int((float(value) - self.offset) / self.scale)
            if v_raw < 0:
                logging.warning("Negative value for " + self.name + ":" +
                                str(v_raw))
                v_raw = 0
            self.bpb.add_32bit_uint(v_raw)
        elif self.type == "int32":
            self.bpb.add_32bit_int(
                int((float(value) - self.offset) / self.scale))
        elif self.type == "float32":
            self.bpb.add_32bit_float(
                int((float(value) - self.offset) / self.scale))
        elif self.type == "str":
            value_str = " " * (self.size - len(str(value))) + str(value)
            self.bpb.add_string(value_str)
        else:
            logging.error("Unknown format:" + self.type + " for " + self.name)
            raise ValueError
        self.registers = self.bpb.to_registers()
        logging.debug("Updated var register " + str(self.registers))
Exemplo n.º 27
0
endian=client.read_holding_registers(49991,4,unit=1)
#endian.registers[0] = byteswap(endian.registers[0])
#endian.registers[1] = byteswap(endian.registers[1])
#endian.registers[2] = byteswap(endian.registers[2])
#endian.registers[3] = byteswap(endian.registers[3])
decoder=BinaryPayloadDecoder.fromRegisters(endian.registers,endian=Endian.Big)
decoded={
    'val':hex(decoder.decode_32bit_uint()),
    'v100':decoder.decode_32bit_float()
}

print decoded

encoder = BinaryPayloadBuilder(endian=Endian.Big)
encoder.add_16bit_uint(0x1234)
buf = encoder.build()
#buf[0] = charswap(buf[0])
client.write_registers(51234, buf, unit=1, skip_encode=True)

encoder = BinaryPayloadBuilder(endian=Endian.Big)
encoder.add_32bit_float(1.0114)
encoder.add_32bit_float(-6)
buf = encoder.build()
#buf[0] = charswap(buf[0])
#buf[1] = charswap(buf[1])
#buf[2] = charswap(buf[2])
#buf[3] = charswap(buf[3])
client.write_registers(50000 + 8 * 5, buf, unit=1, skip_encode=True)

while True:
Exemplo n.º 28
0
elements_total = page_len * page_cnt
empty_rest = elements_total - a_len
#---------

#---------Send start message of firmware
crc32_func = crcmod.mkCrcFun(0x104C11DB7, initCrc=0, xorOut=0xFFFFFFFF) #Poly CRC-32: 0x104C11DB7 http://crcmod.sourceforge.net/crcmod.predefined.html
crc_sum32 = crc32_func(b)

crc_sum32_a = (crc_sum32>>16) & 0xFFFF
crc_sum32_b = crc_sum32 & 0xFFFF
crc_sum32_c = (crc_sum32_a>>8) & 0xFF
crc_sum32_d = crc_sum32_a & 0xFF
crc_sum32_e = (crc_sum32_b >> 8) & 0xFF
crc_sum32_f = crc_sum32_b & 0xFF

builder.add_16bit_uint(2) #Type of packet
builder.add_16bit_uint(1) #Reserved

builder.add_16bit_uint(aa_len) 
builder.add_16bit_uint(ab_len) 

builder.add_16bit_uint(crc_sum32_c) #CRC32 sum of firmware body
builder.add_16bit_uint(crc_sum32_d)
builder.add_16bit_uint(crc_sum32_e)
builder.add_16bit_uint(crc_sum32_f)

pg_num_h = (page_cnt >> 8 ) & 0xFF
pg_num_l = page_cnt & 0xFF

builder.add_16bit_uint(pg_num_h) #total number of pages
builder.add_16bit_uint(pg_num_l)
Exemplo n.º 29
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.º 30
0
client = ModbusClient(method="rtu",
                      port="/dev/ttyUSB0",
                      stopbits=1,
                      bytesize=8,
                      parity='N',
                      baudrate=115200,
                      timeout=0.5)

#Connect to the serial modbus server
connection = client.connect()
print(connection)

builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Little)

builder.add_16bit_uint(5)  #Type of packet
payload = builder.to_registers()
payload = builder.build()
client.write_registers(0, payload, skip_encode=True, unit=mb_unit)
builder.reset()
#time.sleep(20)

builder.add_16bit_uint(6)  #Type of packet
payload = builder.to_registers()
payload = builder.build()
client.write_registers(0, payload, skip_encode=True, unit=mb_unit)
builder.reset()
#time.sleep(20)

builder.add_16bit_uint(0)  #Type of packet
payload = builder.to_registers()
Exemplo n.º 31
0
def handle_control_tags(client, readings_from_rtu, mysql_signals, hr_control_tag_floats=True):
    """
    Function to test control tag feedback values read from RTU against corresponding in MySQL scada_signals,
    and if necessary, write new values to RTU.
    If hr_control_tag_floats=False then HR control tags will be written to as 16Bit integers
    """
    new_coil_control_tags = {}
    new_hr_control_tags = {}

    try:
        # use config control_tags to read corresponding COILS out of readings_from_rtu
        for key in conf.coils_control_tags.keys():
            fb_reading = key + '_fb'
            if readings_from_rtu[fb_reading] == bool(mysql_signals.__dict__[key]):
                logger.debug(
                    "Control tag fb '{}' value {} is equal to scada_signals {}"
                    .format(fb_reading, readings_from_rtu[fb_reading], bool(mysql_signals.__dict__[key])))
            else:
                new_coil_control_tags[key] = mysql_signals.__dict__[key]
                logger.debug(
                    "Control tag fb '{}' value {} does not match new value in scada_signals {}, listed for over-write"
                    .format(fb_reading, readings_from_rtu[fb_reading], bool(mysql_signals.__dict__[key])))
        # use config control_tags to read corresponding HR out of readings_from_rtu
        for key in conf.holding_registers_control_tags.keys():
            fb_reading = key + '_fb'
            if readings_from_rtu[fb_reading] == mysql_signals.__dict__[key]:
                logger.debug(
                    "Control tag fb '{}' value {} is equal to scada_signals {}"
                    .format(fb_reading, readings_from_rtu[fb_reading], bool(mysql_signals.__dict__[key])))
            else:
                new_hr_control_tags[key] = mysql_signals.__dict__[key]
                logger.debug(
                    "Control tag fb '{}' value {} does not match new value in scada_signals {}, listed for over-write"
                    .format(fb_reading, readings_from_rtu[fb_reading], bool(mysql_signals.__dict__[key])))
    except Exception as e:
        logger.exception('Exception occurred comparing control tags  - {}'.format(e))

    # If necessary, write new control tag values from scada_signals to RTU
    try:
        if new_coil_control_tags:
            for key, value in new_coil_control_tags.items():
                client.write_coil(conf.coils_control_tags[key], value)
                logger.info("New control tag value {} for '{}' written to RTU".format(value, key))
    except Exception as e:
        logger.exception('Exception occurred writing new COIL control tags to RTU - {}'.format(e))
    try:
        if new_hr_control_tags:
            builder = BinaryPayloadBuilder(byteorder=Endian.Big, wordorder=Endian.Big)
            if hr_control_tag_floats:
                for key, value in new_hr_control_tags.items():
                    builder.add_32bit_float(value)
                    payload = builder.build()
                    client.write_registers(conf.holding_registers_control_tags[key][0], payload, skip_encode=True)
                    logger.info("New control tag value {} for '{}' written to RTU".format(value, key))
            else:
                for key, value in new_hr_control_tags.items():
                    builder.add_16bit_uint(value)
                    payload = builder.build()
                    client.write_registers(conf.holding_registers_control_tags[key][0], payload, skip_encode=True)
                    logger.info("New control tag value {} for '{}' written to RTU".format(value, key))

                # Pretty sure will never have to write 32Bit integers, but should be able to if need be.
                # BinaryPayloadBuilder would need little endian if 32Bit read is anything to go by.

        # Note: if we had consecutive addresses we could write all at once, instead of building payload
        #       individually and writing for each signal individually. But seeing as it's only max of
        #       8 signals at present, it's safer to just write them individually, so address order doesn't matter

    except Exception as e:
        logger.exception('Exception occurred writing new HR control tags to RTU - {}'.format(e))
Exemplo n.º 32
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.º 33
0
# 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
# - an 8 bit int 0x12
# - an 8 bit bitstring [0,1,0,1,1,0,1,0]
# ---------------------------------------------------------------------------#
builder = BinaryPayloadBuilder(endian=Endian.Little)
builder.add_string("abcdefgh")
builder.add_32bit_float(22.34)
builder.add_16bit_uint(0x1234)
builder.add_8bit_int(0x12)
builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])
payload = builder.build()
address = 0x01
result = client.write_registers(address, payload, skip_encode=True)

# ---------------------------------------------------------------------------#
# 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
Exemplo n.º 34
0
        print("-" * 60)
        print("Decoded Data")
        print("-" * 60)
        for name, value in decoded.items():
            print ("%s\t" % name, value)
        print("\n")

        # Try to write registers 2000
        print("-" * 60)
        print("Writing Registers")
        print("-" * 60)

        builder = BinaryPayloadBuilder(byteorder='>', wordorder='>')
        
        builder.add_16bit_uint(1234)
        builder.add_16bit_uint(0) # Skip 1 byte        
        builder.add_32bit_int(-1234)
        builder.add_32bit_float(-1.234)
        builder.add_32bit_float(54961.85)
        builder.add_16bit_int(-5678)
        builder.add_16bit_uint(0) # Skip 1 byte
        builder.add_32bit_uint(1)
        
        payload = builder.to_registers()
        print("\n")
        print(payload)
        print("\n")
        payload = builder.build()
        # Can write registers
        registers = builder.to_registers()