Exemplo n.º 1
0
    def testPayloadBuilderWithRawPayload(self):
        """ Test basic bit message encoding/decoding """
        _coils1 = [False, False, True, True, False, True, False, False, False,
                   False, False, True, False, False, True, False, False, True,
                   True, True, True, False, False, False, False, True, False,
                   True, False, True, True, False]
        _coils2 = [False, False, False, True, False, False, True, False, False,
                   False, True, True, False, True, False, False, False, True,
                   False, True, False, True, True, False, False, True, True,
                   True, True, False, False, False]

        builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'],
                                       repack=True)
        self.assertEqual(b'\x12\x34\x56\x78', builder.to_string())
        self.assertEqual([13330, 30806], builder.to_registers())
        c = builder.to_coils()
        self.assertEqual(_coils1, c)

        builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'],
                                       byteorder=Endian.Big)
        self.assertEqual(b'\x12\x34\x56\x78', builder.to_string())
        self.assertEqual([4660, 22136], builder.to_registers())
        self.assertEqual('\x12\x34\x56\x78', str(builder))
        c = builder.to_coils()
        self.assertEqual(_coils2, c)
Exemplo n.º 2
0
    def testPayloadBuilderWithRawPayload(self):
        """ Test basic bit message encoding/decoding """
        _coils1 = [
            False, False, True, True, False, True, False, False, False, False,
            False, True, False, False, True, False, False, True, True, True,
            True, False, False, False, False, True, False, True, False, True,
            True, False
        ]
        _coils2 = [
            False, False, False, True, False, False, True, False, False, False,
            True, True, False, True, False, False, False, True, False, True,
            False, True, True, False, False, True, True, True, True, False,
            False, False
        ]

        builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'],
                                       repack=True)
        self.assertEqual(b'\x12\x34\x56\x78', builder.to_string())
        self.assertEqual([13330, 30806], builder.to_registers())
        c = builder.to_coils()
        self.assertEqual(_coils1, c)

        builder = BinaryPayloadBuilder([b'\x12', b'\x34', b'\x56', b'\x78'],
                                       byteorder=Endian.Big)
        self.assertEqual(b'\x12\x34\x56\x78', builder.to_string())
        self.assertEqual([4660, 22136], builder.to_registers())
        self.assertEqual('\x12\x34\x56\x78', str(builder))
        c = builder.to_coils()
        self.assertEqual(_coils2, c)
Exemplo n.º 3
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.º 4
0
#builder_di.add_bits([1,1,1,1,1,1,1,1])

# [heater,cooler,...]
builder_co = BinaryPayloadBuilder()
builder_co.add_bits([0, 0, 0, 0, 0, 0, 0, 0])

# temperature
builder_hr = BinaryPayloadBuilder()
builder_hr.add_8bit_int(70)

# wanted to use input registers for temperature, but they are read only
#builder_ir = BinaryPayloadBuilder()
#builder_ir.add_8bit_int(70)

#di_block = ModbusSequentialDataBlock(0x01, builder_di.to_coils())
co_block = ModbusSequentialDataBlock(0x101, builder_co.to_coils())
hr_block = ModbusSequentialDataBlock(0x201, builder_hr.to_registers())
#ir_block = ModbusSequentialDataBlock(0x301, builder_ir.to_registers())

#store = ModbusSlaveContext(di=di_block, co=co_block, hr=hr_block, ir=ir_block)
store = ModbusSlaveContext(co=co_block, hr=hr_block)
context = ModbusServerContext(slaves=store, single=True)

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 = '2.2.0'
    def _build_payload(
        value: int | float, obj: ModbusObj
    ) -> int | list[int | bytes | bool]:
        """
        # TODO make 4 decoders for all combinations in bo, wo and use them?
        Args:
            value: Value to write in object.
            obj: Object instance.

        Returns:
            Built payload.
        """
        scaled = int(value / obj.scale - obj.offset)  # Scaling

        # In `pymodbus` example INT and UINT values presented by hex values.
        # value = hex(value) if obj.data_type in {DataType.INT, DataType.UINT} else value

        if obj.data_type is ModbusDataType.BOOL and obj.data_length in {1, 16}:
            # scaled = [scaled] + [0] * 7
            return int(bool(scaled))

        builder = BinaryPayloadBuilder(byteorder=obj.byte_order, wordorder=obj.word_order)
        build_funcs = {
            # 1: {DataType.BOOL: builder.add_bits},
            8: {
                ModbusDataType.INT: builder.add_8bit_int,
                ModbusDataType.UINT: builder.add_8bit_uint,
                # DataType.BOOL: builder.add_bits,
            },
            16: {
                ModbusDataType.INT: builder.add_16bit_int,
                ModbusDataType.UINT: builder.add_16bit_uint,
                ModbusDataType.FLOAT: builder.add_16bit_float,
                # DataType.BOOL: builder.add_bits,
            },
            32: {
                ModbusDataType.INT: builder.add_32bit_int,
                ModbusDataType.UINT: builder.add_32bit_uint,
                ModbusDataType.FLOAT: builder.add_32bit_float,
            },
            64: {
                ModbusDataType.INT: builder.add_64bit_int,
                ModbusDataType.UINT: builder.add_64bit_uint,
                ModbusDataType.FLOAT: builder.add_64bit_float,
            },
        }
        assert build_funcs[obj.data_length][obj.data_type] is not None

        build_funcs[obj.data_length][obj.data_type](scaled)

        # FIXME: string not support now
        payload = builder.to_coils() if obj.is_coil else builder.to_registers()

        _LOG.debug(
            "Encoded",
            extra={
                "object": obj,
                "value_raw": value,
                "value_scaled": scaled,
                "value_encoded": payload,
            },
        )
        return payload