gps::ks-102设备协议接入代码

gps::ks-102设备协议接入代码
  1  #  -- coding:utf-8 --
  2  # TK102 解码器定义
  3  # 这个设备没有包头包尾格式定义,假定一次读取一个完整数据包
  4 
  5  # from aobject import *
  6  import  os,os.path,sys,time,datetime,copy,struct,array,traceback
  7  # import codec
  8 
  9  # MediaCodecType = MediaDataType
 10  class  MediaDataType:    
 11      GPS    =   1 << 0
 12      AUDIO  =   1 << 1
 13      VIDEO  =   1 << 2
 14      IMAGE  =   1 << 3
 15      TEXT  =    1 << 4
 16      IODATA  =   1 << 5
 17      RAWBLOB  =   1 << 6     
 18      COMMAND  =   1 << 7      # 通用命令
 19      ALARM  =    1 << 8    # 报警信息
 20      UNDEFINED  =   0xff
 21      
 22 
 23  AOCTRL_CMD_SHAKE_ACK  = 1       # 应答握手信号信息
 24  AOCTRL_CMD_REG_ACK =   2      # 终端注册响应消息
 25  AOCTRL_CMD_SAMPLING_TIMESET  =   3       # 等时连续回传设置
 26  AOCTRL_CMD_ALARM_ACK  =   4      # 应答报警消息
 27  AOCTRL_CMD_NAMED  =   5       # 一次点名消息
 28  AOCTRL_CMD_SPEEDSET  =   6   # 设置车速上下限
 29  AOCTRL_CMD_POWER_ONOFF  =   7   # 电路控制信号
 30  AOCTRL_CMD_OIL_ONOFF  =   8    # 油路控制信号
 31  AOCTRL_CMD_REBOOT  =   9           # 控制设备重启消息
 32  AOCTRL_CMD_ACC_ON_TIME  =   10   # 设置ACC开发送数据间隔
 33  AOCTRL_CMD_ACC_OFF_TIME  =   11   # 设置ACC关发送数据间隔
 34  AOCTRL_CMD_BARRIER_SET  =   12       # 设置电子围栏消息
 35  AOCTRL_CMD_GETLOCATION  =   13           # 应答获取终端所在位置消息
 36  AOCTRL_CMD_LISTEN_START  =   14           # 监听命令
 37  AOCTRL_CMD_COMMADDR_SET  =   15       # 设置终端IP地址和端口
 38  AOCTRL_CMD_APN_SET  =   16              #  设置APN消息
 39  AOCTRL_CMD_GET_VERSION  =   17       #  读取终端版本消息
 40  AOCTRL_CMD_CLEAR_ALARMS  =   18       # 取消所有报警消息
 41  AOCTRL_CMD_CLEAR_MILES  =   19       # 里程清零消息
 42  AOCTRL_CMD_INIT_MILES  =   20           # 里程初始化消息
 43  AOCTRL_CMD_UPDATING  =   21           # 启动升级消息
 44 
 45  AOCTRL_CMD_SHACK_REQ  = 31   # 握手信号消息
 46  AOCTRL_CMD_REG_REQ  = 32       # 终端注册信息
 47  AOCTRL_CMD_SAMPLING_TIMESET_ACK  =   32   # 应答等时连续回传设置
 48  AOCTRL_CMD_ALARM_REQ  =   33           # 警报消息
 49  AOCTRL_CMD_NAMED_ACK  =   34           # 应答点名信息
 50  AOCTRL_CMD_SIMPLING_GPSDATA  =   35           # 等时连续回传消息
 51  AOCTRL_CMD_SIMPLING_END  =   36       # 连续回传结束消息
 52  AOCTRL_CMD_SPEEDSET_ACK  =   37       # 应答设置车速上下限
 53  AOCTRL_CMD_POWERCTRL_ACK  =   38     # 应答电路控制
 54  AOCTRL_CMD_OILCTRL_ACK  =   39       # 应答油路控制
 55  AOCTRL_CMD_REBOOT_ACK  =   40           # 应答设备重启消息
 56  AOCTRL_CMD_ACCON_TIMESET_ACK  =   41   # 应答设置ACC开发送数据间隔
 57  AOCTRL_CMD_ACCOFF_TIMESET_ACK = 42   # 应答设置ACC关发送数据间隔
 58  AOCTRL_CMD_BARRIER_SET_ACK  =    43   # 应答设置电子围栏消息
 59  AOCTRL_CMD_GETLOCATION_ACK  =   44    # 获取终端所在位置消息
 60  AOCTRL_CMD_LISTEN_ACK  =   45           # 应答监听命令
 61  AOCTRL_CMD_COMMADDR_SET_ACK = 46      # 应答设置终端IP地址和端口
 62  AOCTRL_CMD_APN_SET_ACK = 47          # 应答设置APN消息
 63  AOCTRL_CMD_GETVERSION_ACK = 48      # 应答读取终端版本消息
 64  AOCTRL_CMD_CLEAR_ALARMS_ACK = 49      # 应答取消所有报警消息
 65  AOCTRL_CMD_CLEAR_MILES_ACK = 50       # 应答里程清零消息
 66  AOCTRL_CMD_UPDATING_ACK  =   61       # 应答启动升级消息
 67  AOCTRL_CMD_INIT_MILES_ACK  =   62      # 应答初始化里程消息    
 68 
 69  AOCTRL_CMD_LIST = {
 70      AOCTRL_CMD_SHAKE_ACK:u ' 应答握手信号信息 ' ,
 71      AOCTRL_CMD_REG_ACK:u ' 终端注册响应消息 ' ,
 72      AOCTRL_CMD_SAMPLING_TIMESET:u ' 等时连续回传设置 ' ,
 73      AOCTRL_CMD_ALARM_ACK:u ' 应答报警消息 ' ,
 74      AOCTRL_CMD_NAMED:u ' 一次点名消息 ' ,
 75      AOCTRL_CMD_SPEEDSET:u ' 设置车速上下限 ' ,
 76      
 77      AOCTRL_CMD_POWER_ONOFF:u ' 电路控制信号 ' ,
 78      AOCTRL_CMD_OIL_ONOFF:u ' 油路控制信号 ' ,
 79      AOCTRL_CMD_REBOOT:u ' 控制设备重启消息 ' ,
 80      AOCTRL_CMD_ACC_ON_TIME :u ' 设置ACC开发送数据间隔 ' ,
 81      AOCTRL_CMD_ACC_OFF_TIME :u ' 设置ACC关发送数据间隔 ' ,
 82      AOCTRL_CMD_BARRIER_SET :u ' 设置电子围栏消息 ' ,
 83      AOCTRL_CMD_GETLOCATION :u ' 应答获取终端所在位置消息 ' ,
 84      AOCTRL_CMD_LISTEN_START :u ' 监听命令 ' ,
 85      AOCTRL_CMD_COMMADDR_SET :u ' 设置终端IP地址和端口 ' ,
 86      AOCTRL_CMD_APN_SET :u ' 设置APN消息 ' ,
 87      AOCTRL_CMD_GET_VERSION :u ' 读取终端版本消息 ' ,
 88      AOCTRL_CMD_CLEAR_ALARMS :u ' 取消所有报警消息 ' ,
 89      AOCTRL_CMD_CLEAR_MILES :u ' 里程清零消息 ' ,
 90      AOCTRL_CMD_INIT_MILES :u ' 里程初始化消息 ' ,
 91      AOCTRL_CMD_UPDATING :u ' 启动升级消息 ' ,
 92      
 93      AOCTRL_CMD_SHACK_REQ :u ' 握手信号消息 ' ,
 94      AOCTRL_CMD_REG_REQ :u ' 终端注册信息 ' ,
 95      AOCTRL_CMD_SAMPLING_TIMESET_ACK :u ' 应答等时连续回传设置 ' ,
 96      AOCTRL_CMD_ALARM_REQ :u ' 警报消息 ' ,
 97      AOCTRL_CMD_NAMED_ACK :u ' 应答点名信息 ' ,
 98      AOCTRL_CMD_SIMPLING_GPSDATA :u ' 等时连续回传消息 ' ,
 99      AOCTRL_CMD_SIMPLING_END :u ' 连续回传结束消息 ' ,
100      AOCTRL_CMD_SPEEDSET_ACK :u ' 应答设置车速上下限 ' ,
101      AOCTRL_CMD_POWERCTRL_ACK :u ' 应答电路控制 ' ,
102      AOCTRL_CMD_OILCTRL_ACK :u ' 应答油路控制 ' ,
103      AOCTRL_CMD_REBOOT_ACK :u ' 应答设备重启消息 ' ,
104      AOCTRL_CMD_ACCON_TIMESET_ACK :u ' 应答设置ACC开发送数据间隔 ' ,
105      AOCTRL_CMD_ACCOFF_TIMESET_ACK:u ' 应答设置ACC关发送数据间隔 ' ,
106      AOCTRL_CMD_BARRIER_SET_ACK :u ' 应答设置电子围栏消息 ' ,
107      AOCTRL_CMD_GETLOCATION_ACK :u ' 获取终端所在位置消息 ' ,
108      AOCTRL_CMD_LISTEN_ACK :u ' 应答监听命令 ' ,
109      AOCTRL_CMD_COMMADDR_SET_ACK:u ' 应答设置终端IP地址和端口 ' ,
110      AOCTRL_CMD_APN_SET_ACK:u ' 应答设置APN消息 ' ,
111      AOCTRL_CMD_GETVERSION_ACK:u ' 应答读取终端版本消息 ' ,
112      AOCTRL_CMD_CLEAR_ALARMS_ACK:u ' 应答取消所有报警消息 ' ,
113      AOCTRL_CMD_CLEAR_MILES_ACK:u ' 应答里程清零消息 ' ,
114      AOCTRL_CMD_UPDATING_ACK :u ' 应答启动升级消息 ' ,
115      AOCTRL_CMD_INIT_MILES_ACK :u ' 应答初始化里程消息 ' ,    
116  }
117      
118      
119  ALARM_TYPELIST = {
120      0:u ' 车辆断电 ' ,
121       1 :u ' 电子围栏入界报警 ' ,
122       2 :u ' 车辆劫警(SOS求助) ' ,
123       3 :u ' 车辆防盗器警报 ' ,
124       4 :u ' 车辆低速报警 ' ,
125       5 :u ' 车辆超速报警 ' ,
126       6 :u ' 电子围栏出界报警 '
127  }
128 
129 
130  def  parseTime(dmy,hms):
131      d,mon,y  =  map(int, map(float,[dmy[: 2 ],dmy[ 2 : 4 ],dmy[ 4 :]]) )
132      h,min,s  =  map(int, map(float,[hms[: 2 ],hms[ 2 : 4 ],hms[ 4 :]]) )
133       print  d,mon,y,h,min,s
134       return  time.mktime(( 2000 + y,mon,d,h,min,s,0,0,0))
135 
136  def  parseDegree(v):
137      pp  =  v.split( ' . ' )
138      mm1  =  pp[0][ - 2 :]
139      mm2  =   ' 0 '
140       if  len(pp) > 1 :
141          mm2  =  pp[ 1 ]
142      dd  =  pp[0][: - 2 ]
143      mm  =  mm1  +   " . "   +  mm2
144      degree  =  float(dd) +  float(mm) / 60.0
145       return  degree
146 
147  # 1节等于每小时 1海里,也就是每小时行驶1.852千米(公里)
148  def  parseSpeed(s):
149      km  = 0
150      km  =  float(s) * 1.852
151       return  km
152 
153 
154  # 简单的模拟gps接收解码器
155  # gps接收程序解析之后连接本地的TcpService端口,并传送过来
156  # 只有简单的gps数据,模拟端口打开
157  class  MediaCodec_KS102:
158       def   __init__ (self):
159          self.buf  = ''
160          self.conn  =  None
161          self.errtimes = 0     # 解析出错次数达到指定数则断开连接
162      
163 
164      
165       #  parse - codec 必须实现
166       # 对于某些设备的请求消息,这里必须进行默认的应答
167       # 如果出现大量数据包的要发送回设备的情况,考虑建立队列,用工作线程
168       #  慢慢发送,因为parse还在socket接收线程中
169       def  parse(self,aom,d):
170           pass  
171 
172       def  crc_16_result(self,d):
173           # struct.unpack('I')
174           print  d
175          i = 0
176          j = 0
177          c = 0
178          treat  = 0
179          bcrc  =  0
180          crc  = 0
181          s  = array.array( ' B ' )
182          s.fromstring(d)
183           # print len(s)
184           for  i  in  range(len(s)):            
185              c  =  s[i]
186               for  j  in  range( 8 ):
187                  treat  =  c & 0x80
188                  c  =  (c << 1 ) & 0xff
189                  
190                  bcrc  =  ( crc  >> 8  ) & 0xff
191                  bcrc  =  bcrc & 0x80
192                   # print crc
193                  crc  =  (crc  <<   1 &   0xffff
194                   # print crc
195                   if  treat  !=  bcrc:
196                      crc  =  (crc ^ 0x1021 & 0xffff
197                       # print '..',crc            
198              
199           return  crc
200      
201       
202       def  decode(self,s,conn):            
203           # @return:     packets,retry        
204           # 解码出多个消息包,并返回是否
205           #  imei 视为设备唯一编号 mid
206          self.conn  =  conn        
207          msglist = []
208          retry  =  True
209           try :
210              p  =  s.find( ' , ' )
211              d  =  s[p + 1 : - 2 ]
212              crc  =  s[ - 2 :]
213              sum,  =  struct.unpack( ' H ' ,crc)            
214               if  self.crc_16_result(d)  !=  sum:
215                   print   ' crc error '
216                   return  (),True
217               # 13145826175,GPRMC,022011.000,A,2234.0200,N,11403.0754,E,0.00,189.47,040310,,,A*6F,F, battery,imei:354776030402512,114
218               print  d
219               # print d.split(',')[-1]
220               # tel,gprmc,hms,av,lat,ns,lon,ew,speed,angle,dmy,p1,p2,mode,FL,battery,imei,msglen, = d.split(',')
221              tel,gprmc,hms,av,lat,ns,lon,ew,speed,angle,dmy,p1,p2,mode,FL,imei,msglen,  =  d.split( ' , ' )
222              imei  =  imei.split( ' : ' )[ 1 ]            
223              angle  =  float(angle)
224              speed  =  float(speed) * 1.852   #  节到km转换
225              lon  =  parseDegree(lon)
226              lat  =  parseDegree(lat)
227              time  =  parseTime(dmy,hms) + 3600 * 8      # 时间加上GMT8
228              gps  =  {
229                   ' time ' :time,
230                   ' lon ' :lon,
231                   ' lat ' :lat,
232                   ' speed ' :speed,
233                   ' angle ' :angle
234              }
235              msg  =  {
236                   ' mid ' :imei,
237                   ' cmd ' :AOCTRL_CMD_SIMPLING_GPSDATA,
238                   ' gps ' :gps,                
239              }
240              msglist.append(msg)
241           except :
242              traceback.print_exc()
243              msglist = ()
244              retry  =  True
245              self.errtimes += 1
246               if  self.errtimes  >   4 # 解析错误次数过多,断开连接
247                   return  (),False
248           return  msglist,retry
249 
250 
251      
252       # 执行设备命令
253       def  command(self,aom,msg):
254           #  cmd - object (json decoded)
255           # @return:  返回命令控制消息
256          cmd  =  msg[ ' cmd ' ]
257          code = ''
258          params = ''
259           if   not  msg.has_key( ' seq ' ):
260              msg[ ' seq ' =   ' 0 ' * 12
261              
262           if  cmd  ==  AOCTRL_CMD_REG_ACK:  # 注册响应
263              code  =   " (%sAP05) " % (msg[ ' seq ' ])
264 
265           # save to ctrl log         
266          log  =  aom.gm.AO_CtrlLog()
267          log.ao  =  aom.ao.dbobj
268          log.cmd  =  cmd
269          log.time  =  datetime.datetime.now()
270          text  =   " %s: %s " % (AOCTRL_CMD_LIST[log.cmd],params)
271          log.comment  =  text[: 200 ]
272          log.save()
273          
274           return  code
275      
276       # 将d数据写入db中
277       #  根据不同的数据进行hash分派 目前之后gps和告警信息进行分派
278       def  save(self,aom,d):        
279           # log = aom.gm.AO_CtrlLog()
280           # log.ao = aom.ao.dbobj
281           # log.cmd = d['cmd']
282           # log.time = datetime.datetime.now()
283           # text = "%s: %s"%(AOCTRL_CMD_LIST[log.cmd],d['params'])
284           # log.comment = text[:200]
285           # log.save()
286           # 以下存储gps数据和设备状态数据        
287           if  True:
288               #  save to db
289              timestamp  =  gps[ ' time ' ]
290              g  =  aom.gm.AOMData_Gps()
291              g.ao  =  aom.ao.dbobj
292              g.savetime  =  datetime.datetime.fromtimestamp(timestamp)
293              g.lon  =  gps[ ' lon ' ]
294              g.lat  =  gps[ ' lat ' ]
295              g.speed  =  gps[ ' speed ' ]
296              g.angle  =  gps[ ' angle ' ]
297              g.power  =  0
298              g.acc  =  0
299              g.miles  =  0
300              g.save()
301               # for dispatch
302              t  =  timestamp   # time.mktime(g.savetime.timetuple())
303              s  =  { ' type ' :MediaDataType.GPS, ' hwid ' :aom.id,
304                ' lon ' :g.lon, ' lat ' :g.lat,
305                ' speed ' :g.speed, ' angle ' :g.angle,
306                ' satenum ' :0, ' sateused ' :0,
307                ' time ' :t,
308                ' power ' :g.power,
309                ' acc ' :g.acc,
310                ' miles ' :g.miles}    
311              aom.dispatch(s)  # 分派到 cached server
312      
313      
314  '''
315  TK102方案GPRS通讯协议
316  上传数据
317  “1003040220,13145826175,GPRMC,022011.000,A,2234.0200,N,11403.0754,E,0.00,189.47,040310,,,A*6F,F, battery,imei:354776030402512,114迁”
318 
319  19个,分隔数据段
320 
321  数据解析
322  “1003040220”        
323  时间流水号:  2010年03月04日02时22分
324 
325  “13145826175”      
326  手机号码:授权情况下为授权号码,否则为最后操作tracker的手机号码,或则为空.
327  “GPRMC,022011.000,A,2234.0200,N,11403.0754,E,0.00,189.47,040310,,,A*
328  6F”    
329  GPRMC数据:GPS模块数据完整数据,单片机没有对其进行修改.
330      
331  “F”                当前GPS是否有信号:   F,表示有,L表示没有
332  “battery”          报警信息:【SOS报警:”help me”;电子砸烂报警:” Stockade”;移位报警:” move”;超速报警;” speed”;低电报警;” bat:”】,非报警数据此位置为空.
333  “imei:354776030402512”   GPRS 模块IMEI号
334  “114”                                     数据长度【13145826175,GPRMC,022011.000,A,2234.0200,N,11403.0754,E,0.00,189.47,040310,,,A*6F,F, battery,imei:354776030402512,】,括号内部的数据的长度,单位字节.
335  “迁”                CRC检验:这是两个字节的十六进制数据,有时显示为乱码,又是显示为空,因为他是十六进制。
336                                                                                计算范围【13145826175,GPRMC,022011.000,A,2234.0200,N,11403.0754,E,0.00,189.47,040310,,,A*6F,F, battery,imei:354776030402512,114】
337                                    算法如下:
338  注意:此系统unsigned int  为16bits,对于PC软件,需要对结果做 &0XFFFF运算。
339  unsigned int CRC_16(unsigned char *buf, unsigned int datalen)
340  {
341      unsigned int i;
342      unsigned char j;
343      unsigned char c, treat, bcrc;
344      unsigned int crc = 0;
345 
346      for (i = 0; i < datalen; i++)
347      {
348          c = buf[i];
349          for (j = 0; j < 8; j++)
350          {
351              treat = c & 0x80;
352              c <<= 1;
353              bcrc = (crc >> 8);
354              bcrc &= 0x80;
355              crc <<= 1;
356              if (treat != bcrc)
357                  crc ^= 0x1021;
358          }
359      }
360      return crc;
361  }
362 
363  附:GPS模块数据解释说明:
364 
365    $GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh 
366    <1> UTC时间,hhmmss.sss(时分秒.毫秒)格式 
367    <2> 定位状态,A=有效定位,V=无效定位 
368    <3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输) 
369    <4> 纬度半球N(北半球)或S(南半球) 
370    <5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输) 
371    <6> 经度半球E(东经)或W(西经) 
372    <7> 地面速率(000.0~999.9节,前面的0也将被传输) 
373    <8> 地面航向(000.0~359.9度,以正北为参考基准,前面的0也将被传输) 
374    <9> UTC日期,ddmmyy(日月年)格式 
375    <10> 磁偏角(000.0~180.0度,前面的0也将被传输) 
376    <11> 磁偏角方向,E(东)或W(西) 
377    <12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
378 
379  '''
380  =  MediaCodec_KS102()
381  d = " 1106160039,13916624477,GPRMC,163905.000,A,3104.2062,N,12130.0542,E,0.33,347.69,150611,,,D*6C,F,imei:354779033883985,105 "
382  d = " 13916624477,GPRMC,163905.000,A,3104.2062,N,12130.0542,E,0.33,347.69,150611,,,D*6C,F,imei:354779033883985,105 "
383  # print len(d)
384  # a = c.crc_16_result(d)
385  log  =  open( ' ks102_data.txt ' , ' rb ' )
386  =  log.read()
387  print  c.decode(s,None)
388 
389 

你可能感兴趣的:(gps::ks-102设备协议接入代码)