查看: 25698|回复: 29

arduino core for ESP8266接入OneNET+SPIFFS+HTTPserver

[复制链接]
  • TA的每日心情
    开心
    2016-2-15 10:40
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2016-2-15 09:16 | 显示全部楼层 |阅读模式
    本帖最后由 robert_jw 于 2016-2-15 10:20 编辑

    无标题.png


    摸索ESP8266一段时间了,偶然间在网上发现了一个开源项目,在arduino IDE中,添加ESP8266的库,就可以实现利用arduino环境来对ESP8266进行固件开发的功能,利用其提供的wifi API,就可以很方便的进行物联网设备接入的开发了。同时,该项目还提供了文件系统工具,这样就可以实现配置参数的保存的功能。
    项目地址: https://github.com/esp8266/Arduino下面我们将搭建开发环境,并利用该环境,通过WIFI 热点连接OneNET,搭建一个物联网设备原型。
    step 1:搭建开发环境
    硬件环境:ESP8266-01模块(如上图)
    软件环境:arduino IDE 1.6.7
    在GIT ( https://github.com/esp8266/Arduino )上有如何搭建并使用整个环境的详细文档,这里我们只做简单描述。
    打开Arduino IDE,点击 文件->首选项 ,在“附加开发板管理器网址”一栏输入 http://wechat.doit.am/package_esp8266com_index.json 点击确认,重启arduino IDE,选择工具->开发板xxx->开发板管理器,可以在看到关于esp8266的相关信息:
    PPF2D8{Q28A$NK2IG6{)_6U.jpg

    点击安装,等待安装完成。重启arduino IDE后,设置 工具-> 开发板xxx -> Generic ESP8266 Module
    开发板设置.png


    step 2:硬件连接
    由于ESP8266-01只有2个可以使用的GPIO管脚,所以我们这里只实现一个简单的功能,GPIO2用来采集DHT11温湿度传感器的数值,而GPIO0用来控制发光二极管的开关。
    连接框图如下所示:
    8266 dht.png


    实物连接图如下:
    实物连接.jpg

    step 3:软件编写
    源代码如下:
    arduino主程序
    [C] 纯文本查看 复制代码
    #include <ESP8266WiFi.h>
    #include <ESP8266WiFiMulti.h>
    #include <WiFiClient.h>
    #include <WiFiClientSecure.h>
    #include <WiFiServer.h>
    #include <WiFiUdp.h>
    #include "FS.h"
    #include "DHT.h"
    #include "edp.c"
    
    #define CONFIG_FILE  "/config.txt"    //config info about ssid & password & api-key & dev_id
    
    #define BUILTIN_LED1 0 //GPIO0 control led
    #define DHTPIN 2       //GPIO2 -> DHT11
    #define DHTTYPE DHT11
    
    #define PUSH_ID NULL
    #define SERVER  "jjfaedp.hedevice.com"           //EDP server
    #define PORT    876
    
    char servername[] = "jjfaedp.hedevice.com"; // remote server we will connect to
    
    String ssid = "", pass = "", key = "", id = "";
    static boolean tcpConnected = false, edpConnected = false, wifiConnected = false;
    
    IPAddress apIP(192, 168, 0, 1);     //AP ip address
    WiFiClient client;    //connect to EDP server
    WiFiClient client1;   //connected by webclient
    WiFiServer server(80); //HTTP server for configuration
    
    DHT dht(DHTPIN, DHTTYPE);// Initialize DHT sensor.
    
    /*
     *   packetSend: 发送包
     */
    void packetSend(edp_pkt* pkt)
    {
      int16 len = pkt->len;
      int16 i = 0;
      if (pkt != NULL)
      {
        //client.write(pkt->data, pkt->len);    //串口发送
        while (len--) client.write(pkt->data[i++]);    //串口发送
        free(pkt);              //回收内存
      }
    }
    
    /*
     *  rcvDebug: 将接受数据按照十六进制打印
     */
    void rcvDebug(unsigned char *rcv, int len)
    {
      int i;
    
      Serial.print("rcv len: ");
      Serial.println(len, DEC);
      for (i = 0; i < len; i++)
      {
        Serial.print(rcv[i], HEX);
        Serial.print(" ");
      }
      Serial.println("");
    }
    
    /*
     * readTempHumi: 调用库函数,读取DHT11的温度和湿度值
     */
    boolean readTempHumi(uint32 *temp, uint32 *humi)
    {
      // Reading temperature or humidity takes about 250 milliseconds!
      // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
      float h = dht.readHumidity();
      // Read temperature as Celsius (the default)
      float t = dht.readTemperature();
    
      // Check if any reads failed and exit early (to try again).
      if (isnan(h) || isnan(t))
      {
        Serial.println("Failed to read from DHT sensor!");
        return false;
      }
    
      *temp = (uint32)t;
      *humi = (uint32)h;
      //  Serial.print("Humidity: ");
      //  Serial.print(h);
      //  Serial.print(" %\t");
      //  Serial.print("Temperature: ");
      //  Serial.print(t);
      //  Serial.println(" *C ");
    
      return true;
    }
    
    /*
        readEdpPkt
        从串口缓存中读数据到接收缓存
    */
    bool readEdpPkt(edp_pkt *p)
    {
      int tmp;
      if ((tmp = client.readBytes(p->data + p->len, sizeof(p->data))) > 0 )
      {
        rcvDebug(p->data + p->len, tmp);
        p->len += tmp;
      }
      return true;
    }
    
    
    /*
     * rsStart: 启动文件系统,打印当前保存的参数值
     */
    void fsStart()
    {
      if (SPIFFS.begin())
      {
        Serial.println("FS mounted.");
        if (SPIFFS.exists(CONFIG_FILE))
        {
          Serial.println("/config.txt exist.");
          File f = SPIFFS.open(CONFIG_FILE, "r+");
          if (!f) {
            Serial.println("file open failed");
          }
          else { //print file's content
            String config;
            int iStart = 0, iEnd = 0;
            while (f.available()) config = f.readString();
            f.close();
    
            /* 数据内容以 ssid,pass,key,id,的形式保存*/
            /* 以逗号为分隔符,读取各部分信息 */
            iEnd = config.indexOf(",");
            ssid = config.substring(iStart, iEnd);
            iStart = iEnd + 1;
    
            iEnd = config.indexOf(",", iStart);
            pass = config.substring(iStart, iEnd);
            iStart = iEnd + 1;
    
            iEnd = config.indexOf(",", iStart);
            key = config.substring(iStart, iEnd);
            iStart = iEnd + 1;
    
            iEnd = config.indexOf(",", iStart);
            id = config.substring(iStart, iEnd);
    
            Serial.println("!!!!!!!!!");
            Serial.println(ssid);
            Serial.println(pass);
            Serial.println(key);
            Serial.println(id);
          }
    
        }
        else
          Serial.println("/test.txt not exist.");
      }
      else
        Serial.println("FS mount error");
    }
    
    /*
     * WiFiStart:根据读文件系统中的参数,连接到wifi热点
     *            并且自身作为wifi热点存在,其ssid为“DHTMonitor http://192.168.0.1”
     *            IP地址为apIP:192.168.0.1
     */
    void WiFiStart()
    {
      WiFi.mode(WIFI_AP_STA);
      WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
      WiFi.softAP("DHTMonitor http://192.168.0.1");  //name
    
      Serial.println("softAP: DHTMonitor http://192.168.0.1");
      Serial.print("Connecting to ");
      Serial.println(ssid);
    
      WiFi.begin(ssid.c_str(), pass.c_str());  //配置连接的wifi热点
    
      uint32 time = millis() + 10000;  //10s to connect
      while (WiFi.status() != WL_CONNECTED && millis() < time) {
        delay(500);
        Serial.print(".");
      }
    
      if ( millis() >=  time)  //overtime
      {
        Serial.println("");
        Serial.println("WiFi error");
      }
      else
      {
        wifiConnected = true;
        Serial.println("");
        Serial.println("WiFi connected");
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());
      }
    }
    
    
    void setup()
    {
      //ESP.wdtDisable();ESP.wdtEnable();ESP.wdtFeed().
      pinMode(BUILTIN_LED1, OUTPUT); // Initialize the BUILTIN_LED1 pin as an output
      Serial.begin(9600);
      delay(10);
      Serial.println();
      Serial.println();
    
      dht.begin();
      fsStart();
    
      /* We start by connecting to a WiFi network */
      WiFiStart();
    
      server.begin();
    }
    
    void loop()
    {
      uint32 temp, humi, tmp;
      static unsigned long time = 0, timeOld = 0;
      edp_pkt rcv_pkt;
      uint8 pkt_type;
    
      /* check wifi connection */
      if (WiFi.status() != WL_CONNECTED)
      {
        if (wifiConnected == true)
          Serial.println("wifi disconnected!");
        wifiConnected = false;
        tcpConnected = false;
        edpConnected = false;
      }
      else
        wifiConnected = true;
    
      /* TCP connect */
      if (wifiConnected)
      {
        if (!tcpConnected) client.connect(SERVER, PORT);  //connect to edp server
        if (!tcpConnected && client.connected())
        {
          Serial.print("connected to ");
          Serial.println((String)SERVER);
          tcpConnected = true;
        }
        else if (tcpConnected && !client.connected())  //check TCP connnection
        {
          Serial.print("disconnected to ");
          Serial.println((String)SERVER);
          tcpConnected = false;
          edpConnected = false;
        }
    
        //edp connect
        if (tcpConnected && !edpConnected)
        {
          while (client.available()) client.read(); //清空接收缓存
          packetSend(packetConnect(id.c_str(), key.c_str()));             //发送EPD连接包
          uint32 time = millis() + 5000;
          while (!client.available() && millis() < time);                 //等待EDP连接应答
          if ((tmp = client.readBytes(rcv_pkt.data, sizeof(rcv_pkt.data))) > 0 )
          {
            rcvDebug(rcv_pkt.data, tmp);
            if (rcv_pkt.data[0] == 0x20 && rcv_pkt.data[2] == 0x00 && rcv_pkt.data[3] == 0x00)
            {
              edpConnected = true;
              Serial.println("EDP connected.");
            }
            else
              Serial.println("EDP connect error.");
          }
          else
            Serial.println("EDP connect no response.");
          packetClear(&rcv_pkt);
        }
    
        /* rcv & do EDP command  */
        while (client.available())
        {
          readEdpPkt(&rcv_pkt);
          if (isEdpPkt(&rcv_pkt))
          {
            pkt_type = rcv_pkt.data[0];  //根据EDP协议,byte[0]为数据包类型
            switch (pkt_type)
            {
              case CMDREQ:        //命令请求
                char edp_command[50];
                char edp_cmd_id[40];
                int32 id_len, cmd_len, rm_len;
                char datastr[20];
                char val[10];
                char *p;
    
                memset(edp_command, 0, sizeof(edp_command));
                memset(edp_cmd_id, 0, sizeof(edp_cmd_id));
                edpCommandReqParse(&rcv_pkt, edp_cmd_id, edp_command, &rm_len, &id_len, &cmd_len);
                Serial.print("rm_len: ");
                Serial.println(rm_len, DEC);
                Serial.print("id_len: ");
                Serial.println(id_len, DEC);
                Serial.print("cmd_len: ");
                Serial.println(cmd_len, DEC);
                Serial.print("id: ");
                Serial.println(edp_cmd_id);
                Serial.print("cmd: ");
                Serial.println(edp_command);
    
                //数据处理与应用中EDP命令内容对应
                //本例中格式为  datastream:[1/0]
                //sscanf(edp_command, "%[^:]:%s", datastr, val);
                p = strstr(edp_command, ":");
                *p = '\0';
                p++;
                strcpy(datastr, edp_command);
                strcpy(val, p);
                if (atoi(val) == 1)
                  digitalWrite(BUILTIN_LED1, HIGH);   // 使Led亮
                else
                  digitalWrite(BUILTIN_LED1, LOW);   // 使Led灭
    
                packetSend(packetDataSaveTrans(NULL, datastr, val)); //将新数据值上传至数据流
                break;
              default:
                Serial.print("unknown type: ");
                Serial.println(pkt_type, HEX);
                break;
            }
          }
        }
        if (rcv_pkt.len > 0)
          packetClear(&rcv_pkt);
    
        /* 每10s采集一次温湿度  */
        time = millis() / 10000;  //every 10s
        if (time != timeOld)
        {
          timeOld = time;
          if (readTempHumi(&temp, &humi))
          {
    Serial.print("temp: ");
    Serial.print(temp);
    Serial.print("\thumi: ");
    Serial.println(humi);
            char temp_val[10];
            char humi_val[10];
    
            sprintf(temp_val, "%d", temp);
            sprintf(humi_val, "%d", humi);
            if (edpConnected)
            {
              packetSend(packetDataSaveTrans(NULL, "temp", temp_val));
              packetSend(packetDataSaveTrans(NULL, "humi", humi_val));
            }
          }
        }
      }
    
      /* web server */
      client1 = server.available();
      if (client1)
      {
        Serial.println("new client connected!");
        unsigned long ultimeout = millis() + 250;
        while (!client1.available() && (millis() < ultimeout) )
        {
          delay(1);
        }
        if (millis() > ultimeout)
        {
          Serial.println("overtime!");
          return;
        }
        String sRequest = client1.readStringUntil('\r');
        client1.flush();
    
        if (sRequest == "")
        {
          client1.stop();
          Serial.println("client1 stop!");
          return;
        }
        Serial.println(sRequest);
    
        String sPath = "", sParam = "", sCmd = "";
        String sGetstart = "GET ";
        int iStart, iEndSpace, iEndQuest;
        iStart = sRequest.indexOf(sGetstart);
        if (iStart >= 0)
        {
          iStart += +sGetstart.length();
          iEndSpace = sRequest.indexOf(" ", iStart);
          iEndQuest = sRequest.indexOf("?", iStart);
          if (iEndSpace > 0)
          {
            if (iEndQuest > 0)
            {
              sPath  = sRequest.substring(iStart, iEndQuest);
              sParam = sRequest.substring(iEndQuest, iEndSpace);
              Serial.println("Returned Web Path  ");   // Use this to Verify the actions on returned data
              Serial.println(sPath);
              Serial.println("Returned Parameters");
              Serial.println(sParam);
            }
            else
            {
              sPath  = sRequest.substring(iStart, iEndSpace);
              Serial.println("Returned Web Path  ");    // Use this to Verify the actions on returned data
              Serial.println(sPath);
            }
          }
    
          //参数配置,GET /para_inputs&ssid=1&pass=2&id=3&key=4&nocache=888.694
          if (sPath.startsWith("/para_inputs"))
          {
            int iStart = 0, iEnd;
            String ssid_tmp = "", pass_tmp = "", key_tmp = "", id_tmp = "", para = "";
            iStart = sPath.indexOf("=", iStart) + 1;
            iEnd = sPath.indexOf("&", iStart);
            ssid_tmp = sPath.substring(iStart, iEnd);
    
            iStart = sPath.indexOf("=", iStart) + 1;
            iEnd = sPath.indexOf("&", iStart);
            pass_tmp = sPath.substring(iStart, iEnd);
    
            iStart = sPath.indexOf("=", iStart) + 1;
            iEnd = sPath.indexOf("&", iStart);
            key_tmp = sPath.substring(iStart, iEnd);
    
            iStart = sPath.indexOf("=", iStart) + 1;
            iEnd = sPath.indexOf("&", iStart);
            id_tmp = sPath.substring(iStart, iEnd);
    
            //        Serial.println("!!!!!!!!!");
            //        Serial.println(ssid_tmp);
            //        Serial.println(pass_tmp);
            //        Serial.println(key_tmp);
            //        Serial.println(id_tmp);
    
            if (ssid_tmp != "")
              para += ssid_tmp;
            else
              para += ssid;
            para += ",";
            if (pass_tmp != "")
              para += pass_tmp;
            else
              para += pass;
            para += ",";
            if (key_tmp != "")
              para += key_tmp;
            else
              para += key;
            para += ",";
            if (id_tmp != "")
              para += id_tmp;
            else
              para += id;
            para += ",";
    
            /* 保存新参数然后重启 */
            if (ssid_tmp != "" | pass_tmp != "" | key_tmp != "" | id_tmp != "")
            {
              File f = SPIFFS.open(CONFIG_FILE, "r+");
              f.print(para);
              f.close();
              Serial.println("save parameters!");
              ESP.reset();
            }
          }
    
          else if (sPath == "/")    //客户端输入了 192.168.0.1 发送 GET / 报文
          {
            // send rest of HTTP header
            client1.println("HTTP/1.1 200 OK");
            client1.println("Content-Type: text/html");
            client1.println("Connection: keep-alive");
            client1.println();
            // send web page
            File webFile = SPIFFS.open("/index.html", "r");        // open web page file
            if (webFile)
            {
              while (webFile.available())  client1.print(webFile.readString()); // send web page to client
              webFile.close();
            }
            else
              Serial.println("open html error!");
            Serial.println("Send html file");
            delay(1);
          }
        }
        client1.stop();
      }
    }


    其中,需要edp.c文件共同编译,代码如下:
    [C] 纯文本查看 复制代码
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "arduino.h"
    
    #define CONNREQ             0x10
    #define CONNRESP            0x20
    #define PUSHDATA            0x30
    #define SAVEDATA            0x80
    #define SAVEACK             0x90
    #define CMDREQ              0xA0
    #define CMDRESP             0xB0
    #define PINGREQ             0xC0
    #define PINGRESP            0xD0
    #define ENCRYPTREQ          0xE0
    #define ENCRYPTRESP         0xF0
    
    #define MAX_LEN                                200
    #define PROTOCOL_NAME       "EDP"
    #define PROTOCOL_VERSION    1
    
    //typedef unsigned char   uint8;
    //typedef char            int8;
    //typedef unsigned int    uint16;
    typedef int             int16;
    //typedef unsigned long   uint32;
    //typedef long            int32;
    
    typedef struct
    {
      uint8 data[MAX_LEN];
      int16 len;
      int16 read_p;
    } edp_pkt;
    
    
    /*
     * packetCreate
     * 创建一个EDP包缓存空间
     */
    edp_pkt *packetCreate(void)
    {
      edp_pkt *p;
    
      if((p = (edp_pkt *)malloc(sizeof(edp_pkt))) != NULL)
        memset(p, 0, sizeof(edp_pkt));
      return p;
    }
    
    /*
     * writeRemainlen
     * 向EDP包中写入剩余长度字段
     * len_val: 剩余长度的值
     */
    int8 writeRemainlen(edp_pkt* pkt, int16 len_val)
    {
      int8 remaining_count = 0;
      int8 tmp = 0;
    
      do {
        tmp = len_val % 128;
        len_val = len_val / 128;
        /* If there are more digits to encode, set the top bit of this digit */
        if (len_val > 0) {
          tmp = tmp | 0x80;
        }
        pkt->data[pkt->len++] = tmp;
        remaining_count++;
      } while (len_val > 0 && remaining_count < 5);
    
      return remaining_count;
    }
    
    /*
     * writeByte
     * 向EDP包中写入一个字节
     */
    int16 writeByte(edp_pkt* pkt, int8 byte)
    {
      pkt->data[pkt->len++] = byte;
      return 0;
    }
    
    /*
     * writeBytes
     * 向EDP包中写入多个字节
     */
    int16 writeBytes(edp_pkt* pkt, const void* bytes, int16 count)
    {
      memcpy(pkt->data + pkt->len, bytes, count);
      pkt->len += count;
      return 0;
    }
    
    
    /*
     * writeStr
     * 向EDP包中写入字符串字段
     * 首先写入两个字节的长度,随后紧跟字符串内容
     */
    int16 writeStr(edp_pkt* pkt, const char* str)
    {
      short len = strlen(str);
    
      writeByte(pkt, len >> 8);
      writeByte(pkt, len & 0x00ff);
    
      memcpy(pkt->data + pkt->len, str, len);
      pkt->len += len;
      return 0;
    }
    
    
    /*---------------------------------------------------------------------------*/
    /*
     * readUint8
     * 从EDP包中读出一个字节
     */
    uint8 readUint8(edp_pkt* pkt)
    {
      return pkt->data[pkt->read_p++];
    }
    
    /*
     * readUint16
     * 从EDP包中读出16bit的字段
     */
    uint16 readUint16(edp_pkt* pkt)
    {
      uint16 tmp;
      uint8 msb, lsb;
      
      msb = readUint8(pkt);
      lsb = readUint8(pkt);
    
      tmp = (msb<<8) | lsb;
      return tmp;
    }
    
    /*
     * readUint32
     * 从EDP包中读出4个字节的字段
     */
    uint32 readUint32(edp_pkt* pkt)
    {
      uint32 tmp = 0;
      int i = 4;
    
      while (--i >= 0) 
      {
        tmp <<= 8;
        tmp |= readUint8(pkt);
      }
      return tmp;
    }
    
    /*
     * readStr
     * 根据长度,从EDP包中读出字符串数据
     * len : 字符串的长度
     */
    void readStr(edp_pkt* pkt, char* str, uint16 len)
    {
      memcpy(str, pkt->data + pkt->read_p, len);
      pkt->read_p += len;
    }
    
    /*
     * readRemainlen
     * 从EDP包中读出剩余长度
     */
    int32 readRemainlen(edp_pkt* pkt)
    {
      uint32 multiplier = 1;
      uint32 len_len = 0;
      uint8 onebyte = 0;
      int32 len_val = 0;
      do 
      {
        onebyte = readUint8(pkt);
    
        len_val += (onebyte & 0x7f) * multiplier;
        multiplier *= 0x80;
    
        len_len++;
        if (len_len > 4) 
        {
          return -1; /*len of len more than 4;*/
        }
      } while((onebyte & 0x80) != 0);
      return len_val;
    }
    
    /*
     * packetConnect:组EDP连接包
     * 首先创建EDP缓存空间,按照EDP协议组EDP连接包
     * 分配的内存需要在发送之后free掉
     * devid: 设备id
     * key:APIKey
     */
    edp_pkt *packetConnect(const char* devid, const char* key)
    {
      int32 remainlen;
      edp_pkt* pkt;
      
      if((pkt = packetCreate()) == NULL)
        return NULL;
      
      /* msg type */
      writeByte(pkt, CONNREQ);
      /* remain len */
      remainlen = (2 + 3) + 1 + 1 + 2 + (2 + strlen(devid)) + (2 + strlen(key));
      writeRemainlen(pkt, remainlen);
      /* protocol desc */
      writeStr(pkt, PROTOCOL_NAME);
      /* protocol version */
      writeByte(pkt, PROTOCOL_VERSION);
      /* connect flag */
      writeByte(pkt, 0x40);
      /* keep time */
      writeByte(pkt, 0);
      writeByte(pkt, 0x80);
    
      /* DEVID */
      writeStr(pkt, devid);
      /* auth key */
      writeStr(pkt, key);
      
      return pkt;
    }
    
    
    /*
     * packetDataSaveTrans:组EDP数据存储转发包
     * 首先创建EDP缓存空间,按照EDP协议组EDP数据存储转发包
     * 分配的内存需要在发送之后free掉
     * devid: 设备id
     * streamId:数据流ID,即数据流名
     * val: 字符串形式的数据值
     */
    edp_pkt *packetDataSaveTrans(const char* destId, const char* streamId, const char *val)
    {
      int32 remainlen;
      char tmp[200];
      int16 str_len;
      edp_pkt *pkt;
      
      if((pkt = packetCreate()) == NULL)
        return pkt;
    
      /* 生成数据类型格式5的数据类型 */
      sprintf(tmp, ",;%s,%s", streamId, val);
      str_len = strlen(tmp);
    
      /* msg type */
      writeByte(pkt, SAVEDATA);
    
      if (destId != NULL)
      {
        /* remain len */
        remainlen = 1 + (2 + strlen(destId)) + 1 + (2 + str_len);
        writeRemainlen(pkt, remainlen);
        /* translate address flag */
        writeByte(pkt, 0x80);
        /* dst devid */
        writeStr(pkt, destId);
      }
      else
      {
        /* remain len */
        remainlen = 1 + 1 + (2 + str_len);
        writeRemainlen(pkt, remainlen);
        /* translate address flag */
        writeByte(pkt, 0x00);
      }
    
      /* json flag */
      writeByte(pkt, 5);
      /* json */
      writeStr(pkt, tmp);
      
      return pkt;
    }
    
    
    void packetClear(edp_pkt* pkt)
    {
      memset(pkt, 0, sizeof(edp_pkt));
    }
    
    
    /*
     * isEdpPkt
     * 按照EDP数据格式,判断是否是完整数据包
     */
    int16 isEdpPkt(edp_pkt* pkt)
    {
      uint32 data_len = 0;
      uint32 multiplier = 1;
      uint32 len_val = 0;
      uint32 len_len = 1;
      uint32 pkt_total_len = 0;
      uint8* pdigit;
    
      pdigit = pkt->data;
      data_len = pkt->len;
    
      if (data_len <= 1)
      {
        return 0;   /* continue receive */
      }
    
      do {
        if (len_len > 4)
        {
          return -1;  /* protocol error; */
        }
        if (len_len > data_len - 1)
        {
          return 0;   /* continue receive */
        }
        len_len++;
        pdigit++;
        len_val += ((*pdigit) & 0x7f) * multiplier;
        multiplier *= 0x80;
      } while (((*pdigit) & 0x80) != 0);
    
      pkt_total_len = len_len + len_val;
    
      /* receive payload */
      if (pkt_total_len == data_len)
      {
        return 1;   /* all data for this pkt is read */
      }
      else
      {
        return 0;   /* continue receive */
      }
    }
    
    
    /*
     * edpCommandReqParse
     * 按照EDP命令请求协议,解析数据
     */
    int edpCommandReqParse(edp_pkt* pkt, char *id, char *cmd, int32 *rmlen, int32 *id_len, int32 *cmd_len)
    {
      readUint8(pkt);     /* 包类型 */
      *rmlen = readRemainlen(pkt);    /* 剩余长度 */
      *id_len = readUint16(pkt);      /* ID长度 */
      readStr(pkt, id, *id_len);      /* 命令ID */
      *cmd_len = readUint32(pkt);     /* 命令长度 */
      readStr(pkt, cmd, *cmd_len);    /* 命令内容 */
    }
    
    
    /*
     * edpPushDataParse
     * 按照EDP透传数据格式,解析数据
     */
    int edpPushDataParse(edp_pkt* pkt, char *srcId, char *data)
    {
      uint32 remain_len;
      uint16 id_len;
      
      readUint8(pkt);     /* 包类型 */
      remain_len = readRemainlen(pkt);    /* 剩余长度 */
      id_len = readUint16(pkt);           /* 源ID长度 */
      readStr(pkt, srcId, id_len);    /* 源ID */
      readStr(pkt, data, remain_len - 2 - id_len);    /* 数据内容 */
    }
    


    接下来就是编译和烧写了,需要注意的是ESP8266模块,在烧写flash之前需要将GPIO_0接地才能进去正常的烧写模式,具体烧写方法请参考其他帖子。

    烧写完成之后,还有一个重要的工作,即烧写文件系统
    烧写方法如下:
    Uploading files to file system
    ESP8266FS is a tool which integrates into the Arduino IDE. It adds a menu item to Tools menu for uploading the contents of sketch data directory into ESP8266 flash file system.
    • Download the tool: https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.2.0/ESP8266FS-0.2.0.zip.
    • In your Arduino sketchbook directory, create tools directory if it doesn't exist yet
    • Unpack the tool into tools directory (the path will look like <home_dir>/Arduino/tools/ESP8266FS/tool/esp8266fs.jar)
    • Restart Arduino IDE
    • Open a sketch (or create a new one and save it)
    • Go to sketch directory (choose Sketch > Show Sketch Folder)
    • Create a directory named data and any files you want in the file system there
    • Make sure you have selected a board, port, and closed Serial Monitor
    • Select Tools > ESP8266 Sketch Data Upload. This should start uploading the files into ESP8266 flash file system. When done, IDE status bar will display SPIFFS Image Uploaded message

    GIT上提供了详尽的方法,请参阅 https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md ,
    本例中烧写的内容有两部分:
    一是config.txt文件,即参数保存与配置;
    二是index.html文件,即通过访问192.168.0.1,服务器传给终端的显示页面(类似与登陆路由器之后的登陆界面)。
    config.txt采用逗号将ssid / password / api-key / dev_id 分割开:
    本例中内容为:360,12345678,60ejo9FrV2328GndsKbQvPURzfYA,762767,

    index.html:
    [HTML] 纯文本查看 复制代码
    <!DOCTYPE html>
    <html lang="ch">
        <head>
            <meta charset="utf-8">
            <title>ESP8266 Management Terminal</title>
            <script>
    
            strLine1 = "";
            strLine2 = "";
            
            function SendText()
            {
                nocache = "&nocache=" + Math.random() * 1000000;
                var request = new XMLHttpRequest();
                
                strLine1 = "&ssid=" + document.getElementById("txt_form").SSID.value;
                strLine2 = "&pass=" + document.getElementById("txt_form").PASS.value;
                strLine3 = "&key=" + document.getElementById("txt_form").KEY.value;
                strLine4 = "&id=" + document.getElementById("txt_form").DEV_ID.value;
                
                request.open("GET", "para_inputs" + strLine1 + strLine2 + strLine3 + strLine4 + nocache, true);
                request.send(null);
            }
            </script>
      <body>
    <h1>ESP8266 Management Terminal<BR></h1>
        <body>
           <h1><FONT SIZE=-1>Enter text to config ESP8266:</h1>
            <form id="txt_form" name="frmText">
                <label>SSID    : <input type="text" name="SSID" size="32" maxlength="32" /></label><br /><br />
                <label>;PASS    : <input type="text" name="PASS" size="32" maxlength="32" /></label><br /><br />
                <label>API_KEY : <input type="text" name="KEY" size="32" maxlength="32" /></label><br /><br />
                <label>DEV_ID  : <input type="text" name="DEV_ID" size="32" maxlength="32" /></label>
            </form>
            <br />
            <input type="submit" value="config" />
    
    <font color="#000000"><body bgcolor="#d0d0f0"><meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"><BR>LCD Text Input<BR>
    <div style="clear:both;"><FONT SIZE=-1>[url=mailto:environmental.monitor.log@gmail.com]environmental.monitor.log@gmail.com[/url]<BR><FONT SIZE=-2>ESP8266 With 1602 I2C LCD, DS1307 and DHT22 Peripherals Logging to SPIFFS<BR>Compiled using ver. 1.6.5-1160-gef26c5f, built on Sep 30, 2015<BR></body></html>



    用浏览器打开该index.html文件,即为登陆界面:
    54$V03H@Z0[0XA%YC}4DH$R.png

    将文件系统烧写到flash中,重新上电之后便可以进行正常使用了;

    使用方法:
    1、打开手机WIFI,搜索附近热点,可以看到一个名为DHTMonitor http://192.168.0.1 的热点,这便是我们在软件中编辑好的热点名称,连接到该热点上:
    Screenshot_2016-02-15-09-29-39.jpeg



    打开手机浏览器,在地址栏中输入192.168.0.1(就像访问家里的路由器一样),即可以看到登陆界面:
    Screenshot_2016-02-15-09-27-42.jpeg


    在SSID,和PASS栏中输入,模块需要连接的WIFI热点,API_KEY和DEV_ID分别为设备对应的参数,点击config,之后ESP8266会进行重启,在串口上会看到一些调试信息,如下所示:
    LHZUIG`R1@UVDTJC$MG7T2J.png
    在OneNET平台上,在对应的设备下可以看到已经连接的状态,同时会有温湿度的数据流数据产生:
    27P@H$$%D)70C{}@Z1}9]Z8.png K0S(8%HANU(3_UXMT5]EK29.png


    可以利用应用编辑器中的开关控制LED灯,这里不再累述。具体控制方法参见代码部分和OneNET社区中的帖子:

    http://open.iot.10086.cn/bbs/topics/410

  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-17 17:38 | 显示全部楼层
    Arduino:1.6.7 (Windows 7), 开发板:"Generic ESP8266 Module, Serial, 80 MHz, 40MHz, DIO, 115200, 512K (64K SPIFFS), ck, Disabled, None"

    D:\Documents\Arduino\ESP8266__OneNET_SPIFFS_HTTPserver\ESP8266__OneNET_SPIFFS_HTTPserver.ino:8:17: fatal error: DHT.h: No such file or directory

    #include "DHT.h"

                     ^

    compilation terminated.

    exit status 1
    编译有误。

      报告将会包含更多的信息
      "在编译时,输出详细信息"
      在 文件>首选项 中启用

    怎么办 没有"DHT.h"
  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-17 22:28 | 显示全部楼层
    cavy 发表于 2016-2-17 17:38
    Arduino:1.6.7 (Windows 7), 开发板:"Generic ESP8266 Module, Serial, 80 MHz, 40MHz, DIO, 115200, 512K ...

    找到了
  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-17 22:38 | 显示全部楼层
    本帖最后由 cavy 于 2016-2-18 16:38 编辑

    这次真的烧录成功 谢谢楼主  但config.txt文件和index.html文件;不知道怎么烧进去
  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-17 22:39 | 显示全部楼层
    终于烧录成功了 但烧了就像没烧前一样 连wifi名字都没改变  其他功能更加没看到  不知道哪里错了.......楼主 还有哪里要注意啊
  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-18 17:57 | 显示全部楼层
    cavy 发表于 2016-2-17 22:38
    这次真的烧录成功 谢谢楼主  但config.txt文件和index.html文件;不知道怎么烧进去
    ...

    哦 又看了一次楼主的教程 html烧进去了
    但打开196.168.0.1后 输入密码后 按 config 8266并没有反应 今晚我再看看代码
  • TA的每日心情
    开心
    2016-2-15 10:40
  • 签到天数: 1 天

    [LV.1]初来乍到

     楼主| 发表于 2016-2-19 09:12 | 显示全部楼层
    cavy 发表于 2016-2-18 17:57
    哦 又看了一次楼主的教程 html烧进去了
    但打开196.168.0.1后 输入密码后 按 config 8266并没有反应 今晚 ...

    没有反应,串口打印为什么内容呢?
  • TA的每日心情
    开心
    2016-11-7 11:04
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-19 17:15 | 显示全部楼层
    robert_jw 发表于 2016-2-19 09:12
    没有反应,串口打印为什么内容呢?

    FS mounted.
    /config.txt exist.
    !!!!!!!!!
    1234567890
    123456789
    l6J3NMxrgJjOR52GbiO=Iw6O9Vw=
    768880
    softAP: DHTMonitor http://192.168.0.1
    Connecting to 1234567890
    ....................
    WiFi error      
    new client connected!                      //手机登陆192.168.0.1
    GET / HTTP/1.1
    Returned Web Path  
    /
    Send html file
    new client connected!
    client1 stop!
    new client connected!
    client1 stop!

    //填完账号密码按config 串口就什么都没收到  
  • TA的每日心情
    奋斗
    2017-3-26 20:34
  • 签到天数: 14 天

    [LV.3]偶尔看看II

    发表于 2016-2-20 16:09 | 显示全部楼层
    怎么在浏览器中写好配置信息按 config 没有反应
    打赏作者鼓励一下!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    Arduino IDE安装esp8266 SDK
    Arduino IDE安装esp8266 S
    使用Arduino IDE开发esp8266开发板 1.下载Arduino IDE 下载地址 2.打开Arduino IDE
    arduino SD卡识别不了
    arduino SD卡识别不了
    arduino版本为1.8.7 单片机是arduino uno 使用的程序为自带程序cardinf 连线开始弄错
    arduino sd卡读取后 后期数据处理的问题
    arduino sd卡读取后 后期
    测试内容:UNO板子+SD卡+时钟1302模块+自制传感器模块。实现采集到的数据储存到SD卡中
    求助!在使用Digispack Kickstarter做BadUSB时报错
    求助!在使用Digispack Ki
    如图 在编译时出现错误 [mw_shl_code=c,true]void setup() { Digispark.Keyboard vo
    arduino智能小车蓝牙控制系统
    arduino智能小车蓝牙控制
    蓝牙智能小车简介 智能小车主要可以分为 3 部分, 传感器部分、控制部分、执行部分。
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表