内容简介:基于3G模块的树莓派基站定位
具体的AT命令请查阅相关手册,绝大多数命令是通用的,部分命令会随着生产厂家有所差异,这里列举有关基站定位的几个AT命令
#测试有无SIM Q: AT+CPIN? A: +CPIN:READY #信号强度 AT+CSQ +CSQ: 16,99 #运营商信息 AT+COPS? +COPS: 0,2,"46001" #基站信息 AT+CREG=2 AT+CREG? +CREG: 2,1,"AAAA","BBBBBB"
串口编程
c
首先对上面的AT命令进行测试,观察返回的信息, win
平台上有串口调试助手可以使用, linux
下也有 minicom
,或者像我一样直接上 C
语言测试串口收发
#include <stdio.h> #include <errno.h> #include <sys/stat.h> #include <fcntl.h> #include <termios.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> int set_opt( int fd, int nSpeed, int nBits, char nEvent, int nStop ); int main( int argc, char **argv ) { if ( argc != 3 ) { printf( "Usage: ttytest device cmd\n" ); exit( 0 ); } int fd; char * cmgf = argv[2]; strcat( cmgf, "\r" ); char reply[128]; fd = open( argv[1], O_RDWR | O_NOCTTY | O_NDELAY ); if ( fd < 0 ) { perror( "Can't Open Serial Port" ); return(-1); } /* 配置串口 */ set_opt( fd, 115200, 8, 'N', 1 ); write( fd, cmgf, strlen( cmgf ) ); printf( "write %s\n", cmgf ); sleep( 2 ); memset( reply, 0, sizeof(reply) ); read( fd, reply, sizeof(reply) ); printf( "reply :\n" ); printf( "%s\n", reply ); } int set_opt( int fd, int nSpeed, int nBits, char nEvent, int nStop ) { struct termios newttys1, oldttys1; if ( tcgetattr( fd, &oldttys1 ) != 0 ) /* 保存原先串口配置 */ { perror( "Setupserial 1" ); return(-1); } bzero( &newttys1, sizeof(newttys1) ); /* 将一段内存区域的内容全清为零 */ newttys1.c_cflag |= (CLOCAL | CREAD); /* CREAD 开启串行数据接收,CLOCAL并打开本地连接模式 */ newttys1.c_cflag &= ~CSIZE; /* 设置数据位数 */ switch ( nBits ) /*选择数据位 */ { case 7: newttys1.c_cflag |= CS7; break; case 8: newttys1.c_cflag |= CS8; break; } switch ( nEvent ) /* 设置校验位 */ { case '0': /* 奇校验 */ newttys1.c_cflag |= PARENB; /* 开启奇偶校验 */ newttys1.c_iflag |= (INPCK | ISTRIP); /* INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特 */ newttys1.c_cflag |= PARODD; /* 启用奇校验(默认为偶校验) */ break; case 'E': /* 偶校验 */ newttys1.c_cflag |= PARENB; /* 开启奇偶校验 */ newttys1.c_iflag |= (INPCK | ISTRIP); /* 打开输入奇偶校验并去除字符第八个比特 */ newttys1.c_cflag &= ~PARODD; /* 启用偶校验; */ break; case 'N': /* 关闭奇偶校验 */ newttys1.c_cflag &= ~PARENB; break; } switch ( nSpeed ) /* 设置波特率 */ { case 2400: cfsetispeed( &newttys1, B2400 ); /* 设置输入速度 */ cfsetospeed( &newttys1, B2400 ); /* 设置输出速度 */ break; case 4800: cfsetispeed( &newttys1, B4800 ); cfsetospeed( &newttys1, B4800 ); break; case 9600: cfsetispeed( &newttys1, B9600 ); cfsetospeed( &newttys1, B9600 ); break; case 115200: cfsetispeed( &newttys1, B115200 ); cfsetospeed( &newttys1, B115200 ); break; default: cfsetispeed( &newttys1, B9600 ); cfsetospeed( &newttys1, B9600 ); break; } if ( nStop == 1 ) /* 设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB。 */ { newttys1.c_cflag &= ~CSTOPB; /* 默认为送一位停止位; */ }else if ( nStop == 2 ) { newttys1.c_cflag |= CSTOPB; /* CSTOPB表示送两位停止位; */ } /* 设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时 */ newttys1.c_cc[VTIME] = 0; /* 非规范模式读取时的超时时间; */ newttys1.c_cc[VMIN] = 0; /* 非规范模式读取时的最小字符数; */ tcflush( fd, TCIFLUSH ); /* tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */ /* 在完成配置后,需要激活配置使其生效 */ if ( (tcsetattr( fd, TCSANOW, &newttys1 ) ) != 0 ) /* TCSANOW不等数据传输完毕就立即改变属性 */ { perror( "com set error" ); return(-1); } return(0); }
编译
gcc ttytest.c -o ttytest
使用方法就是 ttytest device cmd
python
安装 Python
的串口支持模块
sudo pip install pyserial -i https://pypi.douban.com/simple/
一个简单的串口程序框架
import serial cmd="AT\r" ser=serial.Serial('/dev/ttyUSB1',115200) ser.write(cmd) print ser.readline()
获取 AT
返回信息的代码,为了避免串口长时间等待加了超时处理
#coding=utf-8 import serial import signal import time ser=serial.Serial('/dev/ttyUSB3',115200) # Define signal handler function def myHandler(signum, frame): print("Recieve timeout!") exit() def time_out(fun): def wrapper(*argv): signal.signal(signal.SIGALRM, myHandler) signal.alarm(5) return fun(*argv) return wrapper @time_out def getRes(cmd): #保存OK之前的所有接收信息 res='' #保存每一行的信息 line='' #发出AT信息 ser.write(cmd) #死循环 while True: #读取每一个返回的字符 for c in ser.read(): #添加字符到res和line res+=c line+=c #到达行末 if c == '\n': #打印输出 便于调试 #print("Line: " + line) #每一行如果匹配到 OK 或ERROR 则结束循环返回res if not ((line.find("OK")) == -1): return res line = '' # test start req="AT+CREG?" res=getRes(req+"\r") print "req is "+req+"\nres is:"+res req="AT+CSQ" res=getRes(req+"\r") print "req is "+req+"\nres is:"+res # test end
测试结果
可以看到返回的一行如果以 +CREG
开头则包含运营商基站信息,其中 AAAA
格式的为 lac
, BBBBBB
格式的为 CID
,均为十六进制,我们要提取并转化为十进制
str=''' +CREG: 2,1,AAAA,BBBBBB OK ''' lac=int((str.replace("\n","").replace("\r","").split(',')[2]),16) cid=int((str.replace("\n","").replace("\r","").split(',')[3][:-2]),16) print lac print cid
获取API
基站信息获取基站位置
基站定位接口介绍以及API文档 传送门
params={ "mmc":"460", "mnc":"01", "lac":"", "ci":"", "output":"json", }
返回范例:
{ "errcode": 0, "lat": "30.495039", "lon": "114.392479", "radius": "403", "address": "湖北省武汉市洪山区关山街道当代曙光嘉园2号楼-1单元;民族大道与南湖北路路口东南166米" }
编写脚本从串口拿到的 lac
和 cid
获取基站的经纬度以及其他信息
def getStationLocation(longtitude, latitude): getURL="http://api.cellocation.com/cell/" params={ "mmc":"460", "mnc":"01", "lac":"", "ci":"", "output":"json", } try: rep=urllib.urlopen(getURL,urllib.urlencode(params)) repdict=eval(rep.read()) except Exception, e: print 'str(Exception):\t', str(Exception) print 'str(e):\t\t', str(e) return repdict
经纬度获取地名
上面拿到的只是基站的具体地理位置,我们仍然需要从基站的经纬度确定树莓派的大致位置
我们无法通过经纬度直观的知道自己在哪里,不过有提供好的 API
给我们调用,这里使用 腾讯地图 开放API,现阶段对开发者是免费的。
注册过后拿到开发密钥XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
经纬度信息转为详细地理位置的API使用文档 传送门
返回的格式如下
{ "status": 0, "message": "query ok", "request_id": "6269494254796579061", "result": { "location": { "lat": 30.494491, "lng": 114.399033 }, "address": "湖北省武汉市洪山区民族大道163号桃园路", "formatted_addresses": { "recommend": "洪山区桃园路关山荷兰风情园", "rough": "洪山区桃园路关山荷兰风情园" }, ... }
脚本调用API获取地理位置
def getRPILocation(longtitude, latitude): getURL="http://apis.map.qq.com/ws/geocoder/v1/" params={ "location":longtitude+","+latitude, "output":"json", "key":"XXXXX-XXXXX-XXXXX-XXXXX-XXXXX", } try: rep=urllib.urlopen(getURL,urllib.urlencode(params)) repdict=eval(rep.read()) except Exception, e: print 'str(Exception):\t', str(Exception) print 'str(e):\t\t', str(e) return repdict
剩下的工作就是对拿到的 json
数据进行解析提取,比较简单就不做说明
以上所述就是小编给大家介绍的《基于3G模块的树莓派基站定位》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- SeaGlass:手工搭建伪基站监控系统
- 技术讨论 | 基于基站定位APP开发实录
- 建一个 5G 基站,到底要花多少钱?
- Eero分布式组网路由器推2代产品 包括基站和Beacon
- [树莓派]树莓派的入门教程
- 「玩转树莓派」树莓派 3B+ 安装 OpenCv
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。