1 # -- coding:utf-8 --
2 #解碼器定義
3
4 #from aobject import *
5 import os,os.path,sys,time,datetime,copy
6 #import codec
7
8 #MediaCodecType = MediaDataType
9 class MediaDataType:
10 GPS = 1<<0
11 AUDIO = 1<<1
12 VIDEO = 1<<2
13 IMAGE = 1<<3
14 TEXT = 1<<4
15 IODATA = 1<<5
16 RAWBLOB = 1<<6
17 COMMAND = 1<<7 #通用命令
18 ALARM = 1<<8 #報警信息
19 UNDEFINED = 0xff
20
21
22 AOCTRL_CMD_SHAKE_ACK =1 #應答握手信號信息
23 AOCTRL_CMD_REG_ACK= 2 #終端注冊響應消息
24 AOCTRL_CMD_SAMPLING_TIMESET = 3 #等時連續回傳設置
25 AOCTRL_CMD_ALARM_ACK = 4 #應答報警消息
26 AOCTRL_CMD_NAMED = 5 #一次點名消息
27 AOCTRL_CMD_SPEEDSET = 6 #設置車速上下限
28 AOCTRL_CMD_POWER_ONOFF = 7 #電路控制信號
29 AOCTRL_CMD_OIL_ONOFF = 8 #油路控制信號
30 AOCTRL_CMD_REBOOT = 9 #控制設備重啟消息
31 AOCTRL_CMD_ACC_ON_TIME = 10 #設置ACC開發送數據間隔
32 AOCTRL_CMD_ACC_OFF_TIME = 11 #設置ACC關發送數據間隔
33 AOCTRL_CMD_BARRIER_SET = 12 #設置電子圍欄消息
34 AOCTRL_CMD_GETLOCATION = 13 #應答獲取終端所在位置消息
35 AOCTRL_CMD_LISTEN_START = 14 #監聽命令
36 AOCTRL_CMD_COMMADDR_SET = 15 #設置終端IP地址和端口
37 AOCTRL_CMD_APN_SET = 16 # 設置APN消息
38 AOCTRL_CMD_GET_VERSION = 17 # 讀取終端版本消息
39 AOCTRL_CMD_CLEAR_ALARMS = 18 #取消所有報警消息
40 AOCTRL_CMD_CLEAR_MILES = 19 #里程清零消息
41 AOCTRL_CMD_INIT_MILES = 20 #里程初始化消息
42 AOCTRL_CMD_UPDATING = 21 #啟動升級消息
43
44 AOCTRL_CMD_SHACK_REQ =31 #握手信號消息
45 AOCTRL_CMD_REG_REQ =32 #終端注冊信息
46 AOCTRL_CMD_SAMPLING_TIMESET_ACK = 32 #應答等時連續回傳設置
47 AOCTRL_CMD_ALARM_REQ = 33 #警報消息
48 AOCTRL_CMD_NAMED_ACK = 34 #應答點名信息
49 AOCTRL_CMD_SIMPLING_GPSDATA = 35 #等時連續回傳消息
50 AOCTRL_CMD_SIMPLING_END = 36 #連續回傳結束消息
51 AOCTRL_CMD_SPEEDSET_ACK = 37 #應答設置車速上下限
52 AOCTRL_CMD_POWERCTRL_ACK = 38 #應答電路控制
53 AOCTRL_CMD_OILCTRL_ACK = 39 #應答油路控制
54 AOCTRL_CMD_REBOOT_ACK = 40 #應答設備重啟消息
55 AOCTRL_CMD_ACCON_TIMESET_ACK = 41 #應答設置ACC開發送數據間隔
56 AOCTRL_CMD_ACCOFF_TIMESET_ACK=42 #應答設置ACC關發送數據間隔
57 AOCTRL_CMD_BARRIER_SET_ACK = 43 #應答設置電子圍欄消息
58 AOCTRL_CMD_GETLOCATION_ACK = 44 #獲取終端所在位置消息
59 AOCTRL_CMD_LISTEN_ACK = 45 #應答監聽命令
60 AOCTRL_CMD_COMMADDR_SET_ACK=46 #應答設置終端IP地址和端口
61 AOCTRL_CMD_APN_SET_ACK=47 #應答設置APN消息
62 AOCTRL_CMD_GETVERSION_ACK=48 #應答讀取終端版本消息
63 AOCTRL_CMD_CLEAR_ALARMS_ACK=49 #應答取消所有報警消息
64 AOCTRL_CMD_CLEAR_MILES_ACK=50 #應答里程清零消息
65 AOCTRL_CMD_UPDATING_ACK = 61 #應答啟動升級消息
66 AOCTRL_CMD_INIT_MILES_ACK = 62 #應答初始化里程消息
67
68 AOCTRL_CMD_LIST={
69 AOCTRL_CMD_SHAKE_ACK:u'應答握手信號信息',
70 AOCTRL_CMD_REG_ACK:u'終端注冊響應消息',
71 AOCTRL_CMD_SAMPLING_TIMESET:u'等時連續回傳設置',
72 AOCTRL_CMD_ALARM_ACK:u'應答報警消息',
73 AOCTRL_CMD_NAMED:u'一次點名消息',
74 AOCTRL_CMD_SPEEDSET:u'設置車速上下限',
75
76 AOCTRL_CMD_POWER_ONOFF:u'電路控制信號',
77 AOCTRL_CMD_OIL_ONOFF:u'油路控制信號',
78 AOCTRL_CMD_REBOOT:u'控制設備重啟消息',
79 AOCTRL_CMD_ACC_ON_TIME :u'設置ACC開發送數據間隔',
80 AOCTRL_CMD_ACC_OFF_TIME :u'設置ACC關發送數據間隔',
81 AOCTRL_CMD_BARRIER_SET :u'設置電子圍欄消息',
82 AOCTRL_CMD_GETLOCATION :u'應答獲取終端所在位置消息',
83 AOCTRL_CMD_LISTEN_START :u'監聽命令',
84 AOCTRL_CMD_COMMADDR_SET :u'設置終端IP地址和端口',
85 AOCTRL_CMD_APN_SET :u'設置APN消息',
86 AOCTRL_CMD_GET_VERSION :u'讀取終端版本消息',
87 AOCTRL_CMD_CLEAR_ALARMS :u'取消所有報警消息',
88 AOCTRL_CMD_CLEAR_MILES :u'里程清零消息',
89 AOCTRL_CMD_INIT_MILES :u'里程初始化消息',
90 AOCTRL_CMD_UPDATING :u'啟動升級消息',
91
92 AOCTRL_CMD_SHACK_REQ :u'握手信號消息',
93 AOCTRL_CMD_REG_REQ :u'終端注冊信息',
94 AOCTRL_CMD_SAMPLING_TIMESET_ACK :u'應答等時連續回傳設置',
95 AOCTRL_CMD_ALARM_REQ :u'警報消息',
96 AOCTRL_CMD_NAMED_ACK :u'應答點名信息',
97 AOCTRL_CMD_SIMPLING_GPSDATA :u'等時連續回傳消息',
98 AOCTRL_CMD_SIMPLING_END :u'連續回傳結束消息',
99 AOCTRL_CMD_SPEEDSET_ACK :u'應答設置車速上下限',
100 AOCTRL_CMD_POWERCTRL_ACK :u'應答電路控制',
101 AOCTRL_CMD_OILCTRL_ACK :u'應答油路控制',
102 AOCTRL_CMD_REBOOT_ACK :u'應答設備重啟消息',
103 AOCTRL_CMD_ACCON_TIMESET_ACK :u'應答設置ACC開發送數據間隔',
104 AOCTRL_CMD_ACCOFF_TIMESET_ACK:u'應答設置ACC關發送數據間隔',
105 AOCTRL_CMD_BARRIER_SET_ACK :u'應答設置電子圍欄消息',
106 AOCTRL_CMD_GETLOCATION_ACK :u'獲取終端所在位置消息',
107 AOCTRL_CMD_LISTEN_ACK :u'應答監聽命令',
108 AOCTRL_CMD_COMMADDR_SET_ACK:u'應答設置終端IP地址和端口',
109 AOCTRL_CMD_APN_SET_ACK:u'應答設置APN消息',
110 AOCTRL_CMD_GETVERSION_ACK:u'應答讀取終端版本消息',
111 AOCTRL_CMD_CLEAR_ALARMS_ACK:u'應答取消所有報警消息',
112 AOCTRL_CMD_CLEAR_MILES_ACK:u'應答里程清零消息',
113 AOCTRL_CMD_UPDATING_ACK :u'應答啟動升級消息',
114 AOCTRL_CMD_INIT_MILES_ACK :u'應答初始化里程消息',
115 }
116
117
118 ALARM_TYPELIST={
119 0:u'車輛斷電',
120 1:u'電子圍欄入界報警',
121 2:u'車輛劫警(SOS求助)',
122 3:u'車輛防盜器警報',
123 4:u'車輛低速報警',
124 5:u'車輛超速報警',
125 6:u'電子圍欄出界報警'
126 }
127
128
129 #簡單的模擬gps接收解碼器
130 #gps接收程序解析之后連接本地的TcpService端口,并傳送過來
131 #只有簡單的gps數據,模擬端口打開
132 class MediaCodec_KS108:
133 def __init__(self):
134 self.buf =''
135 self.conn = None
136
137
138 def parse_gps(self,msg,s):
139 # gps 數據長度62個字符
140 msg['gps'] = None #AOCTRL_CMD_SIMPLING_GPSDATA
141 if len(s)!=62:
142 return
143 try:
144 yy = int(s[:2])
145 mm = int(s[2:4])
146 dd = int(s[4:6])
147 av = s[6] #是否有效
148 lat = int(s[7:9])+ float( s[9:16]) / 60.
149 ns = s[16] #維度標志 N/S
150 lon = int(s[17:20]) + float( s[20:27]) /60.
151 ew = s[27]
152 speed = float(s[28:33])
153 HH = int(s[33:35])
154 MM = int(s[35:37])
155 SS = int(s[37:39])
156 angle = float(s[39:45])
157 power = int(s[45])
158 acc = int(s[46])
159 mileflag = s[53]
160 miles = int(s[54:],16)
161 gpstime = datetime.datetime(yy,mm,dd,HH,MM,SS)
162 msg['gps'] = {
163 'time':gpstime,
164 'lon':lon,
165 'lat':lat,
166 'speed':speed,
167 'angle':angle,
168 'power':power,
169 'acc':acc,
170 'miles':miles
171 }
172 except:
173 traceback.print_exc()
174 msg['gps'] = None
175
176
177
178 def __parseMessage(self,s):
179 # @return: [object,] or [None,]
180 msg={'mid':self.conn.mid,'cmd':0,'seq':'','params':'','gps':None} # mid - 模塊硬件編號
181
182
183 cmd = s[12:16]
184 msg['msg'] = cmd
185 msg['seq'] = s[:12]
186
187 if cmd == 'BP00' and len(s) == 24:
188 msg['cmd'] = AOCTRL_CMD_SHACK_REQ
189 elif cmd =='BP05': #注冊信息
190 msg['cmd'] = AOCTRL_CMD_REG_REQ
191 msg['mid'] = s[16:31] #
192 self.conn.mid = msg['mid'] #設備連接上來這個是第一個消息包
193 #將gps獨立出單獨的包
194 self.parse_gps(msg,s[31:])
195 elif cmd =='BS08' and len(s) == 24:
196 msg['cmd'] = AOCTRL_CMD_SAMPLING_TIMESET_ACK #應答等時連續回傳設置
197 msg['samplewait'] = int(s[16:20],16)
198 hours = int(s[20:22],16)
199 minutes = int(s[22:24],16)
200 msg['samplecycle'] = hours*3600 + minutes * 60
201 msg['params'] = "samplewait:%s,samplecycle:%s"%(msg['samplewait'],msg['samplecycle'])
202
203 elif cmd == 'BO01':
204 msg['cmd'] = AOCTRL_CMD_ALARM_REQ #警報消息
205 msg['alarm'] = int(s[16]) #報警類型
206 msg['params'] = ALARM_TYPELIST[msg['alarm']]
207 self.parse_gps(msg,s[17:])
208 elif cmd =='BP04' : #點名應答
209 msg['cmd'] = AOCTRL_CMD_NAMED_ACK #應答點名信息
210 self.parse_gps(msg,s[16:])
211 elif cmd == 'BR00' :
212 msg['cmd'] = AOCTRL_CMD_SIMPLING_GPSDATA
213 self.parse_gps(msg,s[16:])
214 elif cmd == 'BR02' :
215 msg['cmd'] = AOCTRL_CMD_SIMPLING_END
216 self.parse_gps(msg,s[16:])
217 elif cmd == 'BP12' and len(s) == 24:
218 msg['cmd'] = AOCTRL_CMD_SPEEDSET_ACK
219 msg['hispeed'] = int(s[17:20])
220 msg['lospeed'] = int(s[21:24]) #低速限制
221 msg['params'] = "hispeed:%s,lospeed:%s"%( msg['hispeed'],msg['lospeed'] )
222
223 elif cmd == 'BV00' and len(s) == 17:
224 msg['cmd'] = AOCTRL_CMD_POWERCTRL_ACK ##應答電路控制
225 msg['onoff'] = int(len(s[17]))
226 if msg['onoff'] == 0:
227 msg['params'] = u'已關電路'
228 else:
229 msg['params'] = '已開電路'
230
231 elif cmd =='BV01' and len(s) == 17:#應答油路控制
232 msg['cmd'] = AOCTRL_CMD_OILCTRL_ACK
233 msg['onoff'] = int(len(s[17]))
234 if msg['onoff'] == 0:
235 msg['params'] = u'已關油路'
236 else:
237 msg['params'] = '已開油路'
238 elif cmd =='BT00':
239 msg['cmd'] = AOCTRL_CMD_REBOOT_ACK
240 elif cmd =='BR05':
241 msg['cmd'] = AOCTRL_CMD_ACCON_TIMESET_ACK #應答設置ACC開發送數據間隔
242 elif cmd =='BR06':
243 msg['cmd'] = AOCTRL_CMD_ACCOFF_TIMESET_ACK #應答設置ACC關發送數據間隔
244 elif cmd == 'BU00':
245 msg['cmd'] = AOCTRL_CMD_BARRIER_SET_ACK
246 elif cmd == 'BR03': #獲取終端所在位置消息
247 msg['cmd'] = AOCTRL_CMD_GETLOCATION_ACK
248 self.parse_gps(msg,s[16:])
249 elif cmd =='BS20' :
250 msg['cmd'] = AOCTRL_CMD_LISTEN_ACK #應答監聽命令
251 elif cmd =='BP02' and len(s) == 16:
252 msg['cmd'] = AOCTRL_CMD_COMMADDR_SET_ACK #應答設置終端IP地址和端口
253 elif cmd =='BP03':
254 msg['cmd'] = AOCTRL_CMD_APN_SET_ACK #應答設置APN消息
255 elif cmd == 'BP01':
256 msg['cmd'] = AOCTRL_CMD_GETVERSION_ACK
257 msg['version'] = s[16:]
258 elif cmd == 'BS21':
259 msg['cmd'] = AOCTRL_CMD_CLEAR_ALARMS_ACK #應答取消所有報警消息
260 elif cmd == 'BS04':
261 msg['cmd'] = AOCTRL_CMD_CLEAR_MILES_ACK #應答里程清零消息
262 elif cmd == 'BS05':
263 msg['cmd'] = AOCTRL_CMD_UPDATING_ACK #= 61 #應答啟動升級消息
264 elif cmd == 'BS06':
265 msg['cmd'] = AOCTRL_CMD_INIT_MILES_ACK #應答初始化里程消息
266 else:
267 msg = None
268
269 return msg
270
271 # parse - codec 必須實現
272 def parse(self,aom,d):
273 #對于某些設備的請求消息,這里必須進行默認的應答
274 cmd = d['cmd']
275 if cmd == AOCTRL_CMD_SHACK_REQ: #握手回復
276 self.command(aom,{'cmd':AOCTRL_CMD_SHAKE_ACK,'seq':d['seq']})
277 if cmd == AOCTRL_CMD_REG_REQ: #設備注冊
278 self.command(aom,{'cmd':AOCTRL_CMD_REG_ACK,'seq':d['seq']})
279 if cmd == AOCTRL_CMD_ALARM_REQ:
280 self.command(aom,{'cmd':AOCTRL_CMD_ALARM_ACK,'seq':d['seq'],'alarm':d['alarm']})
281
282 def decode(self,s,conn):
283 #@return: packets,retry
284 #解碼出多個消息包,并返回是否
285 self.conn = conn
286 msglist=[]
287 retry = True
288
289 self.buf+=s
290 while True:
291 p1 = self.buf.find('(')
292 if p1 == -1:
293 self.buf=''
294 break
295 self.buf = self.buf[p1:]
296
297 p2 = self.buf.find(')')
298 if p2 == -1:
299 if len(self.buf) > 1024:
300 return (),False # please break socket connection
301 break # push in more data
302 #find tail
303 msg = None
304 try:
305 msg = self.__parseMessage(self.buf[1:p2])
306 except:
307 traceback.print_exc()
308 msg = None
309 if msg:
310 msglist.append(m)
311 self.buf = self.buf[p2+1:]
312 return msglist,retry
313
314
315
316 #執行設備命令
317 def command(self,aom,msg):
318 # cmd - object (json decoded)
319 #@return: 返回命令控制消息
320 cmd = msg['cmd']
321 code=''
322 params=''
323 if not msg.has_key('seq'):
324 msg['seq'] = '0'*12
325
326 if cmd == AOCTRL_CMD_REG_ACK: #注冊響應
327 code = "(%sAP05)"%(msg['seq'])
328
329 elif cmd == AOCTRL_CMD_SAMPLING_TIMESET: #等時連續回傳設置
330 wait = msg['samplewait'] #時間間隔
331 cycle = msg['samplecycle'] #總時長
332 hh = int(cycle/3600)
333 mm = (cycle - hh*3600)/60
334 mm = int(mm)
335 code = "(%sAR00%04x%02x%02x)"%('0'*12,wait,hh,mm)
336 params = "wait:%s seconds, cycle: %s hours,%s mimuts"%(wait,hh,mm)
337 elif cmd == AOCTRL_CMD_ALARM_ACK: #應答報警消息
338 alarm = msg['alarm']
339 code = "(%sAS01%d)"%(msg['seq'],alarm)
340 params = ALARM_TYPELIST[alarm]
341 elif cmd == AOCTRL_CMD_NAMED : #一次點名消息
342 code = "(%sAP00)"%('0'*12)
343 elif cmd == AOCTRL_CMD_SPEEDSET: #設置車速上下限
344 hi = msg['hispeed']
345 lo = msg['lospeed']
346 code = "(%sAP12H%03dL%03d)"%('0'*12,hi,lo)
347 params = "hi:%s,lo:%s"%(hi,lo)
348 elif cmd == AOCTRL_CMD_POWER_ONOFF: #電路控制信號
349 onoff = msg['onoff']
350 code = "(%sAV00%d)"%('0'*12,onoff) #“1”表示開電路,“0”表示關電路
351 params = "onoff:%s"%(onoff)
352 elif cmd ==AOCTRL_CMD_OIL_ONOFF: #油路控制信號
353 onoff = msg['onoff']
354 code = "(%sAV01%d)"%('0'*12,onoff) #“1”表示開油路,“0”表示關油路
355 params = "onoff:%s"%(onoff)
356 elif cmd == AOCTRL_CMD_REBOOT: #控制設備重啟消息
357 code = "(%sAT00)"%('0'*12)
358 elif cmd == AOCTRL_CMD_ACC_ON_TIME: #設置ACC開發送數據間隔
359 interval = msg['interval']
360 code = "(%sAR05%04x)"%('0'*12,interval)
361 params = "interval:%s seconds"%(interval)
362 elif cmd == AOCTRL_CMD_ACC_OFF_TIME: #設置ACC關發送數據間隔
363 interval = msg['interval']
364 code = "(%sAR06%04x)"%('0'*12,interval)
365 params = "interval:%s seconds"%(interval)
366 elif cmd == AOCTRL_CMD_BARRIER_SET: #設置電子圍欄消息
367 pass
368 #code = "(%sAR06%04x)"%('0'*12,interval)
369 elif cmd ==AOCTRL_CMD_GETLOCATION : #應答獲取終端所在位置消息
370 pass
371 elif cmd == AOCTRL_CMD_LISTEN_START: #監聽命令
372 phone = msg['phone']
373 code = "(%sAP15%s)"%('0'*12,phone) #讓設備主動撥打電話
374 params = "phone:%s"%(phone)
375 elif cmd == AOCTRL_CMD_COMMADDR_SET: #設置終端IP地址和端口
376 p1,p2,p3,p4 = map(int,msg['ip'].strip().split('.'))
377 port = int(msg['port'])
378 code = "(%sAP03%03d%03d%03d%03d%05d)"%('0'*12,p1,p2,p3,p4,port)
379 params = "%s:%s"%(msg['ip'],msg['port'])
380 elif cmd == AOCTRL_CMD_APN_SET: #設置APN消息
381 apn = msg['apn']
382 code = "(%sAP04%s)"%('0'*12,apn)
383 params = "APN:%s"%(apn)
384 elif cmd == AOCTRL_CMD_GET_VERSION: #讀取終端版本消息
385 code = "(%sAP07)"%('0'*12)
386 elif cmd == AOCTRL_CMD_CLEAR_ALARMS: #取消所有報警消息
387 code = "(%sAV02)"%('0'*12)
388 elif cmd == AOCTRL_CMD_CLEAR_MILES: #里程清零消息
389 code = "(%sAX01)"%('0'*12)
390 elif cmd == AOCTRL_CMD_INIT_MILES: #里程初始化消息
391 miles = msg['miles']
392 code = "(%sAX03%08x)"%('0'*12,miles) #為初始化里程值,8位16進制的ASCII值,單位為米
393 params = "miles:%s"%(miles)
394 elif cmd == AOCTRL_CMD_UPDATING: #啟動升級消息
395 ip = msg['ip']
396 port = msg['port']
397 code = "(%sAX02%s:%s)"%('0'*12,ip,port)
398 params ="%s:%s"%(ip,port)
399 else:
400 return ''
401 #save to ctrl log
402 log = aom.gm.AO_CtrlLog()
403 log.ao = aom.ao.dbobj
404 log.cmd = cmd
405 log.time = datetime.datetime.now()
406 text = "%s: %s"%(AOCTRL_CMD_LIST[log.cmd],params)
407 log.comment = text[:200]
408 log.save()
409
410 return code
411
412 #將d數據寫入db中
413 # 根據不同的數據進行hash分派 目前之后gps和告警信息進行分派
414 def save(self,aom,d):
415 log = aom.gm.AO_CtrlLog()
416 log.ao = aom.ao.dbobj
417 log.cmd = d['cmd']
418 log.time = datetime.datetime.now()
419 text = "%s: %s"%(AOCTRL_CMD_LIST[log.cmd],d['params'])
420 log.comment = text[:200]
421 log.save()
422 #以下存儲gps數據和設備狀態數據
423 gps = d['gps']
424 if gps:
425 # save to db
426 g = aom.gm.AOMData_Gps()
427 g.ao = aom.ao.dbobj
428 g.savetime = gps['time']
429 g.lon = gps['lon']
430 g.lat = gps['lat']
431 g.speed = gps['speed']
432 g.angle = gps['angle']
433 g.power = gps['power']
434 g.acc = gps['acc']
435 g.miles = gps['miles']
436 g.save()
437 #for dispatch
438 t = time.mktime(g.savetime.timetuple())
439 s = {'type':MediaDataType.GPS,'hwid':aom.id,
440 'lon':g.lon,'lat':g.lat,
441 'speed':g.speed,'angle':g.angle,
442 'satenum':0,'sateused':0,
443 'time':t,
444 'power':g.power,
445 'acc':g.acc,
446 'miles':g.miles}
447 aom.dispatch(s) #分派到 cached server
448
449 if d['msg'] == 'BO01': #報警
450 alarm = aom.gm.AO_AlarmLog()
451 alarm.ao = aom.ao.dbobj
452 alarm.time = datetime.datetime.now()
453 alarm.type = d['alarm']
454 alarm.save()
455 #分派報警
456 t = time.mktime(alarm.time.timetuple())
457 s = {'type':MediaDataType.ALARM,
458 'alarm':alarm.type,
459 'comment':ALARM_TYPELIST[alarm.type]
460 }
461 aom.dispatch(s) #分派到 cached server
462
463