Blame view

simulators/plc/plcSimulator.py 8.67 KB
20ed1e7a   Etienne Pallier   bugfixed time sav...
1
2
#!/usr/bin/env python3

3c179769   Jeremy   userSimulator / a...
3
import os
ce470283   Jeremy   Plc simulator fin...
4
import sys
6c2793c2   jeremy   Update
5
import json
3c179769   Jeremy   userSimulator / a...
6

75ec5b27   Etienne Pallier   bugfix simulateur...
7
DEBUG_FILE = True
3c179769   Jeremy   userSimulator / a...
8
9
10
11
PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

1957226d   Etienne Pallier   Renamed (simulato...
12
13
#(EP renamed) from utils.Device import Device
from utils.DeviceSim import DeviceSim
605b65e5   Jeremy   Update simulators
14
from utils.StatusManager import StatusManager
3c179769   Jeremy   userSimulator / a...
15

6c2793c2   jeremy   Update
16

1957226d   Etienne Pallier   Renamed (simulato...
17
18
#(EP renamed) class PLCSimulator(Device, StatusManager):
class PLCSimulator(DeviceSim, StatusManager):
75ec5b27   Etienne Pallier   bugfix simulateur...
19
20
21
22
    
    # (EP) This simulator will generate some events ?
    EVENT_GENERATOR=False
    
ce470283   Jeremy   Plc simulator fin...
23
    status = {
6c2793c2   jeremy   Update
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
        "name": "STATUS", "from": "Beckhoff", "version_firmware": "20170809", "site": "OSM-Mexico",
        "date": "2017-03-03T13:45:00",
        "device": [{"name": "WXT520", "type": "meteo", "serial_number": "14656423", "valid": "yes",
                    "values": [
                        {"name": "OutsideTemp", "value": 12.12, "unit": "Celcius", "comment": ""},
                        {"name": "OutsideHumidity", "value": 64.1, "unit": "percent", "comment": ""},
                        {"name": "Pressure", "value": 769.2, "unit": "mbar", "comment": "At site elevation"},
                        {"name": "RainRate", "value": 0.0, "unit": "mm/h", "comment": ""},
                        {"name": "WindSpeed", "value": 3.1, "unit": "m/s", "comment": ""},
                        {"name": "WindDir", "value": 202.3, "unit": "deg", "comment": "(N=0, E=90)"},
                        {"name": "DewPoint", "value": 8.3, "unit": "deg", "comment": ""}
                    ]
                    },
                   {"name": "DRD11", "type": "meteo", "serial_number": "RET6789", "valid": "yes",
                    "values": [
                        {"name": "analog", "value": 2.345, "unit": "V", "comment": "3V=Dry <2.5V=Rain"},
                        {"name": "digital", "value": 1, "unit": "bool", "comment": "1=Dry 0=Rain"}
                    ]
                    },
                   {"name": "VantagePro", "type": "meteo", "serial_number": "ERTRY2344324", "valid": "no",
                    "values": [
                        {"name": "OutsideTemp", "value": 12.45, "unit": "Celcius", "comment": ""},
                        {"name": "InsideTemp", "value": 20.28, "unit": "Celcius", "comment": ""},
                        {"name": "OutsideHumidity", "value": 65.3, "unit": "percent", "comment": ""},
                        {"name": "InsideHumidity", "value": 45.6, "unit": "percent", "comment": ""},
                        {"name": "Pressure", "value": 768.7, "unit": "mbar", "comment": "At site elevation"},
                        {"name": "RainRate", "value": 0.0, "unit": "mm/h", "comment": ""},
                        {"name": "WindSpeed", "value": 2.8, "unit": "m/s", "comment": ""},
                        {"name": "WindDir", "value": 207.0, "unit": "deg", "comment": "(N=0, E=90)"},
                        {"name": "WindDirCardinal", "value": "SW", "unit": "string", "comment": ""},
                        {"name": "DewPoint", "value": 8.5, "unit": "deg", "comment": ""}
                    ]
                    },
                   {"name": "MLX90614-1", "type": "meteo", "serial_number": "Unknown", "valid": "yes",
                    "values": [
                        {"name": "SensorTemperature", "value": 23.56, "unit": "Celcius", "comment": ""},
                        {"name": "SkyTemperature", "value": -15.67, "unit": "Celcius",
                         "comment": "Clear<-10 VeryCloudy>4"}
                    ]
                    },
                   {"name": "LAMP_FLAT_CAGIRE", "type": "calib", "serial_number": "REF_3434", "valid": "yes",
                    "values": [
                        {"name": "status", "value": "on", "unit": "string", "comment": "on or off"},
                        {"name": "current", "value": 0.234, "unit": "Ampere", "comment": ""}
                    ]
                    },
                   {"name": "LAMP FLAT CAGIRE", "type": "calib", "serial_number": "REF_3434", "valid": "yes",
                    "values": [
                        {"name": "status", "value": "on", "unit": "string", "comment": "on or off"},
                        {"name": "current", "value": 0.234, "unit": "Ampere", "comment": ""}
                    ]
                    }
                   ]
ce470283   Jeremy   Plc simulator fin...
77
    }
86dd6e43   Jeremy   Simulator script ...
78

6c2793c2   jeremy   Update
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    list = {"name": "LIST", "from": "Beckhoff", "version_firmware": "20170809", "site": "OSM-Mexico",
            "date": "2017-03-03T13:42:46",
            "command": [
                {"name": "LIST", "type": "",
                 "parameters": ""
                 },
                {"name": "SATUS", "type": "",
                 "parameters": ""
                 },
                {"name": "LAMP_FLAT_CAGIRE", "type": "calib",
                 "parameters": [
                     {"name": "value", "unit": "string", "comment": "on or off", "default": ""},
                     {"name": "current", "unit": "Ampere", "comment": "", "default": "0.345"}
                 ]
                 }
            ]
            }

65149de7   Jeremy   Update
97
    def __init__(self, argv):
75ec5b27   Etienne Pallier   bugfix simulateur...
98
        # DeviceSim init
605b65e5   Jeremy   Update simulators
99
        super().__init__(argv)
c7583f6e   Etienne Pallier   Cleaner isolation...
100
        # Listen to its own ip and port (the PLC's)
605b65e5   Jeremy   Update simulators
101
        self.setDevice("PLC")
75ec5b27   Etienne Pallier   bugfix simulateur...
102
103
104
105
        #EP added
        if (len(argv) > 1):
            self.setStatusManager("plcSimulator", argv)
            self.EVENT_GENERATOR = True
3c179769   Jeremy   userSimulator / a...
106

b6b0fd47   Jeremy   Added parameters ...
107
    def plcPrint(self, string: str):
3224f14a   Jeremy   Fixed some simula...
108
109
        if DEBUG_FILE:
            print("PLCSimulator : " + string)
3c179769   Jeremy   userSimulator / a...
110

6c2793c2   jeremy   Update
111
112
    def updateStatus(self, i: int):
        for dic in self.sims:
c7583f6e   Etienne Pallier   Cleaner isolation...
113
            # ex: dic is like "plcSimulator" : {"device_name":"VantagePro", "value_name":"RainRate", "value":12.0} 
6c2793c2   jeremy   Update
114
            if (int(dic["time"]) == i):
c7583f6e   Etienne Pallier   Cleaner isolation...
115
116
117
                print(dic)
                change = dic[self.status_name] # ex: {"device_name":"VantagePro", "value_name":"RainRate", "value":12.0} 
                device_name = change["device_name"] # ex: VantagePro
6c2793c2   jeremy   Update
118
119
120
121
                devices = self.status["device"]
                for device in devices:
                    if device["name"] == device_name:
                        values = device["values"]
c7583f6e   Etienne Pallier   Cleaner isolation...
122
123
124
125
126
                        # ex: for VantagePro
                        # values =
                        # {"name": "OutsideTemp", "value": 12.45, "unit": "Celcius", "comment": ""},
                        # {"name": "InsideTemp", "value": 20.28, "unit": "Celcius", "comment": ""},
                        #...
6c2793c2   jeremy   Update
127
128
                        for value in values:
                            if value["name"] == change["value_name"]:
c7583f6e   Etienne Pallier   Cleaner isolation...
129
                                # This will indirectly update self.status
6c2793c2   jeremy   Update
130
131
132
                                value["value"] = change["value"]
        return 0

ce470283   Jeremy   Plc simulator fin...
133

f7dd3df1   Jeremy   Update simulators...
134
    def handleConnections(self):
c7583f6e   Etienne Pallier   Cleaner isolation...
135
136
137
138
139
        print("number of connexions to handle: "+str(len(self.connections)))
        for conn in self.connections:
            print("current connexion: ")
            print(conn)
            data = self.readBytes(1024, conn)
6c2793c2   jeremy   Update
140
141
            answer = "["
            count = False
c7583f6e   Etienne Pallier   Cleaner isolation...
142
143
            #if data != "" and self.isError(data) is False:
            if data != "" and not self.isError(data):
fe5613f5   jeremy   Update plc protocol
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
                json_array = json.loads(data)
                command_list = json_array["command"]
                for command in command_list:
                    if command["name"] == "STATUS":
                        if count:
                            answer += ','
                        answer += json.dumps(self.status)
                        count = True
                    elif command["name"] == "LIST":
                        if count:
                            answer += ','
                        answer += json.dumps(self.status)
                        count = True
                    else:
                        print("command received by PLC simulator : [>>> "+ str(command["name"]) + " <<<] unknown")
                answer += ']'
                if len(answer) > 0 and answer != "[]":
c7583f6e   Etienne Pallier   Cleaner isolation...
161
                    self.sendMessage(answer, conn)
3c179769   Jeremy   userSimulator / a...
162
163
164
165
166
        return (0)

    def loop(self):
        i = 0

75ec5b27   Etienne Pallier   bugfix simulateur...
167
        if (self.EVENT_GENERATOR and self.ended==0):
c7583f6e   Etienne Pallier   Cleaner isolation...
168
169
            self.plcPrint("No entry for PLC found in config file : " + self.config_file)
            return False
3c179769   Jeremy   userSimulator / a...
170
        while (True):
c7583f6e   Etienne Pallier   Cleaner isolation...
171
            print("\n\n\nIteration "+str(i)+" :")
75ec5b27   Etienne Pallier   bugfix simulateur...
172
            if self.EVENT_GENERATOR: self.updateStatus(i)
605b65e5   Jeremy   Update simulators
173
            if (self.isConnected()):
f7dd3df1   Jeremy   Update simulators...
174
                self.handleConnections()
605b65e5   Jeremy   Update simulators
175
            i += 1
75ec5b27   Etienne Pallier   bugfix simulateur...
176
            if (self.EVENT_GENERATOR and i > self.ended): return (0)
c7583f6e   Etienne Pallier   Cleaner isolation...
177
        return True
86dd6e43   Jeremy   Simulator script ...
178
179

    def run(self):
3224f14a   Jeremy   Fixed some simula...
180
        if DEBUG_FILE:
c7583f6e   Etienne Pallier   Cleaner isolation...
181
            print("PLC simulator running...")
75ec5b27   Etienne Pallier   bugfix simulateur...
182
        if self.EVENT_GENERATOR and not self.parse(): return False
3c179769   Jeremy   userSimulator / a...
183
        self.configSocket()
c7583f6e   Etienne Pallier   Cleaner isolation...
184
185
        return self.loop()
        #return (0)
86dd6e43   Jeremy   Simulator script ...
186

6c2793c2   jeremy   Update
187

86dd6e43   Jeremy   Simulator script ...
188
189
190
if __name__ == "__main__":
    sim = PLCSimulator(sys.argv)
    sim.run()