arduino core for ESP8266接入OneNET+SPIFFS+HTTPserver-Arduino中文社区 - Powered by Discuz! Archiver

robert_jw 发表于 2016-2-15 09:16

arduino core for ESP8266接入OneNET+SPIFFS+HTTPserver

本帖最后由 robert_jw 于 2016-2-15 10:20 编辑




摸索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的相关信息:


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



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



实物连接图如下:


step 3:软件编写 源代码如下:
arduino主程序#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);    //串口发送
    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, 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 == 0x20 && rcv_pkt.data == 0x00 && rcv_pkt.data == 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;//根据EDP协议,byte为数据包类型
      switch (pkt_type)
      {
          case CMDREQ:      //命令请求
            char edp_command;
            char edp_cmd_id;
            int32 id_len, cmd_len, rm_len;
            char datastr;
            char val;
            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:
            //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;
      char humi_val;

      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文件共同编译,代码如下:
#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;
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 = tmp;
    remaining_count++;
} while (len_val > 0 && remaining_count < 5);

return remaining_count;
}

/*
* writeByte
* 向EDP包中写入一个字节
*/
int16 writeByte(edp_pkt* pkt, int8 byte)
{
pkt->data = 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;
}

/*
* 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;
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 systemESP8266FS 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:
<!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>environmental.monitor.log@gmail.com<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文件,即为登陆界面:


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

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




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



在SSID,和PASS栏中输入,模块需要连接的WIFI热点,API_KEY和DEV_ID分别为设备对应的参数,点击config,之后ESP8266会进行重启,在串口上会看到一些调试信息,如下所示:
在OneNET平台上,在对应的设备下可以看到已经连接的状态,同时会有温湿度的数据流数据产生:



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

lzbpli 发表于 2016-2-15 09:44

强!!!!!!!!!!!!!!!

cavy 发表于 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"

cavy 发表于 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 ...

找到了:lol

cavy 发表于 2016-2-17 22:38

本帖最后由 cavy 于 2016-2-18 16:38 编辑

这次真的烧录成功 谢谢楼主但config.txt文件和index.html文件;不知道怎么烧进去

cavy 发表于 2016-2-17 22:39

终于烧录成功了 但烧了就像没烧前一样 连wifi名字都没改变其他功能更加没看到不知道哪里错了.......楼主 还有哪里要注意啊:(

cavy 发表于 2016-2-18 17:57

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

哦 又看了一次楼主的教程 html烧进去了
但打开196.168.0.1后 输入密码后 按 config 8266并没有反应 今晚我再看看代码

robert_jw 发表于 2016-2-19 09:12

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

没有反应,串口打印为什么内容呢?

cavy 发表于 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 串口就什么都没收到

电子情 发表于 2016-2-20 16:09

怎么在浏览器中写好配置信息按 config 没有反应
页: [1] 2 3 4
查看完整版本: arduino core for ESP8266接入OneNET+SPIFFS+HTTPserver