2 # -*- coding: utf-8 -*- |
2 # -*- coding: utf-8 -*- |
3 # |
3 # |
4 # See COPYING.Runtime file for copyrights details. |
4 # See COPYING.Runtime file for copyrights details. |
5 # |
5 # |
6 |
6 |
7 import ctypes |
|
8 from ctypes import * |
7 from ctypes import * |
9 from datetime import timedelta as td |
8 from datetime import timedelta as td |
10 |
|
11 ctypes.pythonapi.PyUnicode_AsUTF8.argtypes = (ctypes.c_void_p,) |
|
12 ctypes.pythonapi.PyUnicode_AsUTF8.restype = ctypes.POINTER(ctypes.c_char) |
|
13 |
|
14 |
9 |
15 class IEC_STRING(Structure): |
10 class IEC_STRING(Structure): |
16 """ |
11 """ |
17 Must be changed according to changes in iec_types.h |
12 Must be changed according to changes in iec_types.h |
18 """ |
13 """ |
26 """ |
21 """ |
27 _fields_ = [("s", c_long), # tv_sec |
22 _fields_ = [("s", c_long), # tv_sec |
28 ("ns", c_long)] # tv_nsec |
23 ("ns", c_long)] # tv_nsec |
29 |
24 |
30 |
25 |
31 def _t(t, u=lambda x: x.value, p=lambda t, x: t(x)): |
26 def _t(t, u=lambda x: x.contents, p=lambda t, x: t(x)): |
32 return (t, u, p) |
27 return (t, u, p) |
33 |
28 |
34 |
29 |
35 def _ttime(): |
30 def _ttime(): |
36 return (IEC_TIME, |
31 return (IEC_TIME, |
37 lambda x: td(0, x.s, x.ns/1000.0), |
32 lambda x: td(0, x.contents.s, x.contents.ns/1000.0), |
38 lambda t, x: t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000)) |
33 lambda t, x: t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000)) |
39 |
34 |
40 |
35 |
41 SameEndianessTypeTranslator = { |
36 SameEndianessTypeTranslator = { |
42 "BOOL": _t(c_uint8, lambda x: x.value != 0), |
37 "BOOL": _t(c_uint8, lambda x: bool(x.contents)), |
43 "STEP": _t(c_uint8), |
38 "STEP": _t(c_uint8), |
44 "TRANSITION": _t(c_uint8), |
39 "TRANSITION": _t(c_uint8), |
45 "ACTION": _t(c_uint8), |
40 "ACTION": _t(c_uint8), |
46 "SINT": _t(c_int8), |
41 "SINT": _t(c_int8), |
47 "USINT": _t(c_uint8), |
42 "USINT": _t(c_uint8), |
48 "BYTE": _t(c_uint8), |
43 "BYTE": _t(c_uint8), |
49 "STRING": (IEC_STRING, |
44 "STRING": (IEC_STRING, |
50 lambda x: x.body[:x.len], |
45 lambda x: x.contents.body[:x.contents.len], |
51 lambda t, x: t(len(x), x)), |
46 lambda t, x: t(len(x), x)), |
52 "INT": _t(c_int16), |
47 "INT": _t(c_int16), |
53 "UINT": _t(c_uint16), |
48 "UINT": _t(c_uint16), |
54 "WORD": _t(c_uint16), |
49 "WORD": _t(c_uint16), |
55 "DINT": _t(c_int32), |
50 "DINT": _t(c_int32), |
78 |
73 |
79 def UnpackDebugBuffer(buff, indexes): |
74 def UnpackDebugBuffer(buff, indexes): |
80 res = [] |
75 res = [] |
81 buffoffset = 0 |
76 buffoffset = 0 |
82 buffsize = len(buff) |
77 buffsize = len(buff) |
83 buffptr = cast(ctypes.pythonapi.PyString_AsString(id(buff)), c_void_p).value |
78 buffptr = cast(cast(buff, c_char_p), c_void_p).value |
84 for iectype in indexes: |
79 for iectype in indexes: |
85 c_type, unpack_func, _pack_func = \ |
80 c_type, unpack_func, _pack_func = TypeTranslator.get(iectype, |
86 TypeTranslator.get(iectype, (None, None, None)) |
81 (None, None, None)) |
87 |
82 |
88 cursor = c_void_p(buffptr + buffoffset) |
83 cursor = c_void_p(buffptr + buffoffset) |
89 if iectype == "STRING": |
84 if iectype == "STRING": |
90 # strlen is stored in c_uint8 and sizeof(c_uint8) is 1 |
85 # strlen is stored in c_uint8 and sizeof(c_uint8) is 1 |
91 # first check we can read size |
86 # first check we can read size |
95 return None |
90 return None |
96 else: |
91 else: |
97 size = sizeof(c_type) |
92 size = sizeof(c_type) |
98 |
93 |
99 if c_type is not None and (buffoffset + size) <= buffsize: |
94 if c_type is not None and (buffoffset + size) <= buffsize: |
100 value = unpack_func(cast(cursor, |
95 n = cast(cursor, POINTER(c_type)) |
101 POINTER(c_type)).contents) |
96 value = unpack_func(n) |
|
97 if iectype not in ["BOOL", "DATE", "DT", "STRING", "TIME", "TOD"]: |
|
98 value = value.value |
|
99 elif iectype == "STRING": |
|
100 value = value.decode() |
102 buffoffset += size |
101 buffoffset += size |
103 res.append(value) |
102 res.append(value) |
104 else: |
103 else: |
105 return None |
104 return None |
106 if buffoffset and buffoffset == buffsize: |
105 if buffoffset and buffoffset == buffsize: |