Skip to content

GNSS定位,GPRS上报Demo

简介

本文档主要介绍基于UC8088芯片下GPS/GPRS切换、实现定位后数据上报的例程。

软件设计模型

说明:在GPRS/GPS上通过manage模块进行二者的切换管理,app层实现应用程序。

应用接口

1、GPRS EAT接口函数(具体使用见文档 GPRS_EAT_API)

函数 描述
void eat_wait_ready(void); 等待进入EAT状态
void eat_rx_reset(void); 清空响应数据缓冲区
EAT_ERROR_CODE eat_send_cmd(n8_t *cmd); 发送AT命令
EAT_ERROR_CODE eat_wait_ok(void); 等待AT命令的回复
EAT_ERROR_CODE eat_recv_line(n8_t *line, u32_t size); 等待读取AT返回的1行数据
EAT_ERROR_CODE eat_wait_rsp(n8_t rsp, u32_t size, n8_t prompt, n8_t **ppara); 等待接收AT返回的特定数据
n8_t parse(n8_t b, n8_t *f, ...); 从字符串中解析提取数据

2、GPRS/GPS 模式切换接口函数

函数 描述
u32_t get_first_start_flag(void); 查看是否为第一次启动
MODE_TYPE get_current_mode(void); 查看当前的模式(GPS模式/中间态/GPRS模式)
u8_t gprs_gps_switch(MODE_TYPE mode); GPRS/GPS模式切换

实现步骤

1、设置GPS回调函数,初始化应用任务

#ifdef EAT_TEST
    app_startup(gps_pvt_callback); //启动GPRS并设置GPS回调函数
    eat_test_app();//启动例程应用任务
#else
    app_startup(NULL);
#endif
void eat_test_app(void)
{
    //创建例程应用任务,注意:优先级约定为1
    xTaskCreat(eat_test_platform, "eat_app", 512, NULL, 1, &gp_test_task_handle);
#ifdef MODE_SWITCH_DEMO6
    uart0_trx_init();
    xTaskCreat(command_parse_task, "command_parse", 256, NULL, 1, &gp_uart0_handle);
#endif
}
void eat_test_platfrom(void *pvParameters)
{
    vTaskDelay(pdMS_TO_TICKS(200));//等待其它任务率先执行
    eat_wait_ready();//等待EAT状态准备完成

    //查看系统当前剩余heap大小,及历史使用中最小剩余量
    TRACE_PRINTF("gps_demo[%d] HeapSize:%d,miniheap=%d\r\n",__LINE__,xPortGetFreeHeapSize(),xPortGetMinimumEverFreeHeapSize());

    //当并非选择demo MODE_SWITCH_DEMO6时,默认上传数据值
#ifndef MODE_SWITCH_DEMO6
    strcpy(gp_gps_data->latitude,"66.6");
    strcpy(gp_gps_data->longitude,"111.1");
    strcpy(gp_gps_switch->speed,"35.3");

    if(MODEM_MODE_GPRS != get_current_mode())
        gprs_gps_switch(MODEM_MODE_GPRS);
#endif

#ifdef TCP_DEMO1
    eat_tcp_long_connection_demo();//TCP应用
#elif HTTP_DEMO2
    while(1) gprs_http_test(gp_gps_data);//HTTP应用
#elif MQTT_DEMO3
    while(1) gprs_mqtt_test(gp_gps_data);//MQTT应用
#elif FTP_DEMO4
    while(1) gprs_ftp_test(gp_gps_data);//FTP应用
#elif SMS_DEMO5
    gprs_sms_test(gp_gps_data);//SMS应用
#elif MODE_SWITCH_DEMO6
    eat_gprs_gps_switch_demo(SMS_REPORT);//GPS定位后,切换到GPRS,使用SMS上报经纬度
#endif
}

2、切换到GPS模式,定位后获取经纬度数据

3、切换到GPRS模式,通过MQTT/HTTP/SMS等方式上传经纬度数据到物联网云平台或者手机端

#define GUARD_MEMORY_SECTION __attribute__(section(".guard"))
GUARD_MEMORY_SECTION REPORT_PARAMS_TYPE gv_gps_data;//注意:我们将经纬度、当前模式等信息指定放在".guard"段,避免切换重启数据丢失
REPORT_PARAMS_TYPE *gp_gps_data = &gv_gps_data;

static void eat_gprs_gps_switch_demo(REPORT_GPS_DATA_TYPE repoet_type)
{
    u8_t get_mode = 0xff;
    //当为第一次启动
    if(0 == get_first_start_flag())
    {
        //如果使用短信上报方式,则进入参数配置模式
        if(repoet_type == SMS_REPOET)
        {
            memset(&g_sms_config, 0, sizeof(SMS_CONFIG_TYPE))
            first_config_wait();
        }
        //设备支持GPS/GPRS双模,它通过静态数据写入设备
        if(DEV_DEFAULF_GPRS == get_dev_operation_mode())
        {
            //切换到GPS模式
            while(1 == gprs_gps_switch(MODEM_MODE_GPS)) EAT_PRINTF("switch fail\r\n");
        }
        else
        {
            while(1)
            {
                EAT_TRACE("dual mode is currently not supported, please change it!\r\n");
                vTaskDelay(pdMS_TO_TICKS(1000));
            }
        }
    }
    while(1)
    {
        get_mode = get_current_mode();//获取当前的模式
        switch(get_mode)
        {
            case MODEM_MODE_GPS:
                if(repoet_type == SMS_REPOET)
                      create_timer_func(g_sms_config.report_time);
                  else if(repoet_type == MQTT_REPOET)
                      create_timer_func(80);
                break;
            case MODEM_MODE_GPRS:
                  if(repoet_type == SMS_REPOET)
                      eat_sms_gps_demo(gp_gps_data);
                  else if(repoet_type == MQTT_REPOET)
                      gprs_mqtt_test(gp_gps_data);
                while(1 == gprs_gps_switch(MODEM_MODE_GPS));
                break;
            default:
                //当此时非GPS/GPRS,则处于中间状态,等待2s
                vTaskDelay(pdMS_TO_TICKS(2000));
                break;
        }
    }
}
//GPS 回调函数
void gps_pvt_callback(IN const PSTU_RTC pRtc, IN const PSTU_USR_PVT pPvt)
{
    const TYP_F32 g_tR2D = {57.2957802f, -6.68802443e-07f};
    //等待GPS定位成功
    if(pPvt->eState == PVT_STATE_OK)
    {
        tLla = pPvt->tLla;
        tEnu = pPvt->tEnu;
        tLla.tLon = MulExtF32(&tLla.tLon, (PTYP_F32)&g_tR2D);
        tLla.tLat = MulExtF32(&tLla.tLat, (PTYP_F32)&g_tR2D);
    }
}
//GPRS MQTT上报数据到阿里云实现
DEMO_RETURN_TYPE gprs_mqtt_test(REPORT_PARAMS_TYPE *p_gps_data)
{
    u8_t error_num = 0;
    while(error_num++ < 3)
    {
        if(DO_OK != dev_control(DEV_DISABLE)) //掉电
            continue;
        if(DO_OK != dev_control(DEV_ENABLE)) //上电、pdp激活
            continue;
        SEND_AT_OUT(AT_CMD_MQTTCONFIG,_mqtt_out) //配置MQTT
        if(DO_OK != gprs_mqtt_connect()) //MQTT连接
            goto _mqtt_out;
        if(DO_OK != gprs_mqtt_pub(p_gps_data)) //MQTT发布数据
            goto _mqtt_out;
        SEND_AT(AT_CMD_MQTTDISCONNECT) //MQTT断开连接
        break;
     _mqtt_out:
        SEND_AT(AT_CMD_MQTTDISCONNECT)
        continue;
    }
    if(3 == error_num)
        return DO_ERROR;
    return DO_OK;
}
//GPRS SMS上报数据到 目标电话号码 对应终端上
void eat_sms_gps_demo(REPORT_PARAMS_TYPE *gp_gps_data)
{
    #define checkMaxNum 6
    u8_t csState = 0;
    u8_t checkNum = checkMaxNum;
    u8_t send_error_num = 0;
    u8_t continue_cycle_num = 0;

    while((continue_cycle_num++) < CYCLE_ERROR_MAX)
    {
        vTaskDelay(pdMS_TO_TICKS(200));

        if(DO_OK != dev_control_cs(DEV_DISABLE)) //掉电失活
            continue;

        if(DO_OK != dev_control_cs(DEV_ENABLE)) //上电激活
            continue;   

        if(DO_OK != sms_general_config(TEXT_MODE)) //配置文本模式
            continue;

        if(DO_OK != sms_text_send_config(g_sms_config.smsc_addr)) //配置短消息中心地址
            continue;

        while(checkNum)
        {
            if(DO_OK != get_cs_state(&csState)) //查看CS域的附着情况
            {
                vTaskDelay(pdMS_TO_TICKS(2000)); //未附着上,则等待两秒继续查看
                checkNum--;
                continue;
            }
            else
                break;
        }
        if(0 == checkNum)  //查看达到最大值,则重新上电附着
            continue;
        else
            checkNum = checkMaxNum;

        while((send_error_num++) < SEND_ERROR_MAX)
        {
            if(DO_OK != sms_send_data(g_sms_config.da_addr,gp_gps_data)) //短信发送GPS数据
            {
                if(DO_OK == get_cs_state(&csState)) //若发送失败,查看CS域的附着状态
                    break;
                else
                {
                    vTaskDelay(pdMS_TO_TICKS(5000));
                    continue;
                }
            }
            else
            {
                EAT_PRINTF("report data ok!\r\n");
                g_sms_config.send_num += 1;
                send_error_num = 0;
                continue_cycle_num = 0;
                break;
            }
        }
        if(send_error_num >= SEND_ERROR_MAX || 1 = csState)
            send_error_num = 0;
        else if(0 == send_error_num)
            break;
    }

    if(continue_cycle_num >= CYCLE_ERROR_MAX)
        riscv_reboot();
}
Back to top