1 #!/usr/bin/env python |
|
2 # -*- coding: utf-8 -*- |
|
3 |
|
4 # This file is part of Beremiz, runtime and an Integrated Development Environment for |
|
5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. |
|
6 # |
|
7 # Copyright (C) 2011: Edouard TISSERANT and Laurent BESSARD |
|
8 # |
|
9 # See COPYING.Runtime file for copyrights details. |
|
10 # |
|
11 # This library is free software; you can redistribute it and/or |
|
12 # modify it under the terms of the GNU Lesser General Public |
|
13 # License as published by the Free Software Foundation; either |
|
14 # version 2.1 of the License, or (at your option) any later version. |
|
15 |
|
16 # This library is distributed in the hope that it will be useful, |
|
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 # Lesser General Public License for more details. |
|
20 |
|
21 # You should have received a copy of the GNU Lesser General Public |
|
22 # License along with this library; if not, write to the Free Software |
|
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
24 |
|
25 |
|
26 from __future__ import absolute_import |
|
27 import ctypes |
|
28 from ctypes import * |
|
29 from datetime import timedelta as td |
|
30 |
|
31 ctypes.pythonapi.PyString_AsString.argtypes = (ctypes.c_void_p,) |
|
32 ctypes.pythonapi.PyString_AsString.restype = ctypes.POINTER(ctypes.c_char) |
|
33 |
|
34 |
|
35 class IEC_STRING(Structure): |
|
36 """ |
|
37 Must be changed according to changes in iec_types.h |
|
38 """ |
|
39 _fields_ = [("len", c_uint8), |
|
40 ("body", c_char * 126)] |
|
41 |
|
42 |
|
43 class IEC_TIME(Structure): |
|
44 """ |
|
45 Must be changed according to changes in iec_types.h |
|
46 """ |
|
47 _fields_ = [("s", c_long), # tv_sec |
|
48 ("ns", c_long)] # tv_nsec |
|
49 |
|
50 |
|
51 def _t(t, u=lambda x: x.value, p=lambda t, x: t(x)): |
|
52 return (t, u, p) |
|
53 |
|
54 |
|
55 def _ttime(): |
|
56 return (IEC_TIME, |
|
57 lambda x: td(0, x.s, x.ns/1000), |
|
58 lambda t, x: t(x.days * 24 * 3600 + x.seconds, x.microseconds*1000)) |
|
59 |
|
60 |
|
61 SameEndianessTypeTranslator = { |
|
62 "BOOL": _t(c_uint8, lambda x: x.value != 0), |
|
63 "STEP": _t(c_uint8), |
|
64 "TRANSITION": _t(c_uint8), |
|
65 "ACTION": _t(c_uint8), |
|
66 "SINT": _t(c_int8), |
|
67 "USINT": _t(c_uint8), |
|
68 "BYTE": _t(c_uint8), |
|
69 "STRING": (IEC_STRING, |
|
70 lambda x: x.body[:x.len], |
|
71 lambda t, x: t(len(x), x)), |
|
72 "INT": _t(c_int16), |
|
73 "UINT": _t(c_uint16), |
|
74 "WORD": _t(c_uint16), |
|
75 "DINT": _t(c_int32), |
|
76 "UDINT": _t(c_uint32), |
|
77 "DWORD": _t(c_uint32), |
|
78 "LINT": _t(c_int64), |
|
79 "ULINT": _t(c_uint64), |
|
80 "LWORD": _t(c_uint64), |
|
81 "REAL": _t(c_float), |
|
82 "LREAL": _t(c_double), |
|
83 "TIME": _ttime(), |
|
84 "TOD": _ttime(), |
|
85 "DATE": _ttime(), |
|
86 "DT": _ttime(), |
|
87 } |
|
88 |
|
89 SwapedEndianessTypeTranslator = { |
|
90 # TODO |
|
91 } |
|
92 |
|
93 TypeTranslator = SameEndianessTypeTranslator |
|
94 |
|
95 # Construct debugger natively supported types |
|
96 DebugTypesSize = dict([(key, sizeof(t)) for key, (t, p, u) in SameEndianessTypeTranslator.iteritems() if t is not None]) |
|
97 |
|
98 |
|
99 def UnpackDebugBuffer(buff, indexes): |
|
100 res = [] |
|
101 buffoffset = 0 |
|
102 buffsize = len(buff) |
|
103 buffptr = cast(ctypes.pythonapi.PyString_AsString(id(buff)), c_void_p).value |
|
104 for iectype in indexes: |
|
105 c_type, unpack_func, _pack_func = \ |
|
106 TypeTranslator.get(iectype, (None, None, None)) |
|
107 if c_type is not None and buffoffset < buffsize: |
|
108 cursor = c_void_p(buffptr + buffoffset) |
|
109 value = unpack_func(cast(cursor, |
|
110 POINTER(c_type)).contents) |
|
111 buffoffset += sizeof(c_type) if iectype != "STRING" else len(value)+1 |
|
112 res.append(value) |
|
113 else: |
|
114 break |
|
115 if buffoffset and buffoffset == buffsize: |
|
116 return res |
|
117 return None |
|
118 |
|
119 |
|
120 LogLevels = ["CRITICAL", "WARNING", "INFO", "DEBUG"] |
|
121 LogLevelsCount = len(LogLevels) |
|
122 LogLevelsDict = dict(zip(LogLevels, range(LogLevelsCount))) |
|
123 LogLevelsDefault = LogLevelsDict["DEBUG"] |
|