Siemens LOGO! PLC data in the wrong order

311 views Asked by At

So I'm accessing an Siemens LOGO! PLC to extract some data from. I managed to do that with my work partner but we're stuck on how the data is being saved. The data is being timestamped in a dictionary with the output and input bytes from the PLC. But the data comes in a certain order and is timestamped the moment the data is extracted.

Now the problem is that the timestamps and data isn't saved in the same order that the data comes in. Somewhere in the process it makes a mistake (I think), but we can't seem to find it.

Here's the Python Code we use:

# initial testing to connect to a PLC
#connects to PLC save I/O into json format with timestamp
import snap7
import time
import ctypes
import math
import json

PLCip = "x.x.x.x" #input  ip
Port = 000 # input port
Rack = 0
Slot = 1
size_to_read = 100
datadb = (ctypes.c_uint8 * size_to_read)()

#creates client and connect to plc, returns true if connected
Client = snap7.client.Client()
Client.connect(PLCip, Rack, Slot)
print("Connected:", Client.get_connected())

#converts sum INT to bits
def access_bit(data, num):
    base = int(num // 8)
    shift = int(num % 8)
    return (data[base] & (1<<shift)) >> shift

#empty dict for storing I/O data
mydata = {}

#save data dict to json format
def save_to_file(stamp, input, output, file):
    mydata[stamp] = {'input': input, 'output': output}
    with open(file,'a') as f:
        json.dump(mydata, f)

while True:
    # ts = time.time()    #gets current time 
    _now = time.time()
    ts = time.localtime(_now)
    # timestamp = (time.strftime('%H:%M:%S',ts),str('%.3f'%_now).split('.')[1])
    timestamp = time.strftime('%X',ts)
    datestamp = time.strftime('%d-%m-%Y',ts)
    log_folder='logs/'
    color=['black/','orange/','metal/']

    #json_file = str(log_folder)+str(datestamp)+'-'+str(timestamp)+'.json'
    json_file = str(log_folder)+str(color[2])+str(datestamp)+'.json'

    data = Client.eb_read(0,2)  # reads input data from 2 bytes
    data_input = format(int.from_bytes(data, "little"), "b")    #converts from int to bits

    outputdata = Client.ab_read(0,2)    #reads output data from 2 bytes
    data_output = format(int.from_bytes(outputdata, "little"), "b")    #converts from int to bits

    #save it to json file with parameters
    save_to_file(timestamp,data_input,data_output, json_file)
    #print to cli for debugging
    print_text= "Time: {}\nInput: {}\nOutput: {}\n".format(timestamp,data_input,data_output)
    print(print_text)
    #wait 1 second and restart
    time.sleep(1)

And the data we get:

{"13:41:57": {"input": "1001010000", "output": "0"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}, "13:42:01": {"input": "1001010000", "output": "1001"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}, "13:42:01": {"input": "1001010000", "output": "1001"}, "13:42:02": {"input": "1010010000", "output": "101"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}, "13:42:01": {"input": "1001010000", "output": "1001"}, "13:42:02": {"input": "1010010000", "output": "101"}, "13:42:03": {"input": "1010010000", "output": "101"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}, "13:42:01": {"input": "1001010000", "output": "1001"}, "13:42:02": {"input": "1010010000", "output": "101"}, "13:42:03": {"input": "1010010000", "output": "101"}, "13:42:04": {"input": "1001010000", "output": "0"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", "output": "0"}, "13:42:00": {"input": "1001010000", "output": "0"}, "13:42:01": {"input": "1001010000", "output": "1001"}, "13:42:02": {"input": "1010010000", "output": "101"}, "13:42:03": {"input": "1010010000", "output": "101"}, "13:42:04": {"input": "1001010000", "output": "0"}, "13:42:05": {"input": "1001010001", "output": "1001"}}{"13:41:57": {"input": "1001010000", "output": "0"}, "13:41:58": {"input": "1001010000", "output": "0"}, "13:41:59": {"input": "1001010000", 

This is one continuous execution of the script. As you can see the timestamps aren't really in order. Can anyone help us solve this problem. Maybe you guys can see something I can't see.

Many thanks!

1

There are 1 answers

0
JD_Bachelor On BEST ANSWER

I found out why it was so duplicating the data packets. Because the dict data is defined outside the while loop it keeps adding new keys,values to the dict. The dict is being wrapped into a json file and keeps getting exponentially increasing.

The dict data needs to be defined inside the while loop so that it can be reused every time it dumps the dict into the json.

...
#save data dict to json format
def save_to_file(stamp, input, output, file):
    mydata[stamp] = {'input': input, 'output': output}
    with open(file,'a') as f:
        json.dump(mydata, f)

while True:
    mydata={}
    # ts = time.time()    #gets current time 
    _now = time.time()
    ts = time.localtime(_now)
    # timestamp = (time.strftime('%H:%M:%S',ts),str('%.3f'%_now).split('.')[1])
    timestamp = time.strftime('%X',ts)
    datestamp = time.strftime('%d-%m-%Y',ts)
    log_folder='logs/'
    color=['black/','orange/','metal/']
...