#!/usr/bin/env python
# -*- coding: utf-8 -*-

#https://scapy.readthedocs.io/en/latest/api/scapy.packet.html#scapy.packet.Packet
#https://scapy.readthedocs.io/en/latest/api/scapy.contrib.modbus.html

import scapy.all as scapy
import scapy.contrib.modbus as mb

def decode(pkt):
    if "ModbusADU" in pkt:
        global miniL
        modpkt = pkt["ModbusADU"]
        print(modpkt.payload.name)
        for i in modpkt.payload.fields:
            typeCall = ""
            print(i,modpkt.payload.getfieldval(i),type(modpkt.payload.get_field(i)))

            if "Multiple" in modpkt.payload.name:
                typeCall += "m"
            else:
                typeCall += "s"

            if "Coil" in modpkt.payload.name:
                typeCall += "C"
            else:
                typeCall += "R"
            miniL[0] = typeCall


            if "Read" in modpkt.payload.name:
                typeCall += "r"
                if "Response" in modpkt.payload.name:
                    byteCount = modpkt.payload.getfieldval("byteCount")
                    print(byteCount,"cc")
                    cs = []
                    if "C" in typeCall:
                        Value = modpkt.payload.getfieldval("coilStatus")
                        for j in range(byteCount):
                            bi=str(bin(Value[j]))
                            bi=bi[2:]
                            bi=bi.rjust(8,'0')[::-1]
                            cs.extend(k for k in [*bi])
                    else:
                        cs = modpkt.payload.getfieldval("registerVal")
                    for j in range(len(cs)):
                        bigL.append([miniL[0],cs[j],miniL[2]+j])
                    miniL = [0,0,0]
                    print(bigL)
                else:
                    startAddr = modpkt.payload.getfieldval("startAddr")
                    miniL[2] = startAddr
            else:
                typeCall += "w"
                if "Response" in modpkt.payload.name:
                    pass
                else:
                    if "m" in typeCall:
                        addr = modpkt.payload.getfieldval("startAddr")
                        #byteCount = modpkt.payload.getfieldval("quantityOutput")
                        outputValue = modpkt.payload.getfieldval("outputsValue")
                        cs = []
                        if "C" in typeCall:
                            for j in range(len(outputValue)):
                                bi=str(bin(outputValue[j]))
                                bi = bi[2:]
                                bi = bi.rjust(8,'0')[::-1]
                                cs.extend(k for k in [*bi])

                        for j in range(len(cs)):
                            bigL.append([miniL[0],cs[j],addr+j]) # changer 5 pour mettre l'adresse
                        print(bigL)
                    else:
                        if "C" in typeCall:
                            addr = modpkt.payload.getfieldval("outputAddr")
                            outputValue = modpkt.payload.getfieldval("outputValue")
                        else:
                            addr = modpkt.payload.getfieldval("registerAddr")
                            outputValue = modpkt.payload.getfieldval("registerValue")
                        bigL.append([miniL[0],outputValue,addr])

        bigL.append(miniL)
        #print(bigL)
bigL = []
miniL = [0,0,0]
scapy.sniff(iface="lo", prn=decode)
