python-snap7 3.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ """
2
+ The :code:`__main__` module is used as an entrypoint when calling the module from the terminal using python -m flag.
3
+ It contains functions providing a command-line interface to the server module.
4
+
5
+ Its :code:`main()` function is also exported as a console-entrypoint.
6
+ """
7
+
8
+ import logging
9
+
10
+ try:
11
+ import click
12
+ except ImportError:
13
+ print("Try using 'pip install python-snap7[cli]'")
14
+ raise
15
+
16
+ from snap7 import __version__
17
+ from snap7.server import mainloop
18
+
19
+ logger = logging.getLogger("Snap7.Server")
20
+
21
+
22
+ @click.command()
23
+ @click.option("-p", "--port", default=1102, help="Port the server will listen on.")
24
+ @click.option("-v", "--verbose", is_flag=True, help="Also print debug-output.")
25
+ @click.version_option(__version__)
26
+ @click.help_option("-h", "--help")
27
+ def main(port: int, verbose: bool) -> None:
28
+ """Start a S7 dummy server with some default values."""
29
+
30
+ # setup logging
31
+ if verbose:
32
+ logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.DEBUG)
33
+ else:
34
+ logging.basicConfig(format="[%(levelname)s]: %(message)s", level=logging.INFO)
35
+
36
+ # start the server mainloop
37
+ mainloop(port, init_standard_values=True)
38
+
39
+
40
+ if __name__ == "__main__":
41
+ main()
snap7/type.py ADDED
@@ -0,0 +1,391 @@
1
+ """
2
+ Python equivalent for snap7 specific types.
3
+ """
4
+
5
+ from _ctypes import Array
6
+ from ctypes import (
7
+ c_int16,
8
+ c_int8,
9
+ c_int32,
10
+ c_void_p,
11
+ c_ubyte,
12
+ c_uint64,
13
+ c_uint16,
14
+ c_uint32,
15
+ Structure,
16
+ POINTER,
17
+ c_char,
18
+ c_byte,
19
+ c_int,
20
+ c_uint8,
21
+ )
22
+ from datetime import datetime, date, timedelta
23
+ from enum import IntEnum
24
+ from typing import Dict, Union, Literal
25
+
26
+ CDataArrayType = Union[
27
+ Array[c_byte], Array[c_int], Array[c_int16], Array[c_int32], Array[c_uint8], Array[c_uint16], Array[c_uint32]
28
+ ]
29
+ CDataType = Union[type[c_int8], type[c_int16], type[c_int32], type[c_uint8], type[c_uint16], type[c_uint32]]
30
+ ValueType = Union[int, float, str, datetime, bytearray, bytes, date, timedelta]
31
+
32
+ Context = Literal["client", "server", "partner"]
33
+
34
+ S7Object = c_void_p
35
+ buffer_size = 65536
36
+ # noinspection PyTypeChecker
37
+ buffer_type = c_ubyte * buffer_size
38
+ time_t = c_uint64
39
+ word = c_uint16
40
+ longword = c_uint32
41
+
42
+ # mask types
43
+ mkEvent = 0
44
+ mkLog = 1
45
+
46
+
47
+ class Parameter(IntEnum):
48
+ """
49
+ The snap7 parameter types
50
+ """
51
+
52
+ LocalPort = 1
53
+ RemotePort = 2
54
+ PingTimeout = 3
55
+ SendTimeout = 4
56
+ RecvTimeout = 5
57
+ WorkInterval = 6
58
+ SrcRef = 7
59
+ DstRef = 8
60
+ SrcTSap = 9
61
+ PDURequest = 10
62
+ MaxClients = 11
63
+ BSendTimeout = 12
64
+ BRecvTimeout = 13
65
+ RecoveryTime = 14
66
+ KeepAliveTime = 15
67
+
68
+ @property
69
+ def ctype(self) -> CDataType:
70
+ map_: Dict[int, CDataType] = {
71
+ self.LocalPort: c_uint16,
72
+ self.RemotePort: c_uint16,
73
+ self.PingTimeout: c_int32,
74
+ self.SendTimeout: c_int32,
75
+ self.RecvTimeout: c_int32,
76
+ self.WorkInterval: c_int32,
77
+ self.SrcRef: c_uint16,
78
+ self.DstRef: c_uint16,
79
+ self.SrcTSap: c_uint16,
80
+ self.PDURequest: c_int32,
81
+ self.MaxClients: c_int32,
82
+ self.BSendTimeout: c_int32,
83
+ self.BRecvTimeout: c_int32,
84
+ self.RecoveryTime: c_uint32,
85
+ self.KeepAliveTime: c_uint32,
86
+ }
87
+ return map_[self]
88
+
89
+
90
+ # Area ID
91
+ # Word Length
92
+ class WordLen(IntEnum):
93
+ """
94
+ The snap7 word length types
95
+ """
96
+
97
+ Bit = 0x01
98
+ Byte = 0x02
99
+ Char = 0x03
100
+ Word = 0x04
101
+ Int = 0x05
102
+ DWord = 0x06
103
+ DInt = 0x07
104
+ Real = 0x08
105
+ Counter = 0x1C
106
+ Timer = 0x1D
107
+
108
+ @property
109
+ def ctype(self) -> CDataType:
110
+ map_: Dict[WordLen, CDataType] = {
111
+ WordLen.Bit: c_int16,
112
+ WordLen.Byte: c_int8,
113
+ WordLen.Word: c_int16,
114
+ WordLen.DWord: c_int32,
115
+ WordLen.Real: c_int32,
116
+ WordLen.Counter: c_int16,
117
+ WordLen.Timer: c_int16,
118
+ }
119
+ return map_[self]
120
+
121
+
122
+ class Area(IntEnum):
123
+ """
124
+ The snap7 area types
125
+ """
126
+
127
+ PE = 0x81
128
+ PA = 0x82
129
+ MK = 0x83
130
+ DB = 0x84
131
+ CT = 0x1C
132
+ TM = 0x1D
133
+
134
+ def wordlen(self) -> WordLen:
135
+ if self == Area.TM:
136
+ return WordLen.Timer
137
+ elif self == Area.CT:
138
+ return WordLen.Counter
139
+ return WordLen.Byte
140
+
141
+
142
+ # backwards compatible alias
143
+ Areas = Area
144
+
145
+
146
+ class SrvArea(IntEnum):
147
+ """
148
+ The snap7 server area types
149
+
150
+ NOTE: these values are DIFFERENT from the normal area IDs.
151
+ """
152
+
153
+ PE = 0
154
+ PA = 1
155
+ MK = 2
156
+ CT = 3
157
+ TM = 4
158
+ DB = 5
159
+
160
+
161
+ class Block(IntEnum):
162
+ """
163
+ The snap7 block type
164
+ """
165
+
166
+ OB = 0x38
167
+ DB = 0x41
168
+ SDB = 0x42
169
+ FC = 0x43
170
+ SFC = 0x44
171
+ FB = 0x45
172
+ SFB = 0x46
173
+
174
+ @property
175
+ def ctype(self) -> c_int:
176
+ return c_int(self)
177
+
178
+
179
+ server_statuses = {
180
+ 0: "SrvStopped",
181
+ 1: "SrvRunning",
182
+ 2: "SrvError",
183
+ }
184
+
185
+ cpu_statuses = {
186
+ 0: "S7CpuStatusUnknown",
187
+ 4: "S7CpuStatusStop",
188
+ 8: "S7CpuStatusRun",
189
+ }
190
+
191
+
192
+ class SrvEvent(Structure):
193
+ """
194
+ The snap7 server event structure
195
+ """
196
+
197
+ _fields_ = [
198
+ ("EvtTime", time_t),
199
+ ("EvtSender", c_int),
200
+ ("EvtCode", longword),
201
+ ("EvtRetCode", word),
202
+ ("EvtParam1", word),
203
+ ("EvtParam2", word),
204
+ ("EvtParam3", word),
205
+ ("EvtParam4", word),
206
+ ]
207
+
208
+ def __str__(self) -> str:
209
+ return (
210
+ f"<event time: {self.EvtTime} sender: {self.EvtSender} code: {self.EvtCode} "
211
+ f"return code: {self.EvtRetCode} param1: {self.EvtParam1} param2:{self.EvtParam2} "
212
+ f"param3: {self.EvtParam3} param4: {self.EvtParam4}>"
213
+ )
214
+
215
+
216
+ class BlocksList(Structure):
217
+ """
218
+ The snap7 block list structure
219
+ """
220
+
221
+ _fields_ = [
222
+ ("OBCount", c_int32),
223
+ ("FBCount", c_int32),
224
+ ("FCCount", c_int32),
225
+ ("SFBCount", c_int32),
226
+ ("SFCCount", c_int32),
227
+ ("DBCount", c_int32),
228
+ ("SDBCount", c_int32),
229
+ ]
230
+
231
+ def __str__(self) -> str:
232
+ return (
233
+ f"<block list count OB: {self.OBCount} FB: {self.FBCount} FC: {self.FCCount} SFB: {self.SFBCount} "
234
+ f"SFC: {hex(self.SFCCount)} DB: {self.DBCount} SDB: {self.SDBCount}>"
235
+ )
236
+
237
+
238
+ # noinspection PyTypeChecker
239
+ class TS7BlockInfo(Structure):
240
+ _fields_ = [
241
+ ("BlkType", c_int32),
242
+ ("BlkNumber", c_int32),
243
+ ("BlkLang", c_int32),
244
+ ("BlkFlags", c_int32),
245
+ ("MC7Size", c_int32),
246
+ ("LoadSize", c_int32),
247
+ ("LocalData", c_int32),
248
+ ("SBBLength", c_int32),
249
+ ("CheckSum", c_int32),
250
+ ("Version", c_int32),
251
+ ("CodeDate", c_char * 11),
252
+ ("IntfDate", c_char * 11),
253
+ ("Author", c_char * 9),
254
+ ("Family", c_char * 9),
255
+ ("Header", c_char * 9),
256
+ ]
257
+
258
+ def __str__(self) -> str:
259
+ return f"""\
260
+ Block type: {self.BlkType}
261
+ Block number: {self.BlkNumber}
262
+ Block language: {self.BlkLang}
263
+ Block flags: {self.BlkFlags}
264
+ MC7Size: {self.MC7Size}
265
+ Load memory size: {self.LoadSize}
266
+ Local data: {self.LocalData}
267
+ SBB Length: {self.SBBLength}
268
+ Checksum: {self.CheckSum}
269
+ Version: {self.Version}
270
+ Code date: {self.CodeDate}
271
+ Interface date: {self.IntfDate}
272
+ Author: {self.Author}
273
+ Family: {self.Family}
274
+ Header: {self.Header}"""
275
+
276
+
277
+ class S7DataItem(Structure):
278
+ """ """
279
+
280
+ _pack_ = 1
281
+ _layout_ = "ms"
282
+ _fields_ = [
283
+ ("Area", c_int32),
284
+ ("WordLen", c_int32),
285
+ ("Result", c_int32),
286
+ ("DBNumber", c_int32),
287
+ ("Start", c_int32),
288
+ ("Amount", c_int32),
289
+ ("pData", POINTER(c_uint8)),
290
+ ]
291
+
292
+ def __str__(self) -> str:
293
+ return (
294
+ f"<S7DataItem Area: {self.Area} WordLen: {self.WordLen} Result: {self.Result} "
295
+ f"DBNumber: {self.DBNumber} Start: {self.Start} Amount: {self.Amount} pData: {self.pData}>"
296
+ )
297
+
298
+
299
+ # noinspection PyTypeChecker
300
+ class S7CpuInfo(Structure):
301
+ """
302
+ S7CpuInfo class for handling CPU with :
303
+ - ModuleTypeName => Model of S7-CPU
304
+ - SerialNumber => SN of the S7-CPU
305
+ - ASName => Family Class of the S7-CPU
306
+ - Copyright => Siemens Copyright
307
+ - ModuleName => TIA project name or for other S7-CPU, same as ModuleTypeName
308
+
309
+ """
310
+
311
+ _fields_ = [
312
+ ("ModuleTypeName", c_char * 33),
313
+ ("SerialNumber", c_char * 25),
314
+ ("ASName", c_char * 25),
315
+ ("Copyright", c_char * 27),
316
+ ("ModuleName", c_char * 25),
317
+ ]
318
+
319
+ def __str__(self) -> str:
320
+ return (
321
+ f"<S7CpuInfo ModuleTypeName: {self.ModuleTypeName} SerialNumber: {self.SerialNumber} "
322
+ f"ASName: {self.ASName} Copyright: {self.Copyright} ModuleName: {self.ModuleName}>"
323
+ )
324
+
325
+
326
+ class S7SZLHeader(Structure):
327
+ """
328
+ LengthDR: Length of a data record of the partial list in bytes
329
+ NDR: Number of data records contained in the partial list
330
+ """
331
+
332
+ _fields_ = [("LengthDR", c_uint16), ("NDR", c_uint16)]
333
+
334
+ def __str__(self) -> str:
335
+ return f"<S7SZLHeader LengthDR: {self.LengthDR}, NDR: {self.NDR}>"
336
+
337
+
338
+ class S7SZL(Structure):
339
+ """See §33.1 of System Software for S7-300/400 System and Standard Functions"""
340
+
341
+ _fields_ = [("Header", S7SZLHeader), ("Data", c_ubyte * (0x4000 - 4))]
342
+
343
+ def __str__(self) -> str:
344
+ return f"<S7SZL Header: {self.S7SZHeader}, Data: {self.Data}>"
345
+
346
+
347
+ class S7SZLList(Structure):
348
+ _fields_ = [("Header", S7SZLHeader), ("List", word * (0x4000 - 2))]
349
+
350
+
351
+ class S7OrderCode(Structure):
352
+ _fields_ = [("OrderCode", c_char * 21), ("V1", c_ubyte), ("V2", c_ubyte), ("V3", c_ubyte)]
353
+
354
+
355
+ class S7CpInfo(Structure):
356
+ """
357
+ S7 Cp class for Communication Information :
358
+ - MaxPduLength => Size of the maximum PDU length in bytes
359
+ - MaxConnections => Max connection allowed to S7-CPU or Server
360
+ - MaxMpiRate => MPI rate (MPI use is deprecated)
361
+ - MaxBusRate => Profibus rate
362
+
363
+ Every data packet exchanged with a PLC must fit within the PDU size,
364
+ whose is fixed from 240 up to 960 bytes.
365
+
366
+ """
367
+
368
+ _fields_ = [
369
+ ("MaxPduLength", c_uint16),
370
+ ("MaxConnections", c_uint16),
371
+ ("MaxMpiRate", c_uint16),
372
+ ("MaxBusRate", c_uint16),
373
+ ]
374
+
375
+ def __str__(self) -> str:
376
+ return (
377
+ f"<S7CpInfo MaxPduLength: {self.MaxPduLength} MaxConnections: {self.MaxConnections} "
378
+ f"MaxMpiRate: {self.MaxMpiRate} MaxBusRate: {self.MaxBusRate}>"
379
+ )
380
+
381
+
382
+ class S7Protection(Structure):
383
+ """See §33.19 of System Software for S7-300/400 System and Standard Functions"""
384
+
385
+ _fields_ = [
386
+ ("sch_schal", word),
387
+ ("sch_par", word),
388
+ ("sch_rel", word),
389
+ ("bart_sch", word),
390
+ ("anl_sch", word),
391
+ ]
snap7/util/__init__.py ADDED
@@ -0,0 +1,108 @@
1
+ from .setters import (
2
+ set_bool,
3
+ set_fstring,
4
+ set_string,
5
+ set_wstring,
6
+ set_real,
7
+ set_dword,
8
+ set_udint,
9
+ set_dint,
10
+ set_uint,
11
+ set_int,
12
+ set_word,
13
+ set_byte,
14
+ set_char,
15
+ set_wchar,
16
+ set_usint,
17
+ set_sint,
18
+ set_time,
19
+ set_lreal,
20
+ set_lword,
21
+ set_date,
22
+ set_tod,
23
+ set_dtl,
24
+ set_dt,
25
+ )
26
+
27
+ from .getters import (
28
+ get_bool,
29
+ get_fstring,
30
+ get_string,
31
+ get_wstring,
32
+ get_real,
33
+ get_dword,
34
+ get_udint,
35
+ get_dint,
36
+ get_uint,
37
+ get_int,
38
+ get_word,
39
+ get_byte,
40
+ get_s5time,
41
+ get_dt,
42
+ get_usint,
43
+ get_sint,
44
+ get_time,
45
+ get_date,
46
+ get_tod,
47
+ get_lreal,
48
+ get_lword,
49
+ get_ltime,
50
+ get_ltod,
51
+ get_ldt,
52
+ get_char,
53
+ get_wchar,
54
+ get_dtl,
55
+ )
56
+
57
+ __all__ = [
58
+ "get_bool",
59
+ "get_real",
60
+ "get_dword",
61
+ "get_udint",
62
+ "get_dint",
63
+ "get_uint",
64
+ "get_int",
65
+ "get_word",
66
+ "get_byte",
67
+ "get_usint",
68
+ "get_sint",
69
+ "get_time",
70
+ "get_date",
71
+ "get_tod",
72
+ "get_lreal",
73
+ "get_lword",
74
+ "get_ltime",
75
+ "get_ltod",
76
+ "get_ldt",
77
+ "get_char",
78
+ "get_wchar",
79
+ "get_dtl",
80
+ "get_s5time",
81
+ "get_dt",
82
+ "get_fstring",
83
+ "get_string",
84
+ "get_wstring",
85
+ "set_real",
86
+ "set_dword",
87
+ "set_date",
88
+ "set_lreal",
89
+ "set_lword",
90
+ "set_udint",
91
+ "set_dint",
92
+ "set_uint",
93
+ "set_int",
94
+ "set_word",
95
+ "set_byte",
96
+ "set_char",
97
+ "set_wchar",
98
+ "set_usint",
99
+ "set_sint",
100
+ "set_time",
101
+ "set_bool",
102
+ "set_fstring",
103
+ "set_string",
104
+ "set_wstring",
105
+ "set_tod",
106
+ "set_dtl",
107
+ "set_dt",
108
+ ]