• ARDUINO使用GPRS发送GPS数据到OneNet测试


    功能:

    测试把固定的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("
    setup 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
    ");
        if (sendCommand(send_buf, "CONNECT", 10000, 5) == Success);
        else GPRS_ERROR(7);
    
        //发送数据
        if (sendCommand("AT+CIPSEND
    ", ">", 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
    ");//注意后面必须加上
    
        strcat(send_buf,"api-key:");
        strcat(send_buf,API_VALUE_temp);
        strcat(send_buf,"
    ");
        strcat(send_buf,"Host:");
        strcat(send_buf,OneNetServer);
        strcat(send_buf,"
    ");
        sprintf(tmp,"Content-Length:%d
    
    ", 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
    ", "CLOSE OK", 3000, 1) == Success);
        else GPRS_ERROR(11);
    
        if (sendCommand("AT+CIPSHUT
    ", "SHUT OK", 3000, 1) == Success);
        else GPRS_ERROR(11);
    }
    
    void initGprs()
    {
        if (sendCommand("AT
    ", "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?
    ", "+CREG: 0,1", 3000, 10) == Success);
        else GPRS_ERROR(2);
    
        if (sendCommand("AT+CGCLASS="B"
    ", "OK", 3000, 2) == Success);
        else GPRS_ERROR(3);
    
        if (sendCommand("AT+CGDCONT=1,"IP","CMNET"
    ", "OK", 3000, 2) == Success);
        else GPRS_ERROR(4);
    
        if (sendCommand("AT+CGATT=1
    ", "OK", 3000, 2) == Success);
        else GPRS_ERROR(5);
    
        if (sendCommand("AT+CLPORT="TCP","2000"
    ", "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
    ", "OK", 100, 10) == Success)
            {
                DebugSerial.print("
    RESET!!!!!!
    ");
                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("
    ---------send AT Command:---------
    ");
            DebugSerial.write(Command);
    
            GprsSerail.write(Command);
    
            Time_Cont = 0;
            while (Time_Cont < Timeout)
            {
                gprsReadBuffer();
                if(strstr(gprsRxBuffer, Response) != NULL)
                {
                    DebugSerial.print("
    ==========receive AT Command:==========
    ");
                    DebugSerial.print(gprsRxBuffer); //输出接收到的信息
                    clrGprsRxBuffer();
                    return Success;
                }
            }
            Time_Cont = 0;
        }
        DebugSerial.print("
    ==========receive AT Command:==========
    ");
        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;
    }
    
  • 相关阅读:
    Vi 和 Vim
    The C Programming Language-Chapter 5 Pointers and Arrays
    C# 4.0开始,泛型接口和泛型委托都支持协变和逆变
    数据库中的锁 and java StampedLock ReadWriteLock
    NetCore and ElasticSearch 7.5
    网关项目 ReverseProxy
    异常捕获&打印异常信息
    刷新:重新发现.NET与未来
    2019 中国.NET 开发者峰会正式启动
    .NET开发者必须学习.NET Core
  • 原文地址:https://www.cnblogs.com/Mysterious/p/5907125.html
Copyright © 2020-2023  润新知