|
@@ -1,7 +1,9 @@
|
|
|
+from psutil import cpu_times
|
|
|
import snap7
|
|
|
import time
|
|
|
+import struct
|
|
|
import re
|
|
|
-from datetime import datetime
|
|
|
+from datetime import datetime, tzinfo
|
|
|
|
|
|
from inputs.common import Input
|
|
|
|
|
@@ -10,32 +12,51 @@ localtz = datetime.now().astimezone().tzinfo
|
|
|
class SiemensCPU(Input):
|
|
|
interval = 0.02
|
|
|
|
|
|
+ time_offset = None
|
|
|
+
|
|
|
def __init__(self):
|
|
|
super().__init__(self.read_handler)
|
|
|
self.server = snap7.server.Server(True)
|
|
|
size = 100
|
|
|
- self.DBdata = (snap7.types.wordlen_to_ctypes[snap7.types.WordLen.Byte.value] * size)()
|
|
|
- self.server.register_area(snap7.types.srvAreaDB, 1, self.DBdata)
|
|
|
+ self.DB1 = (snap7.types.wordlen_to_ctypes[snap7.types.WordLen.Byte.value] * size)()
|
|
|
+ self.DB2 = (snap7.types.wordlen_to_ctypes[snap7.types.WordLen.Byte.value] * size)()
|
|
|
+ self.server.register_area(snap7.types.srvAreaDB, 1, self.DB1)
|
|
|
+ self.server.register_area(snap7.types.srvAreaDB, 2, self.DB2)
|
|
|
self.server.start(102)
|
|
|
|
|
|
def read_handler(self):
|
|
|
event : snap7.types.SrvEvent
|
|
|
while event := self.server.pick_event():
|
|
|
- timestamp = datetime.now(localtz)
|
|
|
text = self.server.event_text(event)
|
|
|
match = re.match("^(?P<datetime>\d+-\d+-\d+ \d+:\d+:\d+) \[(?P<host>[\w\.:]+)\] (?P<type>[\w ]+), Area : (?P<area>.+), Start : (?P<start>\d+), Size : (?P<size>\d+) --> (?P<response>.+)$", text)
|
|
|
if not match:
|
|
|
print(text)
|
|
|
continue
|
|
|
|
|
|
- if match.group("type") != "Write request" or match.group("area") != "DB1":
|
|
|
+ if match.group("type") != "Write request":
|
|
|
print(text)
|
|
|
continue
|
|
|
|
|
|
- raw = bytearray(self.DBdata)
|
|
|
-
|
|
|
- #print("{} {:4d} {:4d}".format(timestamp.microsecond, int(match.group("start")), int(match.group("size"))))
|
|
|
- if int(match.group("start")) < 30:
|
|
|
- self.queue_ifm_from_bytes("S7", timestamp, raw[0:30])
|
|
|
- if int(match.group("start")) < 68 and int(match.group("start")) + int(match.group("size")) > 32:
|
|
|
- self.queue_energy_meter_from_bytes("S7", timestamp, raw[32:68])
|
|
|
+ if int(match.group("start")) + int(match.group("size")) <= 4:
|
|
|
+ continue
|
|
|
+
|
|
|
+ if match.group("area") == "DB1":
|
|
|
+ raw = bytearray(self.DB1)
|
|
|
+ timestamp = self.get_timestamp(raw[0:4])
|
|
|
+ self.queue_ifm_from_bytes("S7", timestamp, raw[4:34])
|
|
|
+ elif match.group("area") == "DB2":
|
|
|
+ raw = bytearray(self.DB2)
|
|
|
+ timestamp = self.get_timestamp(raw[0:4])
|
|
|
+ self.queue_energy_meter_from_bytes("S7", timestamp, raw[4:40])
|
|
|
+
|
|
|
+ def get_timestamp(self, raw):
|
|
|
+ now = datetime.now(localtz)
|
|
|
+ cpu_time = struct.unpack(">I", raw)[0] / 1000
|
|
|
+ offset = now.timestamp() - cpu_time
|
|
|
+ if self.time_offset:
|
|
|
+ self.time_offset = self.time_offset * 0.999 + offset * 0.001
|
|
|
+ else:
|
|
|
+ self.time_offset = offset
|
|
|
+
|
|
|
+ timestamp = datetime.fromtimestamp(self.time_offset + cpu_time, localtz)
|
|
|
+ return timestamp
|