comparison __init__.py @ 0:c978dbb7e4b8

Commit first version of plugin to parse events from MaxStream ZigBee modules. At the moment it is not very configurable and only listens for evens from remote modules set up to send IO events.
author darius@inchoate.localdomain
date Sun, 28 Oct 2007 11:08:38 +1030
parents
children 1e65aca0f39c
comparison
equal deleted inserted replaced
-1:000000000000 0:c978dbb7e4b8
1 import eg
2
3 class PluginInfo(eg.PluginInfo):
4 name = "ZigBee"
5 author = "Darius"
6 version = "1.0.0"
7 description = "Listen for data from a Max Stream ZigBee module"
8
9
10
11 class Text:
12 port = "Port:"
13 baudrate = "Baudrate:"
14 bytesize = "Number of bits:"
15 parity = "Parity:"
16 parities = ['No parity', 'Odd', 'Even'] #, 'Mark', 'Space']
17 stopbits = "Stopbits:"
18 flowcontrol = "Flow control:"
19 handshakes = ['None', 'Xon / Xoff', 'Hardware']
20 generateEvents = "Generate events on incoming data"
21 eventPrefix = "Event prefix:"
22
23
24 import wx
25 import threading
26 import win32event
27 import win32file
28 import struct
29
30 class Serial(eg.RawReceiverPlugin):
31 canMultiLoad = True
32 text = Text
33
34 def __init__(self):
35 eg.RawReceiverPlugin.__init__(self)
36 self.serial = None
37 self.buffer = []
38 self.state = 'init'
39
40 def __start__(
41 self,
42 port,
43 baudrate,
44 bytesize=8,
45 parity=0,
46 stopbits=0,
47 handshake=0,
48 generateEvents=False,
49 prefix="Serial",
50 ):
51 xonxoff = 0
52 rtscts = 0
53 if handshake == 1:
54 xonxoff = 1
55 elif handshake == 2:
56 rtscts = 1
57
58 try:
59 self.serial = eg.SerialPort(
60 port,
61 baudrate=baudrate,
62 bytesize=(5, 6, 7, 8)[bytesize],
63 stopbits=(1, 2)[stopbits],
64 parity=('N', 'O', 'E')[parity],
65 xonxoff=xonxoff,
66 rtscts=rtscts,
67 )
68 except:
69 self.serial = None
70 raise eg.Exception("Can't open COM port.")
71 self.serial.timeout = 1.0
72 self.serial.setRTS()
73 self.info.eventPrefix = prefix
74 self.stopEvent = win32event.CreateEvent(None, 1, 0, None)
75 self.receiveThread = threading.Thread(target=self.ReceiveThread)
76 self.receiveThread.start()
77
78 def __stop__(self):
79 if self.serial is not None:
80 if self.receiveThread:
81 win32event.SetEvent(self.stopEvent)
82 self.receiveThread.join(1.0)
83 self.serial.close()
84 self.serial = None
85
86
87 def HandleChar(self, ch):
88 if (self.state == 'init'):
89 if (ch != '\x7e'):
90 return
91
92 self.state = 'sizemsb'
93 return
94
95 elif (self.state == 'sizemsb'):
96 self.bufszmsb = struct.unpack('B', ch)[0]
97 self.state = 'sizelsb'
98 return
99
100 elif (self.state == 'sizelsb'):
101 self.bufszlsb = struct.unpack('B', ch)[0]
102 self.dataleft = self.bufszmsb << 8 | self.bufszlsb
103
104 self.state = 'data'
105 return
106
107 elif (self.state == 'data'):
108 self.buffer.append(struct.unpack('B', ch)[0])
109 self.dataleft = self.dataleft - 1
110 if (self.dataleft == 0):
111 self.state = 'cksum'
112 return
113
114 elif (self.state == 'cksum'):
115 cksum = reduce(lambda x, y: x + y, self.buffer) & 0xff
116 rxcksum = struct.unpack('B', ch)[0]
117 if (cksum + rxcksum != 0xff):
118 self.PrintError("Bad checksum, got 0x%02x, expected 0x%02x" %
119 cksum, 0xff - cksum)
120 else:
121 self.PrintError("Triggered event: " + str(self.buffer))
122 self.TriggerEvent(str(self.buffer))
123 self.buffer = []
124 self.state = 'init'
125 return
126 else:
127 self.PrintError("Internal error: bad state: " + str(self.state))
128 self.state = 'init'
129
130 def ReceiveThread(self):
131 from win32event import (
132 ResetEvent,
133 MsgWaitForMultipleObjects,
134 QS_ALLINPUT,
135 WAIT_OBJECT_0,
136 WAIT_TIMEOUT,
137 )
138 from win32file import ReadFile, AllocateReadBuffer, GetOverlappedResult
139 from win32api import GetLastError
140
141 continueLoop = True
142 overlapped = self.serial._overlappedRead
143 hComPort = self.serial.hComPort
144 hEvent = overlapped.hEvent
145 stopEvent = self.stopEvent
146 n = 1
147 waitingOnRead = False
148 buf = AllocateReadBuffer(n)
149 while continueLoop:
150 if not waitingOnRead:
151 ResetEvent(hEvent)
152 hr, _ = ReadFile(hComPort, buf, overlapped)
153 if hr == 997:
154 waitingOnRead = True
155 elif hr == 0:
156 pass
157 #n = GetOverlappedResult(hComPort, overlapped, 1)
158 #self.HandleChar(str(buf))
159 else:
160 self.PrintError("error")
161 raise
162
163 rc = MsgWaitForMultipleObjects(
164 (hEvent, stopEvent),
165 0,
166 1000,
167 QS_ALLINPUT
168 )
169 if rc == WAIT_OBJECT_0:
170 n = GetOverlappedResult(hComPort, overlapped, 1)
171 if n:
172 self.HandleChar(str(buf))
173 #else:
174 # print "WAIT_OBJECT_0", n, str(buf[:n])
175 waitingOnRead = False
176 elif rc == WAIT_OBJECT_0+1:
177 continueLoop = False
178 elif rc == WAIT_TIMEOUT:
179 pass
180 else:
181 self.PrintError("unknown message")
182
183
184 def Configure(
185 self,
186 port=0,
187 baudrate=9600,
188 bytesize=8,
189 parity=0,
190 stopbits=0,
191 handshake=0,
192 generateEvents=False,
193 prefix="Serial",
194 ):
195 text = self.text
196 dialog = eg.ConfigurationDialog(self)
197 portCtrl = eg.SerialPortChoice(dialog, value=port)
198
199 baudrateCtrl = wx.ComboBox(
200 dialog,
201 value=str(baudrate),
202 choices=[
203 '110', '300', '600', '1200', '2400', '4800', '9600',
204 '14400', '19200', '38400', '57600', '115200',
205 '128000', '256000'
206 ],
207 style=wx.CB_DROPDOWN,
208 validator=eg.DigitOnlyValidator()
209 )
210
211 bytesizeCtrl = wx.Choice(dialog, choices=['5', '6', '7', '8'])
212 bytesizeCtrl.SetSelection(8 - 5)
213
214 parityCtrl = wx.Choice(dialog, choices=text.parities)
215 parityCtrl.SetSelection(parity)
216
217 stopbitsCtrl = wx.Choice(dialog, choices=['1', '2'])
218 stopbitsCtrl.SetSelection(stopbits)
219
220 handshakeCtrl = wx.Choice(dialog, choices=text.handshakes)
221 handshakeCtrl.SetSelection(handshake)
222
223 generateEventsCtrl = wx.CheckBox(dialog, label=text.generateEvents)
224 generateEventsCtrl.SetValue(generateEvents)
225
226 prefixCtrl = wx.TextCtrl(dialog)
227 prefixCtrl.SetValue(prefix)
228 prefixCtrl.Enable(generateEvents)
229
230 def OnCheckBox(event):
231 flag = generateEventsCtrl.GetValue()
232 prefixCtrl.Enable(flag)
233 generateEventsCtrl.Bind(wx.EVT_CHECKBOX, OnCheckBox)
234
235 flags = wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL
236 mySizer = wx.GridBagSizer(5, 5)
237 Add = mySizer.Add
238 Add(wx.StaticText(dialog, -1, text.port), (0, 0), flag=flags)
239 Add(portCtrl, (0, 1), flag=wx.EXPAND)
240 Add(wx.StaticText(dialog, -1, text.baudrate), (1, 0), flag=flags)
241 Add(baudrateCtrl, (1, 1), flag=wx.EXPAND)
242 Add(wx.StaticText(dialog, -1, text.bytesize), (2, 0), flag=flags)
243 Add(bytesizeCtrl, (2, 1), flag=wx.EXPAND)
244 Add(wx.StaticText(dialog, -1, text.parity), (3, 0), flag=flags)
245 Add(parityCtrl, (3, 1), flag=wx.EXPAND)
246 Add(wx.StaticText(dialog, -1, text.stopbits), (4, 0), flag=flags)
247 Add(stopbitsCtrl, (4, 1), flag=wx.EXPAND)
248 Add(wx.StaticText(dialog, -1, text.flowcontrol), (5, 0), flag=flags)
249 Add(handshakeCtrl, (5, 1), flag=wx.EXPAND)
250
251 Add((5, 5), (6, 0), (1, 2), flag=flags)
252 Add(generateEventsCtrl, (7, 0), (1, 2), flag=flags)
253 Add(wx.StaticText(dialog, -1, text.eventPrefix), (9, 0), flag=flags)
254 Add(prefixCtrl, (9, 1), flag=wx.EXPAND)
255 dialog.sizer.Add(mySizer)
256
257 if dialog.AffirmedShowModal():
258 return (
259 portCtrl.GetValue(),
260 int(baudrateCtrl.GetValue()),
261 bytesizeCtrl.GetSelection(),
262 parityCtrl.GetSelection(),
263 stopbitsCtrl.GetSelection(),
264 handshakeCtrl.GetSelection(),
265 generateEventsCtrl.GetValue(),
266 prefixCtrl.GetValue(),
267 )
268
269
270
271