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();
}