金牌会员
- 积分
- 2285
- 金钱
- 2285
- 注册时间
- 2017-8-24
- 在线时间
- 375 小时
|
根据论坛里面大神的开源ESP8266模块连接MQTT服务器改写的GPRS连接MQTT服务器,自己写的安卓APP测试程序(不太完善)
GPRS模块使用SIM800C
程序首先初始化变量,硬件初始化,检测SIM800C和NRF(4个节点),大循环里面根据GPRS的连接状态控制
如果还未连接网络,就先连接网络,连接网络之后如果还未连接服务器就连接服务器,连接服务器之后就会间隔1秒左右发送一次数据,几个主题发送不同的数据
同时通过4个NRF接收3路温湿度和1路霍尔传感器数据
u8 temp_data[] = "##################------000000000000"; //36字节 MQTT消息内容缓存
最后是RTC时间,前面是发送的数据全部转换成字符进行发送,具体的协议可以自己定义
例如NRF第18个字节代表NRF终端编号
以下是温度拆解过程
menu_mess.temp[0] = tmp_buf[19] == '+' ? ((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01) : \
-((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01);
先判断编号之后的符号,再合成具有两位小数的温度数据
#include "./sys/sys.h"
#include "./delay/delay.h"
#include "./usart/usart.h"
#include "./LED/led.h"
#include "./LCD/lcd.h"
#include "./KEY/key.h"
#include "./RTC/rtc.h"
//#include "./RTC/bsp_rtc.h"
#include "./BEEP/beep.h"
#include "usmart.h"
#include "malloc.h"
#include "./SDIO/sdio_sdcard.h"
#include "./W25QXX/w25qxx.h"
#include "./src/ff.h"
#include "./exfuns/exfuns.h"
#include "text.h"
#include "piclib.h"
#include "./TOUCH/touch.h"
#include "./USART2/usart2.h"
#include "./USART3/usart3.h"
#include "./MPU6050/mpu6050.h"
#include "sim800c.h"
#include "./gps.h"
#include "./OV7670/ov7670.h"
#include "./NRF24L01/24l01.h"
#include "./TIMER/timer.h"
//#include "./OV7670/sccb.h"
#include "./OV2640/ov2640.h"
#include "MQTTPacket.h"
#include "StackTrace.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include "./T9INPUT/t9input.h"
#include "stdarg.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* 私有变量 ------------------------------------------------------------------*/
FATFS mfs; /* FatFs文件系统对象 */
FIL mfile; /* 文件对象 */
FRESULT mf_res; /* 文件操作结果 */
char mfpath[] = "0:TEXT"; /* 保存当前扫描路径 */
BYTE WriteBuffer[100] = "欢迎使用智能终端\r\n";
UINT file_num;
nmea_msg gpsx; //GPS信息
const u8 *port = (u8 *)"1883"; //端口固定为1883
const u8 *ipaddr = (u8 *)"118.190.146.251";
typedef struct
{
float temp[3];
float humi[3];
float gps[3];
uint8_t door[4];
short mpu[6];
}menu_message,*menu_message_;
uint16_t screen_w = 800; //屏幕宽度
uint16_t screen_h = 480; //屏幕高度
uint8_t line_w = 3; //分界线宽
uint8_t menu_num = 4; //菜单组数
uint8_t cur_menu_item,old_menu_item; //当前菜单
uint8_t tmp_buf[33]; //NRF缓存
u8 mqtt_msg[200]={0}; //MQTT消息包缓存
u16 len; //消息包有效长度
u8 gprs_tcp_flag; //TCP连接标志
u8 mqtt_data_flag; //MQTT消息类型标志
u8 send_data_flag; //发布消息标志
u8 temp_data[] = "##################------000000000000"; //36字节 MQTT消息内容缓存
u8 message_type; //消息类型,区别TOPIC主题
u8 about_text_size = 24; //关于字体大小
u8* const Info_Show[13]=
{
"温度1","温度2","温度3",
"湿度1","湿度2","湿度3",
"GPS经度","GPS纬度",
"车门信息","陀螺仪状态",
"服务器IP","蓝牙地址","阈值设置"
};
menu_message menu_mess;
//_t9_obj * t9in; //输入法
//私有函数声明
void sim800c_init(void); //SIM800C初始化
void gprs_send_data(u8 * data,u8 lenth); //GPRS发送数据
u8 *my_strstr(const u8 *s1,u16 n1,const u8 *s2,u16 n2); //字符串查找
void Start_Gprs_TCP(void); //GPRS建立TCP连接
void Stop_Gprs_Connect(void); //关闭GPRS连接
void Gps_Msg_Show(void); //显示GPS定位信息
void send_model_temp_humi(menu_message * mes,u8 * space,u8 type); //MQTT发送内容包装
int main(void)
{
int sys_run_times=0;
unsigned char valtest=0;
u8 key,fontok=0;
u8 *p1,*p2,*p3;
u8 hbeaterrcnt=0; //心跳错误计数器,连续5次心跳信号无应答,则重新连接
// t9in = 0;
gprs_tcp_flag = 0;
mqtt_data_flag = 0;
send_data_flag = 0;
message_type = 0;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
uart_init(115200); //串口初始化为115200
usmart_dev.init(72); //初始化USMART
GENERAL_TIMx_Configuration(); //通用定时器初始化:1ms中断一次
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //初始化按键
LCD_Init(); //初始化LCD
BEEP_Init(); //蜂鸣器初始化
W25QXX_Init(); //初始化W25Q128
tp_dev.init(); //初始化触摸屏
usart3_init(115200); //初始化串口3
my_mem_init(SRAMIN); //初始化内部内存池
exfuns_init(); //为fatfs相关变量申请内存
f_mount(fs[0],"0:",1); //挂载SD卡
f_mount(fs[1],"1:",1); //挂载FLASH.
key=KEY_Scan(0);
if(key==KEY0_PRES&&((tp_dev.touchtype&0X80)==0))//强制校准
{
LCD_Clear(WHITE); //清屏0
TP_Adjust(); //屏幕校准
TP_Save_Adjdata();
LCD_Clear(WHITE); //清屏
}
fontok=font_init(); //检查字库是否OK
if(fontok||key==KEY1_PRES) //需要更新字库
{
LCD_Clear(WHITE); //清屏
POINT_COLOR=RED; //设置字体为红色
LCD_ShowString(60,50,200,16,16,(u8 *)"ALIENTEK STM32");
while(SD_Init()) //检测SD卡
{
LCD_ShowString(60,70,200,16,16,(u8 *)"SD Card Failed!");
delay_ms(200);
LCD_Fill(60,70,200+60,70+16,WHITE);
delay_ms(200);
}
LCD_ShowString(60,70,200,16,16,(u8 *)"SD Card OK");
LCD_ShowString(60,90,200,16,16,(u8 *)"Font Updating...");
key=update_font(20,110,16,(u8 *)"0:"); //从SD卡更新
while(key) //更新失败
{
LCD_ShowString(60,110,200,16,16,(u8 *)"Font Update Failed!");
delay_ms(200);
LCD_Fill(20,110,200+20,110+16,WHITE);
delay_ms(200);
}
LCD_ShowString(60,110,200,16,16,(u8 *)"Font Update Success!");
delay_ms(1500);
LCD_Clear(WHITE); //清屏
}
//RTC_CheckAndConfig(&systmtime);
RTC_Init(); //RTC初始化
delay_ms(1000);
RTC_Get();
printf("time:%02d-%02d-%02d.%02d:%02d:%02d\r\n",calendar.w_year%100,calendar.w_month,calendar.w_date,calendar.hour,calendar.min,calendar.sec);
init_gps();
NRF24L01_Init();
while(NRF24L01_Check()){;}
NRF24L01_RX_Mode();
LCD_Clear(BLACK);
key = 0;
piclib_init(); //初始化画图
//I2C初始化
i2c_CfgGpio();
//MPU6050初始化
MPU6050_Init();
//检测MPU6050
// while(!MPU6050ReadID()){;}
while(sim800c_send_cmd((u8 *)"AT",(u8 *)"OK",100))//检测是否应答AT指令
{
Show_Str(40,55,200,16,(u8 *)"未检测到模块!!!",16,0);
delay_ms(800);
Show_Str(40,55,200,16,(u8 *)"尝试连接模块...",16,0);
delay_ms(400);
}
printf("SIM800C Check OK\r\n");
p1=mymalloc(SRAMIN,100); //申请100字节内存
while(1)
{
if(NRF24L01_RxPacket(tmp_buf)==0)
{
printf("NRF24L01:%s\r\n",(char *)tmp_buf);
switch(tmp_buf[17])
{
case '0'://终端1
menu_mess.temp[0] = tmp_buf[19] == '+' ? ((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01) : \
-((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01);
if(tmp_buf[27] != '#')
menu_mess.humi[0] = (tmp_buf[27] - '0') * 10 + (tmp_buf[28] - '0') * 1;
break;
case '1'://终端2
menu_mess.temp[1] = tmp_buf[19] == '+' ? ((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01) : \
-((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01);
if(tmp_buf[27] != '#')
menu_mess.humi[1] = (tmp_buf[27] - '0') * 10 + (tmp_buf[28] - '0') * 1;
break;
case '2'://终端3
menu_mess.temp[2] = tmp_buf[19] == '+' ? ((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01) : \
-((tmp_buf[20] - '0') * 10 + (tmp_buf[21] - '0') * 1 + (tmp_buf[23] - '0') * 0.1 + (tmp_buf[24] - '0') * 0.01);
if(tmp_buf[27] != '#')
menu_mess.humi[2] = (tmp_buf[27] - '0') * 10 + (tmp_buf[28] - '0') * 1;
break;
case '3'://终端4
menu_mess.door[0] = tmp_buf[19] == 0x17 ? 0x11 : 0x10;
break;
default :
break;
}
}
sys_run_times++;
if(gprs_tcp_flag == 17)
{
//构建MQTT连接
switch(mqtt_data_flag)
{
case 0:
sim800c_send_cmd("AT+CIPSTATUS","OK",500); //查询连接状态
if(strstr((const char*)USART3_RX_BUF,"CONNECT OK"))
{
len=mqtt_connect_message(mqtt_msg,"STM32","admin","public");//id=123456,用户名和密码为空
gprs_send_data((u8 *)mqtt_msg,len);
delay_ms(600);
len=mqtt_subscribe_message(mqtt_msg,"home/temp",1,1); //订阅test主题
gprs_send_data((u8 *)mqtt_msg,len);
printf("MQTT Connect and subscribe OK\r\n");
}
mqtt_data_flag = 1;
break;
case 1:
if(17 == send_data_flag)
{
MQTTString topicString = MQTTString_initializer;
RTC_Get();
send_model_temp_humi(&menu_mess,(u8 *)temp_data,message_type);
temp_data[24] = calendar.w_year%100/10+'0';
temp_data[25] = calendar.w_year%10+'0';
temp_data[26] = calendar.w_month%100/10+'0';
temp_data[27] = calendar.w_month%10+'0';
temp_data[28] = calendar.w_date%100/10+'0';
temp_data[29] = calendar.w_date%10+'0';
temp_data[30] = calendar.hour%100/10+'0';
temp_data[31] = calendar.hour%10+'0';
temp_data[32] = calendar.min%100/10+'0';
temp_data[33] = calendar.min%10+'0';
temp_data[34] = calendar.sec%100/10+'0';
temp_data[35] = calendar.sec%10+'0';
printf("数据发送中...\r\n"); //提示数据发送中
if(0 == message_type)
{
topicString.cstring = "L180309001/YY0118050001/Temp"; //发送的主题
}
else if(1 == message_type)
{
topicString.cstring = "L180309001/YY0118050001/EGps";
}
else if(2 == message_type)
{
topicString.cstring = "L180309001/YY0118050001/Gyro";
}
else if(3 == message_type)
{
topicString.cstring = "L180309001/YY0118050001/Door";
}
else if(4 == message_type)
{
topicString.cstring = "L180309001/YY0118050001/Point";
}
message_type++;
if(message_type>=5)
message_type = 0;
len = MQTTSerialize_publish(mqtt_msg, 200, 0, 0, 0, 0, topicString, (u8 *)temp_data, strlen((const char *)temp_data)); /* 2 */
gprs_send_data((u8 *)mqtt_msg,len);
printf("MQTT Send data OK\r\n");
send_data_flag = 0;GPIOB -> ODR ^= GPIO_Pin_5;
}
break;
}
if(USART3_RX_STA&0X8000) //接收到一次数据了
{
USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0; //添加结束符
printf("%s",USART3_RX_BUF); //发送到串口
if(hbeaterrcnt) //需要检测心跳应答
{
if(strstr((const char*)USART3_RX_BUF,"SEND OK"))hbeaterrcnt=0;//心跳正常
}
p2=(u8*)strstr((const char*)USART3_RX_BUF,"+IPD");
if(p2) //接收到TCP/UDP数据
{
p3=(u8*)strstr((const char*)p2,",");
p2=(u8*)strstr((const char*)p2,":");
p2[0]=0; //加入结束符
sprintf((char*)p1,"收到%s字节",p3+1); //接收到的字节数
printf("%s\r\n",(char*)p1);
}
USART3_RX_STA=0;
}
}
else
{
Start_Gprs_TCP(); //创建TCP连接
}
if(17 == (sys_run_times%100))
{
menu_mess.gps[0] = (float)(gpsx.longitude/100000);
menu_mess.gps[1] = (float)(gpsx.latitude/100000);
menu_mess.gps[2] = (float)(gpsx.speed/1000);
send_data_flag = 17;
printf("Send flag OK\r\n");
hbeaterrcnt++;
printf("hbeaterrcnt:%d\r\n",hbeaterrcnt); //方便调试代码
}
else if(27 == (sys_run_times%5000))
{
len = mqtt_ping_message(mqtt_msg); /* 2 */
gprs_send_data((u8 *)mqtt_msg,len);
printf("heart Send OK\r\n");
}
switch(KEY_Scan(0))
{
case KEY0_PRES:
f_close(&mfile);
while(1)
{
printf("System Stop\r\n");
delay_ms(1000);
}
break;
default:
break;
}
delay_ms(6);
// printf("Sys_Time:%d \r\n",sys_run_times);
}
while(1)
{
printf("Error\r\n");
delay_ms(500);
}
}
void Start_Gprs_TCP(void)
{
//
u8 *p1,p2[100];
u8 res=0;
p1=mymalloc(SRAMIN,100); //申请50个字节的内存
sim800c_send_cmd((u8 *)"ATE0",(u8 *)"OK",200); //不回显
USART3_RX_STA=0;
sim800c_send_cmd("AT+SAPBR=3,1,\"Contype\",\"GPRS\"","OK",200); //配置承载场景1
sim800c_send_cmd("AT+SAPBR=3,1,\"APN\",\"CMNET\"","OK",200);
sim800c_send_cmd("AT+SAPBR=1,1",0,200); //激活一个GPRS上下文
delay_ms(5);
sim800c_send_cmd("AT+CNTPCID=1","OK",200); //设置CNTP使用的CID
sim800c_send_cmd("AT+CNTP=\"202.120.2.101\",32","OK",200); //设置NTP服务器和本地时区(32时区 时间最准确)
sim800c_send_cmd("AT+CNTP","+CNTP: 1",600); //同步网络时间
USART3_RX_STA=0;
if(sim800c_send_cmd("AT+CPIN?","OK",200))res|=1<<0; //查询SIM卡是否在位
USART3_RX_STA=0;
if(0 == res)
{
sim800c_send_cmd("AT+CIPCLOSE=1","CLOSE OK",100); //关闭连接
sim800c_send_cmd("AT+CIPSHUT","SHUT OK",100); //关闭移动场景
if(sim800c_send_cmd("AT+CGCLASS=\"B\"","OK",1000)) printf("SIM800C Init1 FAIL\r\n"); //设置GPRS移动台类别为B,支持包交换和数据交换
if(sim800c_send_cmd("AT+CGDCONT=1,\"IP\",\"CMNET\"","OK",1000)) printf("SIM800C Init2 FAIL\r\n"); //设置PDP上下文,互联网接协议,接入点等信息
if(sim800c_send_cmd("AT+CGATT=1","OK",500)) printf("SIM800C Init3 FAIL\r\n"); //附着GPRS业务
if(sim800c_send_cmd("AT+CIPCSGP=1,\"CMNET\"","OK",500)) printf("SIM800C Init4 FAIL\r\n"); //设置为GPRS连接模式
if(sim800c_send_cmd("AT+CIPHEAD=1","OK",500)) printf("SIM800C Init5 FAIL\r\n"); //设置接收数据显示IP头(方便判断数据来源)
printf("SIM800C Start OK\r\n");
USART3_RX_STA=0;
sprintf((char*)p2,"AT+CIPSTART=\"%s\",\"%s\",\"%s\"","TCP",ipaddr,port);
if(0==sim800c_send_cmd(p2,"OK",500)) //发起连接
{
delay_ms(1500);delay_ms(1000);
sim800c_send_cmd("AT+CIPSTATUS","OK",500); //查询连接状态
USART3_RX_STA = 0;
if(strstr((const char*)USART3_RX_BUF,"CONNECT OK"))
{
gprs_tcp_flag = 17;
printf("SIM800C TCP Connect OK\r\n");
}
else
{
gprs_tcp_flag = 0;
printf("SIM800C TCP Connect Fail\r\n");
}
}
}
myfree(SRAMIN,p2);
}
void Stop_Gprs_Connect(void)
{
sim800c_send_cmd("AT+CIPCLOSE=1","CLOSE OK",100); //关闭连接
sim800c_send_cmd("AT+CIPSHUT","SHUT OK",100); //关闭移动场景
}
void send_model_temp_humi(menu_message * mes,u8 * space,u8 type)
{
long val;
u8 t;
//if(strlen(space)<36)return;
switch(type)
{
case 0: //温湿度+RTC
for(t = 0;t < 3;t ++)
{
val = (int)(mes->temp[t] * 100);
if(val<0)
{
space[t * 6] = '-';
}
else
{
space[t * 6] = '+';
}
val = val >= 0 ? val : -val;
space[t * 6 + 1] = val % 10000 /1000 + '0';
space[t * 6 + 2] = val % 1000 /100 + '0';
space[t * 6 + 3] = '.';
space[t * 6 + 4] = val % 100 /10 + '0';
space[t * 6 + 5] = val % 10 /1 + '0';
val = (int)(mes->humi[t]);
space[18 + t * 2] = val % 100 / 10 + '0';
space[18 + t * 2 + 1] = val % 10 / 1 + '0';
}
printf("Temp_Data:%s\r\n",(u8 *)space);
break;
case 1: //GPS+RTC
for(t = 0;t < 2;t ++)
{
val = (long)(mes->gps[t] * 100000);
if(val<0)
{
space[t * 10] = '-';
}
else
{
space[t * 10] = '+';
}
val = val >= 0 ? val : -val;
space[t * 10 + 1] = val % 100000000 /10000000 + '0';
space[t * 10 + 2] = val % 10000000 /1000000 + '0';
space[t * 10 + 3] = val % 1000000 /100000 + '0';
space[t * 10 + 5] = val % 100000 /10000 + '0';
space[t * 10 + 6] = val % 10000 /1000 + '0';
space[t * 10 + 7] = val % 1000 /100 + '0';
space[t * 10 + 8] = val % 100 /10 + '0';
space[t * 10 + 9] = val % 10 /1 + '0';
space[t * 10 + 4] = '.';
}
val = (int)(mes->gps[2] * 10);
space[20] = val % 10000 / 1000 + '0';
space[21] = val % 1000 / 100 + '0';
space[22] = val % 100 / 10 + '0';
space[23] = val % 10 / 1 + '0';
printf("Gps_Data:%s\r\n",(u8 *)space);
break;
case 2: //陀螺仪+RTC
MPU6050ReadAcc((short *)(mes->mpu));
for(t = 0;t < 3;t ++)
{
space[t * 2] = ((mes -> mpu[t]) >> 8) & 0xFF;
space[t * 2 + 1] = (mes -> mpu[t]) & 0xFF;
}
MPU6050ReadGyro((short *)(mes->mpu));
for(t = 0;t < 3;t ++)
{
space[6 + t * 2] = ((mes -> mpu[t]) >> 8) & 0xFF;
space[6 + t * 2 + 1] = (mes -> mpu[t]) & 0xFF;
}
for(t = 12;t < 24;t ++)
{
space[t] = '#';
}
printf("Gyro_Data:%s\r\n",(u8 *)space);
break;
case 3: //开关门+RTC
space[0] = mes->door[0] + '0';
for(t = 1;t < 24;t ++)
{
space[t] = '#';
}
printf("Door_Data:%s\r\n",(u8 *)space);
break;
case 4: //点熄火+RTC
space[0] = mes->door[1] + '0';
for(t = 1;t < 24;t ++)
{
space[t] = '#';
}
printf("Point_Data:%s\r\n",(u8 *)space);
break;
default :
break;
}
}
//在str1字符串中找出str2字符串(不包括str2的串结束符,忽略str中的\0)
//返回该位置的指针,如找不到,返回空指针
u8 *my_strstr(const u8 *s1,u16 n1,const u8 *s2,u16 n2)
{
int n,x=0,y=0;
if (*s2)
{
while(1)
{
if(*s1==*s2)//找到s2第一次出现,两种情况考虑
{
for (n=0;n<n2;n++)
{
if (*(s1+n)==*(s2+n))
{
y++;
if (y>=n2)
//if (!*(s2+n+1)) //s2下一个字符是否为'\0'
{
return (u8 *)s1;
}
if (x+n>=n1-1) //防止数组越界
{
return NULL;
}
if (*(s1+n+1)!=*(s2+n+1))//查找的下一个字符不相等,一个字符相等
{
break;
}
}
else
{
break;
}
}
}
s1++;
x++;
if(x>=n1)
{
break;
}
}
return NULL;
}
else
{
return (u8*)s1;
}
}
void gprs_send_data(u8 *data,u8 lenth)
{
if(sim800c_send_cmd("AT+CIPSEND",">",500)==0) //发送数据
{
//u3_printf("%s",(u8 *)data);
my_u3_send((char *)mqtt_msg,lenth);
delay_ms(10);
if(sim800c_send_cmd((u8*)0X1A,"SEND OK",5000)==0)
printf("GPRS数据发送成功!\r\n");//最长等待10s
}
else
sim800c_send_cmd((u8*)0X1B,0,0); //ESC,取消发送
}
安卓APP程序使用AndroidStdio2.3.2开发
可以设置发布主题和内容
欢迎大家修正
|
|