import struct
import time
import serial

fc_mapping = {
    1: ("Read Coil Status", "input"),
    2: ("Read Input Status", "input"),
    3: ("Read Holding Registers", "input"),
    4: ("Read Input Registers ", "input"),
    5: ("Force Single Coil", "output"),
    6: ("Force Single Register", "output"),
    15: ("Force Multiple Coils", "output"),
    16: ("Preset Multiple Registers", "output"),
    101: ("Huanyang VFD", "output"),
}


def crc16(data: bytearray, offset=0, length=None):
    if length is None:
        length = len(data) - offset
    if data is None or offset < 0 or offset > len(data) - 1 and offset + length > len(data):
        return 0
    crc = 0xFFFF
    for i in range(length):
        crc ^= data[offset + i]
        for j in range(8):
            if (crc & 0x1) == 1:
                crc = int((crc / 2)) ^ 40961
            else:
                crc = int(crc / 2)
    csum = crc & 0xFFFF
    return [csum & 0xFF, (csum >> 8) & 0xFF]


def int2list(value):
    return [(value >> 8 & 0xFF), (value & 0xFF)]


def list2int(data):
    return (data[0] << 8) | (data[1])


ser = serial.Serial("/dev/ttyUSB2", 9600, timeout=0.01, parity=serial.PARITY_NONE)

registers = {
    4097: 110,
    4098: 10, 
}

while True:
    response = list(ser.read(100))
    if response:
        addr = response[0]
        ctype = response[1]
        if ctype == 3:
            reg = struct.unpack(">H", bytearray(response[2:4]))[0]
            vlen = struct.unpack(">H", bytearray(response[4:6]))[0]

            """
            print("REC:", response)
            print(" ADDR:", addr)
            print(" TYPE:", ctype)
            print(" REG:", reg)
            print(" LEN:", vlen)
            """

            value = registers.get(reg, 0)
            data = [response[0], response[1],  2] + list(struct.pack(">H", value))
            csum = crc16(data)
            frame = data + csum
            #print(" SEND:", frame)
            ser.write(bytes(frame))

            registers[reg] += 1


        elif ctype == 6:
            reg = struct.unpack(">H", bytearray(response[2:4]))[0]
            value = struct.unpack(">H", bytearray(response[4:6]))[0]

            print("REC:", response)
            print(" ADDR:", addr)
            print(" TYPE:", ctype)
            print(" REG:", reg)
            print(" VAL:", value)


            ser.write(bytes(response))


