AdvancedClimateSystems / uModbus

Python implementation of the Modbus protocol.
Mozilla Public License 2.0
211 stars 82 forks source link

unspected crc error #64

Open coyool opened 5 years ago

coyool commented 5 years ago

run as rtu serve when writing to 233 station, 33000 write a data(<0,eg:-100) to addr 33000 (larger than 2^15), will surely cause "salve failure error" all code as below:


import threading
import serial
from collections import defaultdict
from umodbus.server.serial import get_server
from umodbus.server.serial.rtu import RTUServer
import threadstop

running = threading.Thread()
comName = 'com31'
port = serial.Serial(comName)
port.timeout = 10
port.baudrate = 9600
port.stopbits = 1
port.parity = 'N'

data_rd = defaultdict(int)
data_wr = defaultdict(int)
link = get_server(RTUServer, port)

@link.route(slave_ids=[233], function_codes=[3], addresses=list(range(33000, 33000 + 1000)))
def read_data_store(slave_id, function_code, address):
    """" Return value of address. """
    # return data_store[address]
    return data_rd[address] + address

@link.route(slave_ids=[233], function_codes=[6, 16], addresses=list(range(33000, 33000 + 1000)))
def write_data_store(slave_id, function_code, address, value):
    """" Set value for address. """
    data_rd[address] = value  #OK
    data_wr[address] = value #ERROR

def poll():
    try:
        link.serve_forever()
    finally:
        link.shutdown()

def connect(comx):
    running = threading.Thread(target=poll)
    running.start()

def reconnect(comx):
    try:
        threadstop(running)
        link.shutdown()
    finally:
        comName = comx
        port = serial.Serial(comName)
        link.shutdown()

if __name__ == '__main__':
    try:
        link.serve_forever()
    finally:
        link.shutdown()
OrangeTux commented 5 years ago

Thanks for reporting this issue. Could you add a stacktrace?

coyool commented 5 years ago

sorry , I am very new to python, I don't know how to get stacktrace. you can get this error simply by putting a value of 33333 into the address 33333 which belong to station 233

coyool commented 5 years ago

I problely found the bug is that: when you use struct.pack, you must make sure all the values in the list are between 0~65535(for H pack) stand modbus NEVER predefine the type of values( negative or not), so please remove the signed config, and make it more compatble \umodbus\functions.py line 728

        val = []
        for d in data:
            tmp = d
            if tmp<0 :
                tmp = 65536+d
            val.append(tmp)
        return struct.pack(fmt, self.function_code, len(data) * 2, *val)