功能:
測試把固定的GPS數據發送到OneNet平台
調試途中碰到的問題
ARDUINO不支持sprintf的double打印,只能轉換為char字符串然后再%s打印
#include <TimerOne.h>
#define DebugSerial Serial
#define GprsSerail Serial3
#define Success 1U
#define Failure 0U
int L = 13; //LED指示燈引腳
unsigned long Time_Cont = 0; //定時器計數器
const unsigned int gprsRxBufferLength = 600;
char gprsRxBuffer[gprsRxBufferLength];
unsigned int gprsBufferCount = 0;
char OneNetServer[] = "api.heclouds.com"; //不需要修改
char device_id[] = "3225187"; //修改為自己的設備ID
char API_KEY[] = "R9xO5NZm6oVI4YBHvCPKEqtwYtMA"; //修改為自己的API_KEY
char sensor_gps[] = "location";
char lon_str[] = "11224.4992";
char lat_str[] = "3438.1633";
void setup() {
pinMode(L, OUTPUT);
digitalWrite(L, LOW);
DebugSerial.begin(9600);
GprsSerail.begin(9600);
Timer1.initialize(1000);
Timer1.attachInterrupt(Timer1_handler);
initGprs();
DebugSerial.println("\r\nsetup end!");
}
void loop() {
postGpsDataToOneNet(API_KEY,device_id,sensor_gps,lon_str,lat_str);
delay(5000);
}
double longitudeToOnenetFormat(char *lon_str_temp)
{
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_temp);
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(char *lat_str_temp)
{
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_temp);
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 postGpsDataToOneNet(char* API_VALUE_temp,char* device_id_temp,char* sensor_id_temp,char* lon_temp,char* lat_temp)
{
char send_buf[400]= {0};
char text[100] = {0};
char tmp[25] = {0};
char lon_str_end[15] = {0};
char lat_str_end[15] = {0};
dtostrf(longitudeToOnenetFormat(lon_temp),3,6, lon_str_end); //轉換成字符串輸出
dtostrf(latitudeToOnenetFormat(lat_temp),2,6, lat_str_end); //轉換成字符串輸出
//連接服務器
memset(send_buf, 0, 400); //清空
strcpy(send_buf, "AT+CIPSTART=\"TCP\",\"");
strcat(send_buf, OneNetServer);
strcat(send_buf, "\",80\r\n");
if (sendCommand(send_buf, "CONNECT", 10000, 5) == Success);
else GPRS_ERROR(7);
//發送數據
if (sendCommand("AT+CIPSEND\r\n", ">", 3000, 1) == Success);
else GPRS_ERROR(8);
memset(send_buf, 0, 400); //清空
/*准備JSON串*/
//ARDUINO平台不支持sprintf的double的打印,只能轉換到字符串然后打印
sprintf(text,"{\"datastreams\":[{\"id\":\"%s\",\"datapoints\":[{\"value\":{\"lon\":%s,\"lat\":%s}}]}]}"
,sensor_id_temp,lon_str_end,lat_str_end);
/*准備HTTP報頭*/
send_buf[0] = 0;
strcat(send_buf,"POST /devices/");
strcat(send_buf,device_id_temp);
strcat(send_buf,"/datapoints HTTP/1.1\r\n");//注意后面必須加上\r\n
strcat(send_buf,"api-key:");
strcat(send_buf,API_VALUE_temp);
strcat(send_buf,"\r\n");
strcat(send_buf,"Host:");
strcat(send_buf,OneNetServer);
strcat(send_buf,"\r\n");
sprintf(tmp,"Content-Length:%d\r\n\r\n", strlen(text));//計算JSON串長度
strcat(send_buf,tmp);
strcat(send_buf,text);
if (sendCommand(send_buf, send_buf, 3000, 1) == Success);
else GPRS_ERROR(9);
char sendCom[2] = {0x1A};
if (sendCommand(sendCom, "\"succ\"}", 3000, 1) == Success);
else GPRS_ERROR(10);
if (sendCommand("AT+CIPCLOSE\r\n", "CLOSE OK", 3000, 1) == Success);
else GPRS_ERROR(11);
if (sendCommand("AT+CIPSHUT\r\n", "SHUT OK", 3000, 1) == Success);
else GPRS_ERROR(11);
}
void initGprs()
{
if (sendCommand("AT\r\n", "OK", 3000, 10) == Success);
else GPRS_ERROR(1);
// 如果輸入 AT+CREG? <CR>則返回+CREG: <mode>, <stat> [ ,<lac>,<ci> ]
// 注: <mode>的值共有三個選項,分別是 0 or 1 or 2, 其中0 代表關閉網絡注冊結果
// 碼, 1 代表當網絡注冊狀態改變時激活網絡注冊結果碼, 2 代表激活網
// 絡注冊結果碼同時顯示區域和小區信息.
// <stat>的返回值共有三個,分別是 0, 1, 2,3,4,5 , 其中 0 代表沒有注冊網絡同時
// 模塊沒有找到運營商, 1代注冊到了本地網絡, 2 代表找到運營商但沒
// 有注冊網絡, 3 代表注冊被拒絕, 4 代表未知的數據, 5代表注冊在漫游
// 狀態.
// <lac>表示所屬網絡區域代碼,十六進制格式顯示,如: “ 279C”
// <ci>表示所屬網絡的小區 ID,十六進制格式顯示,如: “ 0EB2” Tech-Link T&E
if (sendCommand("AT+CREG?\r\n", "+CREG: 0,1", 3000, 10) == Success);
else GPRS_ERROR(2);
if (sendCommand("AT+CGCLASS=\"B\"\r\n", "OK", 3000, 2) == Success);
else GPRS_ERROR(3);
if (sendCommand("AT+CGDCONT=1,\"IP\",\"CMNET\"\r\n", "OK", 3000, 2) == Success);
else GPRS_ERROR(4);
if (sendCommand("AT+CGATT=1\r\n", "OK", 3000, 2) == Success);
else GPRS_ERROR(5);
if (sendCommand("AT+CLPORT=\"TCP\",\"2000\"\r\n", "OK", 3000, 2) == Success);
else GPRS_ERROR(6);
}
void(* resetFunc) (void) = 0; //制造重啟命令
void GPRS_ERROR(int num)
{
DebugSerial.print("ERROR");
DebugSerial.println(num);
while (1)
{
digitalWrite(L, HIGH);
delay(300);
digitalWrite(L, LOW);
delay(300);
if (sendCommand("AT\r\n", "OK", 100, 10) == Success)
{
DebugSerial.print("\r\nRESET!!!!!!\r\n");
resetFunc();
}
}
}
unsigned int sendCommand(char *Command, char *Response, unsigned long Timeout, unsigned char Retry)
{
clrGprsRxBuffer();
for (unsigned char n = 0; n < Retry; n++)
{
DebugSerial.print("\r\n---------send AT Command:---------\r\n");
DebugSerial.write(Command);
GprsSerail.write(Command);
Time_Cont = 0;
while (Time_Cont < Timeout)
{
gprsReadBuffer();
if(strstr(gprsRxBuffer, Response) != NULL)
{
DebugSerial.print("\r\n==========receive AT Command:==========\r\n");
DebugSerial.print(gprsRxBuffer); //輸出接收到的信息
clrGprsRxBuffer();
return Success;
}
}
Time_Cont = 0;
}
DebugSerial.print("\r\n==========receive AT Command:==========\r\n");
DebugSerial.print(gprsRxBuffer);//輸出接收到的信息
clrGprsRxBuffer();
return Failure;
}
void Timer1_handler(void)
{
Time_Cont++;
}
void gprsReadBuffer() {
while (GprsSerail.available())
{
gprsRxBuffer[gprsBufferCount++] = GprsSerail.read();
if (gprsBufferCount == gprsRxBufferLength)clrGprsRxBuffer();
}
}
void clrGprsRxBuffer(void)
{
memset(gprsRxBuffer, 0, gprsRxBufferLength); //清空
gprsBufferCount = 0;
}