链接
https://detail.tmall.com/item.htm?_u=d1qf7bf5f35c&id=592705445141&spm=a1z09.2.0.0.d67e2e8d7TgPZ7

$GPRMC,055430.00,A,2256.25353,N,11343.15605,E,2.440,177.00,080119,,,A*69
055430.00, <1> UTC 时间,hhmmss(时分秒)格式
A, <2> 定位状态,A=有效定位,V=无效定位)
2256.25353, <3>纬度ddmm.mmmm(度分)格式(前面的0也将被传输 22°+56.25353
N, <4> 纬度半球N(北半球)或S(南半球)
11343.15605, <5>经度dddmm.mmmm(度分)格式(前面的0也将被传输)<6> 经度半球E(东经)或W(西经)
E, <6> 经度半球E(东经)或W(西经)
2.440, <7>地面速率(000.0~999.9节,前面的0也将被传输)*1.852 = KM
177.00, <8>地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)
080119, <9> UTC 日期,ddmmyy(日月年)格式
, <10>磁偏角(000.0~180.0度,前面的0也将被传输)
, <11> 磁偏角方向,E(东)或W(西)
A*69 <12>模式指示(仅NMEA01833.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
dd+(mm.mmmm/60)
GPS的数据格式是DDMM.MMMMMM
获取到的GPS帧数据比如是:$GNRMC,112317.000,A,3438.1633,N,11224.4992,E,0.19,186.95,240916,,,A*7D
说明
经度112°24.4992′
纬度34°38.1633′
OneNet支持的GPS数据经测试是DD.DDDDD,因此需要转换
经度为 112+24.4992/60 = 112.40832
纬度为 34+38.1633/60 = 34.636055
上传到GPS的数据流为
{"datastreams":[{"id":"location","datapoints":[{"value":{"lon":112.40832,"lat":34.636055}}]}]}
OneNet的GPS坐标是经过百度地图纠偏过的,所以这部分转换交给平台,直接上传上面的数据即可
用Arduino测试下转换计算过程:
//char lon_str[] = "10845.55422";
//char lat_str[] = "3402.15704";
//String lon_str = "10845.55422";
//String lat_str = "3402.15704";
// double 转化 string
char* dtostr(char *str, double d)
{
sprintf(str, "%f", d);
return str;
}
// GPS数据 mmmm格式 抓换位
double longitudeToOnenetFormat(String lons)
{
double lon_temp = 0;
long lon_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lon_Onenet_double = 0;
//lon_temp = atof(lon_str); char[] char lon_str[] = "10845.55422";
lon_temp = (lons).toFloat();
lon_Onenet =lon_temp*100000; //转换为整数
dd_int = lon_Onenet/10000000; //取出dd
mm_int = lon_Onenet%10000000; //取出MM部分
lon_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lon_Onenet_double;
}
double latitudeToOnenetFormat(String lat_s)
{
double lat_temp = 0;
long lat_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lat_Onenet_double = 0;
//lat_temp = atof(lat_str); ///char lat_str[] = "3402.15704";
lat_temp = (lat_s).toFloat();
lat_Onenet =lat_temp*100000; //转换为整数
dd_int = lat_Onenet/10000000; //取出dd
mm_int = lat_Onenet%10000000; //取出MM部分
lat_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lat_Onenet_double;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
String lon_str = "10845.55422";
String lat_str = "3402.15704";
double lond=longitudeToOnenetFormat(lon_str);
double latd=latitudeToOnenetFormat(lat_str);
// char lonc[25] ;
// char latc[25] ;
//
// dtostr(lonc,lons);
// dtostr(latc,lats);
String lons= String(lond,6);
String lats= String(latd,6);
Serial.print(lats);Serial.print(" "); Serial.println(lons);
}
void loop(){
}

在地图中选择对应设备中名为“location”的数据流即可。


测试样例1 纯净版本
arduino stm32采集 esp8266上报
esp8266接口

SoftwareSerial Serial_Gps_arduino(4, 5); // SoftwareSerial(rx , tx) SoftwareSerial Serial_esp_arduino(6, 7); // SoftwareSerial(rx , tx)

stm32接口

Serial1 电脑串口 STM32 PA9 TX-> USB-ttl Rx STM32 PA10 RX-> USB-ttl Tx Serial2 GPS STM32 PA2 TX -> GPS Rx STM32 PA3 RX -> GPS Tx Serial3 esp8266 STM32 PB10 TX -> ESP Rx STM32 PB11 RX -> ESP Tx
代码
发送端

#include <SoftwareSerial.h>
SoftwareSerial Serial_Gps_arduino(4, 5); // SoftwareSerial(rx , tx)
SoftwareSerial Serial_esp_arduino(6, 7); // SoftwareSerial(rx , tx)
#define Serial_Gps Serial_Gps_arduino
#define Serial_esp Serial_esp_arduino
//#define Serial_Gps Serial2
//#define Serial_esp Serial3
#include "API_Gps.h"
#define GNRMC_TERM "$GNRMC," //定义要解析的指令,因为这条指令包含定位和时间信息
char nmeaSentence[68];
String latitude_msg; //纬度
String longitude_msg; //经度
String lndSpeed; //速度
String gpsTime; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
String beiJingTime; //北京时间
String latitude_old; //纬度
String longitude_old; //经度
String lndSpeed_old; //速度
String gpsTime_old; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
String beiJingTime_old; //北京时间
void Get_Gps(){
// For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 3000;) //一秒钟内不停扫描GPS信息
{
while (Serial_Gps.available()) //串口获取到数据开始解析
{
char c = Serial_Gps.read(); //读取一个字节获取的数据
switch(c) //判断该字节的值
{
case '$': //若是$,则说明是一帧数据的开始
Serial_Gps.readBytesUntil('*', nmeaSentence, 67); //读取接下来的数据,存放在nmeaSentence字符数组中,最大存放67个字节
//Serial_Gps.println(nmeaSentence);
latitude_msg = parseGNRMcLat(nmeaSentence); //获取纬度值
longitude_msg = parseGNRMcLon(nmeaSentence);//获取经度值
lndSpeed = parseGNRMcSpeed(nmeaSentence);//获取速度值
gpsTime = parseGNRMcTime(nmeaSentence);//获取GPS时间
if(latitude_msg > "") //当不是空时候打印输出
{
//Serial.println("------------------------------------");
//Serial.println("latitude_msg: " + latitude_msg);
latitude_old=latitude_msg;
}
if(longitude_msg > "") //当不是空时候打印输出
{
//Serial.println("longitude_msg: " + longitude_msg);
longitude_old=longitude_msg;
}
if(lndSpeed > "") //当不是空时候打印输出
{
//Serial.println("Speed (knots): " + lndSpeed);
lndSpeed_old=lndSpeed;
}
if(gpsTime > "") //当不是空时候打印输出
{
//Serial.println("gpsTime: " + gpsTime);
beiJingTime = getBeiJingTime(gpsTime); //获取北京时间
//Serial.println("beiJingTime: " + beiJingTime);
beiJingTime_old=beiJingTime;
}
}//switch(c)
}// while
}//for
}
void setup() //初始化内容
{
Serial.begin(9600);
//pinMode(pin_light, INPUT);
Serial_esp.begin(9600); //定义波特率9600,
Serial_Gps.begin(9600); //定义波特率9600,
Serial.println("开始运行");
latitude_msg="0"; //纬度
longitude_msg="0"; //经度
lndSpeed="0"; //速度
gpsTime="0"; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
beiJingTime="0"; //北京时间
}
char lonc[25] ;
char latc[25] ;
void loop() //主循环
{
Get_Gps();
double lond=longitudeToOnenetFormat(longitude_old);
double latd=latitudeToOnenetFormat(latitude_old);
String lons= String(lond,6);
String lats= String(latd,6);
//Serial.print(lats); Serial.print(" "); Serial.println(lons);
String showmsg=String()
+String("纬度")+"-"
+String(lats)+"-"
+String("经度")+"-"
+String(lons)+"-"
+String("速度")+"-"
+String(lndSpeed_old)+"-"
+String("北京时间戳秒")+"-"
+String(beiJingTime_old)+"-"
;
Serial.println(showmsg);
String msg=String()
+String(lats)+"-"
+String(lons)+"-"
+String(lndSpeed_old)+"-"
+String(beiJingTime_old)+"-"
;
Serial_esp.println(msg);
delay(1000);
}//loop()
API_Gps.h
// GPS数据 longitude mmmm格式 转换成onenet格式
double longitudeToOnenetFormat(String lons)
{
if (lons==""){return 0;}
double lon_temp = 0;
long lon_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lon_Onenet_double = 0;
//lon_temp = atof(lon_str); char[] char lon_str[] = "10845.55422";
lon_temp = (lons).toFloat();
lon_Onenet =lon_temp*100000; //转换为整数
dd_int = lon_Onenet/10000000; //取出dd
mm_int = lon_Onenet%10000000; //取出MM部分
lon_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lon_Onenet_double;
}
// GPS数据 latitude mmmm格式 转换成onenet格式
double latitudeToOnenetFormat(String lat_s)
{
if(lat_s==""){return 0;}
double lat_temp = 0;
long lat_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lat_Onenet_double = 0;
//lat_temp = atof(lat_str); ///char lat_str[] = "3402.15704";
lat_temp = (lat_s).toFloat();
lat_Onenet =lat_temp*100000; //转换为整数
dd_int = lat_Onenet/10000000; //取出dd
mm_int = lat_Onenet%10000000; //取出MM部分
lat_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lat_Onenet_double;
}
String getBeiJingTime(String s)
{
int hour = s.substring(0,2).toInt();
int minute = s.substring(2,4).toInt();
int second = s.substring(4,6).toInt();
hour += 8;
if(hour > 24)
hour -= 24;
s = String(hour) + String(minute) + String(second);
return s;
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Latitude
String parseGNRMcLat(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lat;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 5; i++)
{
if(i < 3)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 3, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
if(i == 3)
{
lEndLoc = s.indexOf(',', pLoc+1);
lat = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 3, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
else
{
dEndLoc = s.indexOf(',', lEndLoc+1);
// lat = lat + " " + s.substring(lEndLoc+1, dEndLoc);
/*Serial.print("i = 4, lEndLoc: ");
Serial.println(lEndLoc);
Serial.print("dEndLoc: ");
Serial.println(dEndLoc);*/
}
}
return lat;
}
//}
//}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcLon(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lon;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 7; i++)
{
if(i < 5)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 3, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
if(i == 5)
{
lEndLoc = s.indexOf(',', pLoc+1);
lon = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 3, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
else
{
dEndLoc = s.indexOf(',', lEndLoc+1);
// lon = lon + " " + s.substring(lEndLoc+1, dEndLoc);
/*Serial.print("i = 4, lEndLoc: ");
Serial.println(lEndLoc);
Serial.print("dEndLoc: ");
Serial.println(dEndLoc);*/
}
}
return lon;
}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcSpeed(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lndSpeed;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 8; i++)
{
if(i < 7)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 8, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
else
{
lEndLoc = s.indexOf(',', pLoc+1);
lndSpeed = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 8, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
}
return lndSpeed;
}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcTime(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String gpsTime;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 2; i++)
{
if(i < 1)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 8, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
else
{
lEndLoc = s.indexOf(',', pLoc+1);
gpsTime = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 8, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
}
return gpsTime;
}
}
// Turn char[] array into String object
String charToString(char *c)
{
String val = "";
for(int i = 0; i <= sizeof(c); i++)
{
val = val + c;
}
return val;
}
ESP8266接收上报端

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Ticker.h>
#include <SoftwareSerial.h>
//实例化软串口
SoftwareSerial mySerial(D1, D2); // RX, TX
//分割结果
#define sleng 10 //数组大小
String split_result[sleng];//手动动态调整数组大小,保证数组可以满足容量
#define WIFI_DEBUG 0 //1:使用一键配网,其它值则使用默认无线账号密码
#define ONENET_DISCONNECTED 1 //已经断开
#define ONENET_CONNECTED 2 //已经连接上
#define ONENET_RECONNECT 3 //重连成功
#define VER "ESP8266_MQTT_V1.0" //版本号
const char* ssid = "yaoyao";//wifi账号
const char* password = "love123456";//wifi密码
/*OneNet*/
PubSubClient mqttClient;
const char* mqttServer = "183.230.40.39";//mqtt服务器
const uint16_t mqttPort = 6002; //端口号
#define onenet_productId "589421" //产品ID
#define onenet_deviceId "1065407752" //设备ID
#define onenet_apiKey "mvHyjtrjuXd=6GWhWMtQTB0nNDo=" //产品API_KEY
int state;
Ticker delayTimer;
WiFiClient espClient;
/*字符串分割
输入参数
String zifuchuan, 输入字符串
String fengefu, 分隔符号-可以是多个
String result[] 输出结果
*/
void Split(String zifuchuan,String fengefu,String result[])
{
int weizhi; //找查的位置
String temps;//临时字符串
int i=0;
do
{
weizhi = zifuchuan.indexOf(fengefu);//找到位置
if(weizhi != -1)//如果位置不为空
{
temps=zifuchuan.substring(0,weizhi);//打印取第一个字符
zifuchuan = zifuchuan.substring(weizhi+fengefu.length(), zifuchuan.length());
//分隔后只取后面一段内容 以方便后面找查
}
else
{ //上面实在找不到了就把最后的 一个分割值赋值出来以免遗漏
if(zifuchuan.length() > 0)
temps=zifuchuan;
}
result[i++]=temps;
//Serial.println(result[i-1]);//在这里执行分割出来的字符下面不然又清空了
temps="";
}
while(weizhi >=0);
}
/* 延时N秒 */
void delayNs(uint8_t m){
for(uint8_t index = 0;index<m;index ++){ delay(1000); ESP.wdtFeed();
}
}
/* 延时重启 */
void delayRestart(float t) {
Serial.print("Restart after ");
Serial.print(t);
Serial.println("s");
delayTimer.attach(t, []() {
Serial.println("\r\nRestart now!");
ESP.restart();
});
}
/* 自动连接 */
bool autoConfig()
{
WiFi.begin();
for (int i = 0; i < 20; i++)
{ if (WiFi.status() == WL_CONNECTED) {
Serial.println("AutoConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.printDiag(Serial); return true; }
else {
Serial.print("AutoConfig Waiting......");
Serial.println(WiFi.status());
delay(1000);
}
}
Serial.println("AutoConfig Faild!" );
return false;
}
/* 一键配网 */
void smartConfig()
{
WiFi.mode(WIFI_STA);
Serial.println("\r\nWait for Smartconfig");
WiFi.beginSmartConfig();
while (1)
{ Serial.print(".");
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
if (WiFi.smartConfigDone()) { Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.setAutoConnect(true); // 设置自动连接
break; }
delay(1000); // 这个地方一定要加延时,否则极易崩溃重启
}
}
/* 连接OneNet */
int connectToOneNetMqtt(){
int cnt = 0;
while(!mqttClient.connected()){
ESP.wdtFeed();
cnt++;
Serial.println("Connect to OneNet MQTT...");
if (mqttClient.connect(onenet_deviceId,onenet_productId,onenet_apiKey)) {
Serial.println("connect success!");
return ONENET_RECONNECT;
}
else {
Serial.print("connect fail!");
Serial.println(" try again in 5 seconds");
delay(5000);
}
if(cnt >=10){
//只做10次连接到OneNet,连接不上重启8266
cnt = 0;
delayRestart(1);
} }
return ONENET_CONNECTED;
}
/* 云端下发 */
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if ((char)payload[0] == '1') {
digitalWrite(LED_BUILTIN, LOW);
}
else {
digitalWrite(LED_BUILTIN, HIGH);
}
}
/* 发布一个传感器信息
String sensorname 传感器名字
String data 数据
int sendlen=200; 数据大小
*/
void pubMQTTmsg_one_name_value(String sensorname,String data){
long lastMsg = 0;
int sendlen=200;//28 //数组大小
char msg[sendlen+22]; //数组大小
char tmp[sendlen];
char d[3];
//snprintf(tmp,sizeof(tmp),String("")+"{\""+sensorname+"\":%d}",data);
String sendmsg=String("")+"{\""+sensorname+"\":"+data+"}";
//String sendmsg="{\"mq2\":1234,\"mq3\":345}";
sendmsg.toCharArray(tmp, sendlen);
Serial.println(tmp);
uint16_t streamLen= strlen(tmp);
d[0]='\x03';
d[1] = (streamLen >> 8);
d[2] = (streamLen & 0xFF);
snprintf(msg,sizeof(msg),"%c%c%c%s",d[0],d[1],d[2],tmp);
mqttClient.publish("$dp", (uint8_t*)msg,streamLen+3,false);
}
/* 发布多个传感器信息
String sendmsg 打包数据
{"senseor1":1213,"senseor2":313.3,"senseor3":543.09,"senseor4":645.0}
注意 ” 转义字符串 \“
*/
void pubMQTTmsg_more_name_value(String sendmsg_in){
long lastMsg = 0;
int sendlen=800;//28 //数组大小
char msg[sendlen+22]; //数组大小
char tmp[sendlen];
char d[3];
//snprintf(tmp,sizeof(tmp),String("")+"{\""+sensorname+"\":%d}",data);
//String sendmsg=String("")+"{\""+sensorname+"\":"+data+"}";
String sendmsg=sendmsg_in;
sendmsg.toCharArray(tmp, sendlen);
Serial.println(tmp);
uint16_t streamLen= strlen(tmp);
d[0]='\x03';
d[1] = (streamLen >> 8);
d[2] = (streamLen & 0xFF);
snprintf(msg,sizeof(msg),"%c%c%c%s",d[0],d[1],d[2],tmp);
mqttClient.publish("$dp", (uint8_t*)msg,streamLen+3,false);
}
/* 初始化系统 */
void initSystem(){
int cnt = 0;
Serial.begin (9600);
Serial.println("\r\n\r\nStart ESP8266 MQTT");
Serial.print("Firmware Version:");
Serial.println(VER); Serial.print("SDK Version:");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.println(ESP.getSdkVersion());
ESP.wdtEnable(5000);
if(WIFI_DEBUG==1)//开启一键配网模式
{
if (!autoConfig()) {
Serial.println("Start smartConfig");
smartConfig();
}
}
else {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500); cnt++; Serial.print(".");
if(cnt>=40){
cnt = 0; //重启系统
delayRestart(1);
}
}
}
Serial.print("WIFI Connect \r\n");
}
/* 初始化ONENET通信 */
void initOneNetMqtt(){
mqttClient.setServer(mqttServer,mqttPort);
mqttClient.setClient(espClient);
mqttClient.setCallback(callback);
}
/* 初始化 */
void setup() {
initSystem();
initOneNetMqtt();
Serial.begin(9600);
while (!Serial) {
}
Serial.println("Goodnight moon!");
mySerial.begin(115200);
}
/* 主函数 */
void loop() {
ESP.wdtFeed();
state = connectToOneNetMqtt();
//Serial.println(WiFi.status());
//接收串口消息
if (mySerial.available()){
String split_input =mySerial.readStringUntil(';');
//Serial.println(split_input);
//分割解析
Split(split_input,"-",split_result);//分割调用
Serial.println("----------------");
//打印消息 检查是否为空
for(int i=0;i<sleng;i++)
{
if(split_result[i]!="")
{
Serial.println(String(i)+"-"+split_result[i]);
}
else
{
split_result[i]="0";
}
}
//发送onenet
ESP.wdtFeed();
state = connectToOneNetMqtt();
//Serial.println(WiFi.status());
if(state == ONENET_RECONNECT){
mqttClient.loop();
}
else if(state == ONENET_CONNECTED)
{
//3402.16056-10845.55338-0.10-11228-4.89-18.50-
String msg=String("")+"{"
+"\"location\":"+"{\"lat\":"+split_result[0]+",\"lon\":"+split_result[1]+"}"+","
+"\"速度\":"+String(split_result[2])
+"}";
pubMQTTmsg_more_name_value(msg);
mqttClient.loop();
}
//delay(2000);
}
}
测试样例2 采集 紫外线 A0 + 采集DS18B20温度 + gps
ESP8266上传代码

注意软串口波特率吧 115200 适配loral
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Ticker.h>
#include <SoftwareSerial.h>
//实例化软串口
SoftwareSerial mySerial(D1, D2); // RX, TX
//分割结果
#define sleng 10 //数组大小
String split_result[sleng];//手动动态调整数组大小,保证数组可以满足容量
#define WIFI_DEBUG 0 //1:使用一键配网,其它值则使用默认无线账号密码
#define ONENET_DISCONNECTED 1 //已经断开
#define ONENET_CONNECTED 2 //已经连接上
#define ONENET_RECONNECT 3 //重连成功
#define VER "ESP8266_MQTT_V1.0" //版本号
const char* ssid = "yaoyao";//wifi账号
const char* password = "love123456";//wifi密码
/*OneNet*/
PubSubClient mqttClient;
const char* mqttServer = "183.230.40.39";//mqtt服务器
const uint16_t mqttPort = 6002; //端口号
#define onenet_productId "207282" //产品ID
#define onenet_deviceId "515439794" //设备ID
#define onenet_apiKey "ZcxLlq=Pd4t6CgaFKcB=zQXzDt8=" //产品API_KEY
int state;
Ticker delayTimer;
WiFiClient espClient;
/*字符串分割
输入参数
String zifuchuan, 输入字符串
String fengefu, 分隔符号-可以是多个
String result[] 输出结果
*/
void Split(String zifuchuan,String fengefu,String result[])
{
int weizhi; //找查的位置
String temps;//临时字符串
int i=0;
do
{
weizhi = zifuchuan.indexOf(fengefu);//找到位置
if(weizhi != -1)//如果位置不为空
{
temps=zifuchuan.substring(0,weizhi);//打印取第一个字符
zifuchuan = zifuchuan.substring(weizhi+fengefu.length(), zifuchuan.length());
//分隔后只取后面一段内容 以方便后面找查
}
else
{ //上面实在找不到了就把最后的 一个分割值赋值出来以免遗漏
if(zifuchuan.length() > 0)
temps=zifuchuan;
}
result[i++]=temps;
//Serial.println(result[i-1]);//在这里执行分割出来的字符下面不然又清空了
temps="";
}
while(weizhi >=0);
}
/* 延时N秒 */
void delayNs(uint8_t m){
for(uint8_t index = 0;index<m;index ++){ delay(1000); ESP.wdtFeed();
}
}
/* 延时重启 */
void delayRestart(float t) {
Serial.print("Restart after ");
Serial.print(t);
Serial.println("s");
delayTimer.attach(t, []() {
Serial.println("\r\nRestart now!");
ESP.restart();
});
}
/* 自动连接 */
bool autoConfig()
{
WiFi.begin();
for (int i = 0; i < 20; i++)
{ if (WiFi.status() == WL_CONNECTED) {
Serial.println("AutoConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.printDiag(Serial); return true; }
else {
Serial.print("AutoConfig Waiting......");
Serial.println(WiFi.status());
delay(1000);
}
}
Serial.println("AutoConfig Faild!" );
return false;
}
/* 一键配网 */
void smartConfig()
{
WiFi.mode(WIFI_STA);
Serial.println("\r\nWait for Smartconfig");
WiFi.beginSmartConfig();
while (1)
{ Serial.print(".");
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
if (WiFi.smartConfigDone()) { Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
WiFi.setAutoConnect(true); // 设置自动连接
break; }
delay(1000); // 这个地方一定要加延时,否则极易崩溃重启
}
}
/* 连接OneNet */
int connectToOneNetMqtt(){
int cnt = 0;
while(!mqttClient.connected()){
ESP.wdtFeed();
cnt++;
Serial.println("Connect to OneNet MQTT...");
if (mqttClient.connect(onenet_deviceId,onenet_productId,onenet_apiKey)) {
Serial.println("connect success!");
return ONENET_RECONNECT;
}
else {
Serial.print("connect fail!");
Serial.println(" try again in 5 seconds");
delay(5000);
}
if(cnt >=10){
//只做10次连接到OneNet,连接不上重启8266
cnt = 0;
delayRestart(1);
} }
return ONENET_CONNECTED;
}
/* 云端下发 */
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload[i]);
}
Serial.println();
if ((char)payload[0] == '1') {
digitalWrite(LED_BUILTIN, LOW);
}
else {
digitalWrite(LED_BUILTIN, HIGH);
}
}
/* 发布一个传感器信息
String sensorname 传感器名字
String data 数据
int sendlen=200; 数据大小
*/
void pubMQTTmsg_one_name_value(String sensorname,String data){
long lastMsg = 0;
int sendlen=200;//28 //数组大小
char msg[sendlen+22]; //数组大小
char tmp[sendlen];
char d[3];
//snprintf(tmp,sizeof(tmp),String("")+"{\""+sensorname+"\":%d}",data);
String sendmsg=String("")+"{\""+sensorname+"\":"+data+"}";
//String sendmsg="{\"mq2\":1234,\"mq3\":345}";
sendmsg.toCharArray(tmp, sendlen);
Serial.println(tmp);
uint16_t streamLen= strlen(tmp);
d[0]='\x03';
d[1] = (streamLen >> 8);
d[2] = (streamLen & 0xFF);
snprintf(msg,sizeof(msg),"%c%c%c%s",d[0],d[1],d[2],tmp);
mqttClient.publish("$dp", (uint8_t*)msg,streamLen+3,false);
}
/* 发布多个传感器信息
String sendmsg 打包数据
{"senseor1":1213,"senseor2":313.3,"senseor3":543.09,"senseor4":645.0}
注意 ” 转义字符串 \“
*/
void pubMQTTmsg_more_name_value(String sendmsg_in){
long lastMsg = 0;
int sendlen=800;//28 //数组大小
char msg[sendlen+22]; //数组大小
char tmp[sendlen];
char d[3];
//snprintf(tmp,sizeof(tmp),String("")+"{\""+sensorname+"\":%d}",data);
//String sendmsg=String("")+"{\""+sensorname+"\":"+data+"}";
String sendmsg=sendmsg_in;
sendmsg.toCharArray(tmp, sendlen);
Serial.println(tmp);
uint16_t streamLen= strlen(tmp);
d[0]='\x03';
d[1] = (streamLen >> 8);
d[2] = (streamLen & 0xFF);
snprintf(msg,sizeof(msg),"%c%c%c%s",d[0],d[1],d[2],tmp);
mqttClient.publish("$dp", (uint8_t*)msg,streamLen+3,false);
}
/* 初始化系统 */
void initSystem(){
int cnt = 0;
Serial.begin (9600);
Serial.println("\r\n\r\nStart ESP8266 MQTT");
Serial.print("Firmware Version:");
Serial.println(VER); Serial.print("SDK Version:");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.println(ESP.getSdkVersion());
ESP.wdtEnable(5000);
if(WIFI_DEBUG==1)//开启一键配网模式
{
if (!autoConfig()) {
Serial.println("Start smartConfig");
smartConfig();
}
}
else {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500); cnt++; Serial.print(".");
if(cnt>=40){
cnt = 0; //重启系统
delayRestart(1);
}
}
}
Serial.print("WIFI Connect \r\n");
}
/* 初始化ONENET通信 */
void initOneNetMqtt(){
mqttClient.setServer(mqttServer,mqttPort);
mqttClient.setClient(espClient);
mqttClient.setCallback(callback);
}
/* 初始化 */
void setup() {
initSystem();
initOneNetMqtt();
Serial.begin(9600);
while (!Serial) {
}
Serial.println("Goodnight moon!");
mySerial.begin(115200);
}
/* 主函数 */
void loop() {
ESP.wdtFeed();
state = connectToOneNetMqtt();
//Serial.println(WiFi.status());
//接收串口消息
if (mySerial.available()){
String split_input =mySerial.readStringUntil(';');
//Serial.println(split_input);
//分割解析
Split(split_input,"-",split_result);//分割调用
Serial.println("----------------");
//打印消息 检查是否为空
for(int i=0;i<sleng;i++)
{
if(split_result[i]!="")
{
Serial.println(String(i)+"-"+split_result[i]);
}
else
{
split_result[i]="0";
}
}
//发送onenet
ESP.wdtFeed();
state = connectToOneNetMqtt();
//Serial.println(WiFi.status());
if(state == ONENET_RECONNECT){
mqttClient.loop();
}
else if(state == ONENET_CONNECTED)
{
//3402.16056-10845.55338-0.10-11228-4.89-18.50-
String msg=String("")+"{"
+"\"location\":"+"{\"lat\":"+split_result[0]+",\"lon\":"+split_result[1]+"}"+","
+"\"速度\":"+String(split_result[2])+","
+"\"紫外线\":"+String(split_result[4])+","
+"\"温度\":"+String(split_result[5])
+"}";
pubMQTTmsg_more_name_value(msg);
mqttClient.loop();
}
//delay(2000);
}
}
arduino采集


{"location":{"lat":34.0215704,"lon":108.4555422},"速度":28,"紫外线":28,"温度":28}
{"location":{"lat":34.0215704,"lon":108.4555422},"速度":29,"紫外线":29,"温度":29}
{"location":{"lat":34.0215704,"lon":108.4555422},"速度":30,"紫外线":30,"温度":30}
{"location":{"lat":34.0215704,"lon":108.4555422},"速度":31,"紫外线":31,"温度":31}

v1_send.ino
#define pin_light A0
#include <DS18B20.h>
DS18B20 ds(8);
#include <SoftwareSerial.h>
SoftwareSerial Serial_Gps(4, 5);
SoftwareSerial Serial_esp(6, 7);
#define GNRMC_TERM "$GNRMC," //定义要解析的指令,因为这条指令包含定位和时间信息
char nmeaSentence[68];
String latitude_msg; //纬度
String longitude_msg; //经度
String lndSpeed; //速度
String gpsTime; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
String beiJingTime; //北京时间
String latitude_old; //纬度
String longitude_old; //经度
String lndSpeed_old; //速度
String gpsTime_old; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
String beiJingTime_old; //北京时间
#include "API_Gps.h"
void Get_Gps(){
// For one second we parse GPS data and report some key values
for (unsigned long start = millis(); millis() - start < 3000;) //一秒钟内不停扫描GPS信息
{
while (Serial_Gps.available()) //串口获取到数据开始解析
{
char c = Serial_Gps.read(); //读取一个字节获取的数据
switch(c) //判断该字节的值
{
case '$': //若是$,则说明是一帧数据的开始
Serial_Gps.readBytesUntil('*', nmeaSentence, 67); //读取接下来的数据,存放在nmeaSentence字符数组中,最大存放67个字节
//Serial_Gps.println(nmeaSentence);
latitude_msg = parseGNRMcLat(nmeaSentence); //获取纬度值
longitude_msg = parseGNRMcLon(nmeaSentence);//获取经度值
lndSpeed = parseGNRMcSpeed(nmeaSentence);//获取速度值
gpsTime = parseGNRMcTime(nmeaSentence);//获取GPS时间
if(latitude_msg > "") //当不是空时候打印输出
{
//Serial.println("------------------------------------");
//Serial.println("latitude_msg: " + latitude_msg);
latitude_old=latitude_msg;
}
if(longitude_msg > "") //当不是空时候打印输出
{
//Serial.println("longitude_msg: " + longitude_msg);
longitude_old=longitude_msg;
}
if(lndSpeed > "") //当不是空时候打印输出
{
//Serial.println("Speed (knots): " + lndSpeed);
lndSpeed_old=lndSpeed;
}
if(gpsTime > "") //当不是空时候打印输出
{
//Serial.println("gpsTime: " + gpsTime);
beiJingTime = getBeiJingTime(gpsTime); //获取北京时间
//Serial.println("beiJingTime: " + beiJingTime);
beiJingTime_old=beiJingTime;
}
}//switch(c)
}// while
}//for
}
//char lon_str[] = "10845.55422";
//char lat_str[] = "3402.15704";
//String lon_str = "10845.55422";
//String lat_str = "3402.15704";
// double 转化 string
char* dtostr(char *strc, double d)
{
sprintf(strc, "%f", d);
return strc;
}
// GPS数据 mmmm格式 抓换位
double longitudeToOnenetFormat(String lons)
{
if (lons==""){return 0;}
double lon_temp = 0;
long lon_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lon_Onenet_double = 0;
//lon_temp = atof(lon_str); char[] char lon_str[] = "10845.55422";
lon_temp = (lons).toFloat();
lon_Onenet =lon_temp*100000; //转换为整数
dd_int = lon_Onenet/10000000; //取出dd
mm_int = lon_Onenet%10000000; //取出MM部分
lon_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lon_Onenet_double;
}
double latitudeToOnenetFormat(String lat_s)
{
if(lat_s==""){return 0;}
double lat_temp = 0;
long lat_Onenet = 0;
int dd_int = 0;
long mm_int = 0;
double lat_Onenet_double = 0;
//lat_temp = atof(lat_str); ///char lat_str[] = "3402.15704";
lat_temp = (lat_s).toFloat();
lat_Onenet =lat_temp*100000; //转换为整数
dd_int = lat_Onenet/10000000; //取出dd
mm_int = lat_Onenet%10000000; //取出MM部分
lat_Onenet_double = dd_int + (double)mm_int/60/100000;//换算为Onenet格式
return lat_Onenet_double;
}
// 紫外线等级转换
// 0-11+
int LightDengji(int light_mv){
int dengji=0; //紫外线等级
if(light_mv<50){ dengji=0; }
else if( light_mv>=50 && light_mv<227){ dengji=1; }
else if( light_mv>=227 && light_mv<318){ dengji=2; }
else if( light_mv>=318 && light_mv<408){ dengji=3; }
else if( light_mv>=408 && light_mv<503){ dengji=4; }
else if( light_mv>=503 && light_mv<606){ dengji=5; }
else if( light_mv>=606 && light_mv<696){ dengji=6; }
else if( light_mv>=696 && light_mv<795){ dengji=7; }
else if( light_mv>=795 && light_mv<881){ dengji=8; }
else if( light_mv>=881 && light_mv<976){ dengji=9; }
else if( light_mv>=976 && light_mv<1079){ dengji=10; }
else if( light_mv>=1079 && light_mv<1170){ dengji=11; }
else if( light_mv>=1170 ){ dengji=12; }
return dengji;
}
void setup() //初始化内容
{
Serial.begin(9600);
//pinMode(pin_light, INPUT);
Serial_esp.begin(115200); //定义波特率9600,
Serial_Gps.begin(9600); //定义波特率9600,
Serial.println("开始运行");
latitude_msg="0"; //纬度
longitude_msg="0"; //经度
lndSpeed="0"; //速度
gpsTime="0"; //UTC时间,本初子午线经度0度的时间,和北京时间差8小时
beiJingTime="0"; //北京时间
}
char lonc[25] ;
char latc[25] ;
void loop() //主循环
{
Get_Gps();
int light_svalue=analogRead(pin_light);
float light_value=light_svalue*5000/1023.0;
float tem=float(ds.getTempC());
double lond=longitudeToOnenetFormat(longitude_old);
double latd=latitudeToOnenetFormat(latitude_old);
//dtostr(lonc,lons);
//dtostr(latc,lats);
String lons= String(lond,6);
String lats= String(latd,6);
//Serial.print(lats); Serial.print(" "); Serial.println(lons);
String showmsg=String()
+String("纬度")+"-"
+String(lats)+"-"
+String("经度")+"-"
+String(lons)+"-"
+String("速度")+"-"
+String(lndSpeed_old)+"-"
+String("北京时间戳秒")+"-"
+String(beiJingTime_old)+"-"
+String("紫外线mv")+"-"
+String((light_value))+"-"
+String("紫外线等级")+"-"
+String(LightDengji(light_value))+"-"
+String("温度")+"-"
+String(ds.getTempC())+"-"
;
Serial.println(showmsg);
String msg=String()
+String(lats)+"-"
+String(lons)+"-"
+String(lndSpeed_old)+"-"
+String(beiJingTime_old)+"-"
+String(LightDengji(light_value))+"-"
+String(ds.getTempC())+"-"
;
Serial_esp.println(msg);
delay(1000);
}//loop()
API_Gps.h
String getBeiJingTime(String s)
{
int hour = s.substring(0,2).toInt();
int minute = s.substring(2,4).toInt();
int second = s.substring(4,6).toInt();
hour += 8;
if(hour > 24)
hour -= 24;
s = String(hour) + String(minute) + String(second);
return s;
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Latitude
String parseGNRMcLat(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lat;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 5; i++)
{
if(i < 3)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 3, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
if(i == 3)
{
lEndLoc = s.indexOf(',', pLoc+1);
lat = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 3, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
else
{
dEndLoc = s.indexOf(',', lEndLoc+1);
// lat = lat + " " + s.substring(lEndLoc+1, dEndLoc);
/*Serial.print("i = 4, lEndLoc: ");
Serial.println(lEndLoc);
Serial.print("dEndLoc: ");
Serial.println(dEndLoc);*/
}
}
return lat;
}
//}
//}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcLon(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lon;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 7; i++)
{
if(i < 5)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 3, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
if(i == 5)
{
lEndLoc = s.indexOf(',', pLoc+1);
lon = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 3, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
else
{
dEndLoc = s.indexOf(',', lEndLoc+1);
// lon = lon + " " + s.substring(lEndLoc+1, dEndLoc);
/*Serial.print("i = 4, lEndLoc: ");
Serial.println(lEndLoc);
Serial.print("dEndLoc: ");
Serial.println(dEndLoc);*/
}
}
return lon;
}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcSpeed(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String lndSpeed;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 8; i++)
{
if(i < 7)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 8, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
else
{
lEndLoc = s.indexOf(',', pLoc+1);
lndSpeed = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 8, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
}
return lndSpeed;
}
}
//Parse GNRMC NMEA sentence data from String
//String must be GNRMC or no data will be parsed
//Return Longitude
String parseGNRMcTime(String s)
{
int pLoc = 0; //paramater location pointer
int lEndLoc = 0; //lat parameter end location
int dEndLoc = 0; //direction parameter end location
String gpsTime;
/*make sure that we are parsing the GNRMC string.
Found that setting s.substring(0,5) == "GNRMC" caused a FALSE.
There seemed to be a 0x0D and 0x00 character at the end. */
if(s.substring(0,4) == "GNRM")
{
//Serial.println(s);
for(int i = 0; i < 2; i++)
{
if(i < 1)
{
pLoc = s.indexOf(',', pLoc+1);
/*Serial.print("i < 8, pLoc: ");
Serial.print(pLoc);
Serial.print(", ");
Serial.println(i);*/
}
else
{
lEndLoc = s.indexOf(',', pLoc+1);
gpsTime = s.substring(pLoc+1, lEndLoc);
/*Serial.print("i = 8, pLoc: ");
Serial.println(pLoc);
Serial.print("lEndLoc: ");
Serial.println(lEndLoc);*/
}
}
return gpsTime;
}
}
// Turn char[] array into String object
String charToString(char *c)
{
String val = "";
for(int i = 0; i <= sizeof(c); i++)
{
val = val + c;
}
return val;
}



浙公网安备 33010602011771号