基于3G模块的树莓派基站定位

栏目: 服务器 · 发布时间: 6年前

内容简介:基于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

基于3G模块的树莓派基站定位

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

测试结果

基于3G模块的树莓派基站定位

可以看到返回的一行如果以 +CREG 开头则包含运营商基站信息,其中 AAAA 格式的为 lacBBBBBB 格式的为 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

基于3G模块的树莓派基站定位

获取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米"
}

编写脚本从串口拿到的 laccid 获取基站的经纬度以及其他信息

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模块的树莓派基站定位》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

乔布斯离开了,马斯克来了

乔布斯离开了,马斯克来了

[日]竹内一正 / 干太阳 / 中信出版社 / 2015-11

在电动汽车的创新上,特斯拉抓住了一个群体的独特需求,外形很酷,不烧油,智能化控制。所有的颠覆式创新都不是敲锣打鼓来的,而是隐藏在一片噪声里,马斯克给我们带来的特斯拉虽然不尽完美,但他做产品的思维和执着于未来的勇气,值得学习。埃隆•马斯克创办公司也不是为了赚钱,而是为了拯救人类和地球,电动汽车、太阳能发电、宇宙火箭,不管是哪一项都足以令一个国家付出巨大的代价去研究开发,但埃隆•马斯克却一个人在做这些......一起来看看 《乔布斯离开了,马斯克来了》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换