def read_coils(self, start_coil_address, number_of_coils):
        """ Modbus command : Read coil data(s) (function code = 01)

            @Argument :
            start_coil_address (int16) : Start coil address where to read a coil data
            number_of_coil (int)       : number of coil(s) to read

            @Return :
            response : Coil data (Byte)
                        The coils in the response message are packed as one coil per bit of the
                        data field. Status is indicated as 1= ON and 0= OFF.
        """
        response = None

        # Generate modbus RTU message
        try:
            message = modbus_rtu.read_coils(
                slave_id=self.device_id,
                starting_address=start_coil_address,
                quantity=number_of_coils)
        except Exception as e:
            print("Error during generate modbus message.")

        # Send message via serial port
        try:
            if self.serialport.is_open:
                response = modbus_rtu.send_message(message, self.serialport)
                print("response={}".format(response))
            else:
                print("Error : Cannot send data. Serial port is closed.")
        except Exception as e:
            print("Error during send modbus message.")
            print(e)

        return response
def test_no_response_for_request_with_invalid_crc(rtu_server):
    """ Test if server doesn't respond on a request with an invalid CRC. """
    pdu = rtu.read_coils(1, 9, 2)
    adu = struct.pack('>B', 1) + pdu + struct.pack('>BB', 0, 0)

    rtu_server.serial_port.write(adu)

    with pytest.raises(CRCError):
        rtu_server.serve_once()
Exemplo n.º 3
0
def test_send_message_with_timeout():
    """ Test if TimoutError is raised when serial port doesn't receive enough
    data.
    """
    s = serial_for_url('loop://', timeout=0)
    # As we are using a loop, the sent request will be read back as response.
    # To test timeout use a request that needs more bytes for the response.
    message = read_coils(slave_id=0, starting_address=1, quantity=40)

    with pytest.raises(ValueError):
        send_message(message, s)
Exemplo n.º 4
0
    def read_coil_registers(self, slave_id, address, quantity, port):
        self.serial_port = self.get_serial_port(port)
        add = int(address) - 1
        message = rtu.read_coils(slave_id=int(slave_id), starting_address=add, quantity=int(quantity))
        hexadecimal_string = message.hex()
        print(hexadecimal_string)
        response = rtu.send_message(message, self.serial_port)
        print("response", response)
        result = []
        # return response
        count = 0
        for offset in range(int(address), int(address) + int(quantity)):
            print("offset", offset)
            # for i in response:
            if offset == 100:
                res = response[count] / 10
                print("Factory value", res)

            elif offset == 101:
                res = response[count] / 10
                print("Factory value", res)

            elif offset == 102:
                res = response[count] / 10
                print("Factory value", res)
            # print("count",count)
            elif offset == 103:
                res = response[count] / 10
                print("Factory value", res)
            # print("count",count)
            elif offset == 10:
                res = response[count] / 10
                print("Factory value", res)
            # print("count",count)
            elif offset == 124:
                res = response[count] / 10
                print("Factory value", res)

            elif offset == 131:
                res = response[count] / 10
                print("Factory value", res)

            elif offset == 183:
                res = response[count] / 10
                print("Factory value", res)
            else:
                res = response[count]
                print(res)
            count = count + 1
            result.append(res)

        return result, hexadecimal_string
        self.serial_port.close()
Exemplo n.º 5
0
 def read_pin(self, reg):  # read a single coil register at reg address
     try:
         serial_port = self.get_serial_port()
         message = rtu.read_coils(SLAVE_ID, reg, 1)
         response = rtu.send_message(message, serial_port)
         response = response[0]
         self.release_serial_port()
         return response
     except:
         traceback.print_exc()
         self.close_serial_port()
     return None
Exemplo n.º 6
0
def modbus_tcp_rtu(data_in):
    def msb(data):
        return (data // 256)

    def lsb(data):
        return (data % 256)

    def combine_msb_lsb(data_msb, data_lsb):
        return ((data_msb * 256) + data_lsb)

    com_port = '/dev/ttyUSB0'
    slave_id = data_in[6]
    func = data_in[7]
    str_add = combine_msb_lsb(data_in[8], data_in[9])
    no_of_regs = combine_msb_lsb(data_in[10], data_in[11])

    if (func == 1) or (func == 2):
        #Round up the number of registers without external function
        coil_bytes = -(-no_of_regs // 8)
        data_out = [0] * (9 + coil_bytes)
        data_out[8] = coil_bytes

        ser1 = serial.Serial(port=com_port,
                             baudrate=9600,
                             parity=serial.PARITY_NONE,
                             stopbits=serial.STOPBITS_ONE,
                             bytesize=serial.EIGHTBITS,
                             timeout=1)

        coil_request = rtu.read_coils(slave_id, str_add, no_of_regs)
        coil_request = rtu.read_coils(1, 0, 10)

        ser1.write(bytes(coil_request))
        time.sleep(0.1)
        while ser1.inWaiting():
            coil_reply = ser1.readline()
        data_out[9:] = coil_reply[3:-2]

    if (func == 3) or (func == 4):
        data_out = [0] * ((2 * data_in[11]) + 9)
        data_out[8] = data_in[11] * 2
        #Define Modbus Parameters
        minimalmodbus.BAUDRATE = 9600
        minimalmodbus.BYTESIZE = 8
        minimalmodbus.PARITY = 'N'
        minimalmodbus.STOPBITS = 1
        minimalmodbus.TIMEOUT = 1

        #not closing port after each call causes buffer overflow issue(Probably?)
        minimalmodbus.CLOSE_PORT_AFTER_EACH_CALL = True

        gw = minimalmodbus.Instrument(com_port, slave_id, mode='rtu')
        gw.debug = False

        if no_of_regs == 1:
            rtu_data_out = gw.read_register(str_add, 0, func)
            data_out[9] = msb(rtu_data_out)
            data_out[10] = lsb(rtu_data_out)

        else:
            rtu_data_out = gw.read_registers(str_add, no_of_regs, func)
            for i in range(len(rtu_data_out)):
                data_out[9 + 2 * i] = msb(rtu_data_out[i])
                data_out[9 + 2 * i + 1] = lsb(rtu_data_out[i])

    data_out[0] = data_in[0]
    data_out[1] = data_in[1]
    data_out[2] = data_in[2]
    data_out[3] = data_in[3]
    data_out[4] = msb((2 * data_in[11]) + 3)
    data_out[5] = lsb((2 * data_in[11]) + 3)
    data_out[6] = slave_id
    data_out[7] = func

    return data_out