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