Exemplo n.º 1
0
    async def _write_register_value(
            self, key: str,
            value: Union[str, float, int]) -> WriteMultipleRegistersResponse:
        """Write a single value to the holding registers.

        Currently registers are written one at a time to avoid issues with
        discontinuous modbus addresses.

        """
        start_address = self.tags[key]['address']['start'] - 400001
        builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                       wordorder=Endian.Little)
        data_type = self.tags[key]['type']
        if data_type == 'float':
            builder.add_32bit_float(value)
        elif data_type == 'str':
            chars = self.tags[key]['length']
            if len(value) > chars:
                raise ValueError(f'{value} is too long for {key}. '
                                 f'Max: {chars} chars')
            builder.add_string(value.ljust(chars))
        elif data_type == 'int16':
            builder.add_16bit_int(value)
        elif data_type == 'int32':
            builder.add_32bit_int(value)
        else:
            raise ValueError("Missing data type.")
        resp = await self.write_registers(start_address,
                                          builder.build(),
                                          skip_encode=True)
        return resp[0]
 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.º 3
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.º 4
0
    def writeValue(self, varname, value):
        if CONST_MAP_VARIABLES_TO_ID[varname]["write"] != True:
            self.logger.error(
                "Helios: Variable {0} may not be written!".format(varname))
            return False
        success = False

        self._lock.acquire()
        try:
            # if we have got to write a single bit, we need the current (byte) value to
            # reproduce the other bits...
            #            if CONST_MAP_VARIABLES_TO_ID[varname]["type"] == "bit":
            #                currentval = None
            #                # Send poll request
            #                # Read response
            #                #    CONST_MAP_VARIABLES_TO_ID[varname]["variable"]
            #                value = value
            #                if currentval == None:
            #                    self.logger.error("Helios: Sending value to ventilation system failed. Can not read current variable value '{0}'."
            #                        .format(varname))
            #                    return False
            #                rawvalue = self._convertFromValue(varname, value, currentval)
            #            else:
            #                #rawvalue = self._convertFromValue(varname, value, None)
            rawvalue = str(value)

            # send the new value
            if rawvalue is not None:
                # Writing value
                builder = BinaryPayloadBuilder()
                builder.add_string(
                    CONST_MAP_VARIABLES_TO_ID[varname]["variable"] + '=' +
                    rawvalue + '\0')
                payload = builder.build()
                self._port.write_registers(FIRST_REGISTER_ADDR,
                                           payload,
                                           skip_encode=True,
                                           unit=SLAVE_ID)
                success = True

            else:
                self.logger.error(
                    "Helios: Sending value to ventilation system failed. Can not convert value '{0}' for variable '{1}'."
                    .format(value, varname))
                success = False
        except Exception as e:
            self.logger.error(
                "Helios: Exception in writeValue() occurred: {0}".format(e))
        finally:
            self._lock.release()

        return success
Exemplo n.º 5
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
def prefil_registers(a):
    context=a[0]
    # Values to be filled:
    # 4000 SERIAL NUMBER, length 2, 13070001 HEX
    # 4002 MeterCode, length 1, 0102 HEX
    # 4003 Meter ID, Length 1, 0001
    # 4004 Baud, Length 1, 9600
    # 4005 Protocol Version, Lenth 2, 3.2
    # 4007 Software Version, Length 2, 1.18
    # 4009 Hardware Version, Length 2, 1.03
    # 400B Meter Amps, Length 1, 45
    # 400D S0 Rate, Length 2, 1000
    # 400F Combination Code, Length 1, 10 (Forward - Reverse)
    # 4010 LCD LifeCycle, Lenght 1, 01 HEX
    # 4011 Parity Setting, Length 1, 01
    # 4012 Current Direction, Lenght 1, FW ASCII

    builder = BinaryPayloadBuilder(byteorder=Endian.Big,
                                   wordorder=Endian.Big)
    builder.add_32bit_float(0x13070001)
    builder.add_16bit_int(0x0102)
    builder.add_16bit_int(1)
    builder.add_16bit_int(9600)
    builder.add_32bit_float(3.2)
    builder.add_32bit_float(1.18)
    builder.add_32bit_float(1.03)
    builder.add_16bit_int(45)
#    builder.add_16bit_int(0)
    payload = builder.to_registers()
    context[0x01].setValues(0x10, 0x4000, payload)
    # Skip Address
    builder2 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                   wordorder=Endian.Big)
    builder2.add_32bit_float(1000)
    builder2.add_16bit_int(10)
    builder2.add_16bit_int(0x10)
    builder2.add_16bit_int(01)
    builder2.add_string('FW')
    payload2 = builder2.to_registers()
    context[0x01].setValues(0x10, 0x400D, payload2)

    # 5000
    builder3 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                   wordorder=Endian.Big)
    builder3.add_32bit_float(230)
    builder3.add_32bit_float(230)
    builder3.add_32bit_float(230)
    builder3.add_32bit_float(230)
    builder3.add_32bit_float(50)
    payload3 = builder3.to_registers()
    context[0x01].setValues(0x10, 0x5000, payload3)
Exemplo n.º 7
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.º 8
0
def update_register(context, param):
    values = []
    fn_code = HOLDING_REGISTER_FN_CODE

    if (param == "temperature"):
        address = TEMPERATURE_REGISTER
        newvalue = random.randint(TEMP_LO, TEMP_HI)
        log.debug("new temperatue value: " + str(newvalue))
    elif (param == "humidity"):
        address = HUMIDITY_REGISTER
        newvalue = random.randint(HUMID_LO, HUMID_HI)
        log.debug("new humidity value: " + str(newvalue))
    elif (param == "pressure"):
        address = PRESSURE_REGISTER
        newvalue = random.randint(PRESSURE_LO, PRESSURE_HI)
        log.debug("new pressure value: " + str(newvalue))
    elif (param == "geolati"):
        address = GEO_LATI_REGISTER
        newvalue = random.uniform(LATI_LO, LATI_HI)
        log.debug("new latitude value = " + str(newvalue))
        builder = BinaryPayloadBuilder(endian=Endian.Big)
        builder.add_32bit_float(newvalue)
        payload = builder.to_registers()
        context.setValues(fn_code, address, payload)
        return
    elif (param == "geolongi"):
        address = GEO_LONGI_REGISTER
        newvalue = random.uniform(LONGI_LO, LONGI_HI)
        log.debug("new longitude value = " + str(newvalue))
        builder = BinaryPayloadBuilder(endian=Endian.Big)
        builder.add_32bit_float(newvalue)
        payload = builder.to_registers()
        context.setValues(fn_code, address, payload)
        return
    elif (param == "keyop"):
        address = KEY_OP_REGISTER

        context.setValues(fn_code, address, [0] * 8)

        newvalue = random.choice(operations)
        newvalue = newvalue
        log.debug("new key operation = " + newvalue)
        builder = BinaryPayloadBuilder(endian=Endian.Big)
        builder.add_string(newvalue)
        payload = builder.to_registers()
        context.setValues(fn_code, address, payload)
        return
    else:
        return
    values.append(newvalue)
    context.setValues(fn_code, address, values)
Exemplo n.º 9
0
    def readValue(self, varname):
        if CONST_MAP_VARIABLES_TO_ID[varname]["read"] != True:
            self.logger.error("Variable {0} may not be read!".format(varname))
            return False
        value = None

        self._lock.acquire()
        try:
            self.logger.debug("Helios: Reading value: {0}".format(varname))
            # Send poll request
            builder = BinaryPayloadBuilder()
            builder.add_string(CONST_MAP_VARIABLES_TO_ID[varname]["variable"] +
                               '\0')
            payload = builder.build()
            self._port.write_registers(FIRST_REGISTER_ADDR,
                                       payload,
                                       skip_encode=True,
                                       unit=SLAVE_ID)
            # Read response
            rtr = CONST_MAP_VARIABLES_TO_ID[varname]["count"] + 3
            if rtr < 8:
                rtr = 8
            result = self._port.read_holding_registers(FIRST_REGISTER_ADDR,
                                                       rtr,
                                                       unit=SLAVE_ID)
            output = BinaryPayloadDecoder.fromRegisters(
                result.registers).decode_string(rtr)
            output = re.sub(u'([\x00])', "", output.decode('utf-8'))
            reg, value = output.split('=')

            if value is not None:
                raw_value = value
                value = self._convertFromRawValue(varname, value)
                self.logger.debug(
                    "Value for {0} ({1}) received: {2} --> converted = {3}".
                    format(varname,
                           CONST_MAP_VARIABLES_TO_ID[varname]["variable"],
                           raw_value, value))
            else:  # logging in debug only, so we stop spamming log file (noise on the bus seems to be normal)
                self.logger.debug(
                    "Helios: No valid value for '{0}' from ventilation system received."
                    .format(varname))
        except Exception as e:
            self.logger.error(
                "Helios: Exception in readValue() occurred: {0}".format(e))
        finally:
            self._lock.release()

        return value
Exemplo n.º 10
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.º 11
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())
Exemplo n.º 12
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))
 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.º 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())
Exemplo n.º 15
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.º 16
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
 def convert_string_to_register(value):  # currently not used because no need to write string in register
     """
     Convert a string value to a list of registers
     :param value: A string
     :type value: str
     :return: registers value
     :rtype: list[int]
     """
     if isinstance(value, str):
         if pymodbus.__version__ == '1.3.2':
             # by default, on Version 1.3.2, endian is Endian.Little,
             # so registers were written in the reverse order.
             # For now, we use this version on the raspberry pi
             # and v 2.4.0 in simulation
             builder = BinaryPayloadBuilder(endian=Endian.Big)
         else:
             builder = BinaryPayloadBuilder()
         builder.add_string(value)
         payload = builder.to_registers()
         return payload
     else:
         return None
Exemplo n.º 18
0
    def write_registers(self, reg_id: int, value=None):
        if reg_id is None:
            raise ValueError

        reg_str = "v{:05d}".format(reg_id)

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

        if value is not None:
            builder.add_string("=" + str(value))
        # terminate string with NUL byte
        builder.add_string('\0')

        payload = builder.to_registers()

        self.client.write_registers(address=self.ADDRESS,
                                    values=payload,
                                    unit=self.UNIT)
Exemplo n.º 19
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.º 20
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
def string_to_register(string):
    # code a string to 16 bits hex value to store in register
    builder = BinaryPayloadBuilder()
    builder.add_string(string)
    payload = builder.to_registers()
    return payload
Exemplo n.º 22
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:
#
Exemplo n.º 23
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.º 24
0
from pymodbus.payload import BinaryPayloadDecoder
from pymodbus.payload import BinaryPayloadBuilder

#---------------------------------------------------------------------------#
# 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)
def updating_writer(a):
    """ A worker process that runs every so often and
    updates live values of the context. It should be noted
    that there is a race condition for the update.

    :param arguments: The input arguments to the call
    """
    try:
        #apiurl = 'http://192.168.0.216/json/apiV1p1data.php?order=desc&limit=1&outputmode=object'
        apiurl = 'http://192.168.0.216/api/v1/smartmeter?order=desc&limit=1&json=object'
        url = urllib.urlopen(apiurl).read()
        result_temp = json.loads(url)  # result is now a dict
    except:
        print("Cannot Open Api URL")
    else:
        result = result_temp[0]

        currentimport = float(result['CONSUMPTION_W'])
        currentexport = float(result['PRODUCTION_W'])
        forwardactiveenergy = float(result['CONSUMPTION_KWH_HIGH']) + float(result['CONSUMPTION_KWH_LOW'])
        reverseactiveenergy = float(result['PRODUCTION_KWH_LOW']) + float(result['PRODUCTION_KWH_LOW'])
        totalcurrent = currentimport - currentexport
        totalactiveenergy = forwardactiveenergy - reverseactiveenergy

        log.debug('Current Importing: ' + str(currentimport))
        log.debug('Current Exporting: ' + str(currentexport))
        log.debug('updating the context')

        context = a[0]
        readregister = 0x03
        writeregister = 0x10
        slave_id = 0x01
        address1 = 0x4012 # Flow of the Current RV FV (ASCII)
        address2 = 0x500A # Current of Flow (FLOAT ABCD)
        address3 = 0x5012 # Total active power KW Float ABCD)
        address4 = 0x6000 # Total active energy kWh Float
        address5 = 0x600c # Forward Active Energy kWH Float
        address6 = 0x6018 # Reverse Active Energy kWh Float


        #values1 = context[slave_id].getValues(register, address1, count=1)
        if currentimport > currentexport:
            values1 = 'FW'
        else:
            values1 = 'RV'

        # Build payload
        builder1 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                    wordorder=Endian.Big)
        builder1.add_string(values1)
        payload1 = builder1.to_registers()
        context[slave_id].setValues(writeregister, address1, payload1)
        log.debug("new values: " + str(values1))
        log.debug("new imp values: " + str(round(currentimport/230,2)))
        log.debug("new exp values: " + str(round(currentexport/230,2)))

        #values2 = context[slave_id].getValues(register, address2, count=2)
        if currentimport > currentexport:
            values2 = round(currentimport / 230,2) # Calculate A from Kwh assume 230 volts
        else:
            values2 = round(currentexport / 230,2) # Calculate A from Kwh, assume 230 volts
        log.debug("new values: " + str(values2))
        # Build payload
        builder2 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                        wordorder=Endian.Big)
        builder2.add_32bit_float(values2)
        payload2 = builder2.to_registers()
        context[slave_id].setValues(writeregister, address2, payload2)

        builder3 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                        wordorder=Endian.Big)
        builder3.add_32bit_float(round(totalcurrent/1000,2))
        payload3 = builder3.to_registers()
        context[slave_id].setValues(writeregister, address3, payload3)

        builder4 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                        wordorder=Endian.Big)
        builder4.add_32bit_float(round(totalactiveenergy,2))
        payload4 = builder4.to_registers()
        context[slave_id].setValues(writeregister, address4, payload4)

        builder5 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                        wordorder=Endian.Big)
        builder5.add_32bit_float(round(forwardactiveenergy,2))
        payload5 = builder5.to_registers()
        context[slave_id].setValues(writeregister, address5, payload5)

        builder6 = BinaryPayloadBuilder(byteorder=Endian.Big,
                                        wordorder=Endian.Big)
        builder6.add_32bit_float(round(reverseactiveenergy,2))
        payload6 = builder6.to_registers()
        context[slave_id].setValues(writeregister, address6, payload6)

        readvalues = context[slave_id].getValues(0x03,0x4000,0x12)
        log.debug("Values from datastore: " + str(readvalues))
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.º 27
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.º 28
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:
#
Exemplo n.º 29
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})