简述

原来写了一个C++的wifi库但是发现用c++ arduino这小身板有点扛不住,代码比较大,使用String类型数据处理速度慢,而且很容易无缘无故跑飞。而且封装成库后使用还需要修改arduino的串口缓存大小才能使用。

今天抽空重新用c写了一下代码,运行速度明显加快,也不需要修改Arduino IDE了。本代码主要借鉴 中移物联-周家绪 的http头合成的库,和 DFRobot-Strictus 对AT指令数据处理的方法,在这里感谢两位发布的代码。

下面把测试成功的代码发不出来,供后来者使用。代码有不足之处欢迎指正。

最终效果

发布链接: http://open.iot.10086.cn/appview/p/aa8cb26e886d5c1238237604f155e2db

硬件概述

1.主控:ARDUINO MEGA2560开发板

特点:多个串口,IO口丰富,内存比较大,使用方便



2.WIFI模块:使用ARDUINO MEGA2560的带ESP8266的扩展板

特点:带有贴片的ESP8266 WIFI模块,DHT11温湿度传感器,继电器等功能,和ARDUINO MEGA2560即插即用,扩展很多IO和电源接口方便后续扩展各种传感器。



3.温湿度传感器:DHT11单总线温湿度传感器(扩展板带的有这个传感器)

软件思路

1.使用DHT11温湿度传感器的库<dht11.h>,读取温湿度值。

2.使用定时器<TimerOne.h>库,监控AT指令发送和获取返回数据的时间。

3.使用OneNet提供的<HttpPacket.h>库,合成POST请求的HTTP头

4.使用<ArduinoJson.h>库,合成需要的JSON数据流

5.使用ESP8266连接路由器将数据发送到OneNet服务器

用到的库文件下载地址:

链接:http://pan.baidu.com/s/1miJEIFI 密码:y8ks

传感器和硬件的对应接口

ESP8266 ---> Serial3(TX3/RX3) 用户发送和读取WIFI指令

DHT11 ---> D8 单总线读取温湿度数据值

DEBUG接口---> Serial(D0/D1) 1.把发送给ESP8266的数据,也在DEBUG串口输出,观看指令运行到哪一步,2.ESP8266接收的数据,也通过DEBUG口转发出来,观看反馈数据是否正确。 3.错误跳转,观看错误发生的位置

串口反馈数据界面

源代码(使用ARDUINO IDE 1.06版本测试)

#include <TimerOne.h>
#include <HttpPacket.h>
#include <ArduinoJson.h>
#include <dht11.h>
dht11 DHT11;
#define DHT11PIN 8 //DHT11 连接ARDUINO 8 HttpPacketHead packet; #define DebugSerial Serial
#define ESP8266Serail Serial3 #define Success 1U
#define Failure 0U int L = 13; //LED指示灯引脚 unsigned long Time_Cont = 0; //定时器计数器 const unsigned int esp8266RxBufferLength = 600;
char esp8266RxBuffer[esp8266RxBufferLength];
unsigned int ii = 0;
char OneNetServer[] = "api.heclouds.com"; //不需要修改 const char ssid[] = "PushPull"; //修改为自己的路由器用户名
const char password[] = "********"; //修改为自己的路由器密码 char device_id[] = "600911"; //修改为自己的设备ID
char API_KEY[] = "R9xO5NZm6oVI4YBHvCPKEqtwYtMA"; //修改为自己的API_KEY
char sensor_id1[] = "TEMP";
char sensor_id2[] = "HUMI"; void setup() {
pinMode(L, OUTPUT);
digitalWrite(L, LOW);
DebugSerial.begin(9600);
ESP8266Serail.begin(115200); Timer1.initialize(1000);
Timer1.attachInterrupt(Timer1_handler); initEsp8266(); DebugSerial.println("setup end!");
} void loop() {
//获取温湿度数据
int chk = DHT11.read(DHT11PIN); //读取温湿度值 //串口调试DHT11输出信息
DebugSerial.print("Read sensor: ");
switch (chk)
{
case DHTLIB_OK:
DebugSerial.println("OK");
break;
case DHTLIB_ERROR_CHECKSUM:
DebugSerial.println("Checksum error");
break;
case DHTLIB_ERROR_TIMEOUT:
DebugSerial.println("Time out error");
break;
default:
DebugSerial.println("Unknown error");
break;
} //发送数据到Onenet
postDataToOneNet(API_KEY,device_id,sensor_id1,DHT11.temperature);
delay(100);
postDataToOneNet(API_KEY,device_id,sensor_id2,DHT11.humidity); delay(5000);
} void postDataToOneNet(char* API_VALUE_temp,char* device_id_temp,char* sensor_id_temp,double thisData)
{
//合成POST请求
StaticJsonBuffer<200> jsonBuffer; JsonObject& value = jsonBuffer.createObject();
value["value"] = thisData; JsonObject& id_datapoints = jsonBuffer.createObject();
id_datapoints["id"] = sensor_id_temp;
JsonArray& datapoints = id_datapoints.createNestedArray("datapoints");
datapoints.add(value); JsonObject& myJson = jsonBuffer.createObject();
JsonArray& datastreams = myJson.createNestedArray("datastreams");
datastreams.add(id_datapoints); char p[200];
int num = myJson.printTo(p, sizeof(p)); packet.setHostAddress(OneNetServer);
packet.setDevId(device_id_temp); //device_id
packet.setAccessKey(API_VALUE_temp); //API_KEY
// packet.setDataStreamId("<datastream_id>"); //datastream_id
// packet.setTriggerId("<trigger_id>");
// packet.setBinIdx("<bin_index>"); /*create the http message about add datapoint */
packet.createCmdPacket(POST, TYPE_DATAPOINT, p);
// if (strlen(packet.content))
// Serial.print(packet.content);
// Serial.print(p);
int httpLength = strlen(packet.content) + num; //连接服务器
char cmd[400];
memset(cmd, 0, 400); //清空cmd
strcpy(cmd, "AT+CIPSTART=\"TCP\",\"");
strcat(cmd, OneNetServer);
strcat(cmd, "\",80\r\n");
if (sendCommand(cmd, "CONNECT", 7, 10000, 5) == Success);
else ESP8266_ERROR(1); //发送数据
memset(cmd, 0, 400); //清空cmd
sprintf(cmd, "AT+CIPSEND=%d\r\n", httpLength);
if (sendCommand(cmd, ">", 1, 3000, 1) == Success);
else ESP8266_ERROR(2); memset(cmd, 0, 400); //清空cmd
strcpy(cmd, packet.content);
strcat(cmd, p);
if (sendCommand(cmd, "\"succ\"}", 7, 3000, 3) == Success);
else ESP8266_ERROR(3); if (sendCommand("AT+CIPCLOSE\r\n", "CLOSED", 6, 3000, 1) == Success);
else ESP8266_ERROR(4);
} void initEsp8266()
{
if (sendCommand("AT\r\n", "OK", 2, 3000, 10) == Success);
else ESP8266_ERROR(5); if (sendCommand("AT+RST\r\n", "ready", 5, 10000, 10) == Success);
else ESP8266_ERROR(6); if (sendCommand("AT+CWMODE=1\r\n", "OK", 2, 3000, 10) == Success);
else ESP8266_ERROR(7); char cmd[50];
strcpy(cmd, "AT+CWJAP=\"");
strcat(cmd, ssid);
strcat(cmd, "\",\"");
strcat(cmd, password);
strcat(cmd, "\"\r\n"); if (sendCommand(cmd, "OK", 2, 20000, 10) == Success);
else ESP8266_ERROR(8); if (sendCommand("AT+CIPMUX=0\r\n", "OK", 2, 3000, 10) == Success);
else ESP8266_ERROR(9); if (sendCommand("AT+CIFSR\r\n", "OK", 2, 20000, 10) == Success);
else ESP8266_ERROR(10);
} void(* resetFunc) (void) = 0; //制造重启命令 void ESP8266_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", 2, 100, 10) == Success)
{
DebugSerial.print("\r\nRESET!!!!!!\r\n");
resetFunc();
}
}
} unsigned int sendCommand(char *Command, char *Response, unsigned int Res_Length, unsigned long Timeout, unsigned char Retry)
{
clrEsp8266RxBuffer();
for (unsigned char n = 0; n < Retry; n++)
{
DebugSerial.print("\r\nsend AT Command:\r\n----------\r\n");
DebugSerial.write(Command); ESP8266Serail.write(Command); Time_Cont = 0;
while (Time_Cont < Timeout)
{
esp8266ReadBuffer();
if ((mystrstr(esp8266RxBuffer, Response, ii, Res_Length)) != NULL)
{
DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
DebugSerial.print(esp8266RxBuffer); //输出接收到的信息
clrEsp8266RxBuffer();
return Success;
}
}
Time_Cont = 0;
}
DebugSerial.print("\r\nreceive AT Command:\r\n==========\r\n");
DebugSerial.print(esp8266RxBuffer);//输出接收到的信息
clrEsp8266RxBuffer();
return Failure;
} unsigned char mystrstr(char *s, char *t, unsigned int Length_s, unsigned int Length_t)
{ char x = 0; char *p; p = t;
int i = 0, j = 0;
for (; i < Length_s; s++, i++)
{
while (*t == *s)
{ s++; t++; i++; j++;
if (j >= Length_t) return 1;
}
s -= j;
t = p; j = 0;
}
return NULL;
} void Timer1_handler(void)
{
Time_Cont++;
} void esp8266ReadBuffer() {
while (ESP8266Serail.available())
{
esp8266RxBuffer[ii++] = ESP8266Serail.read();
if (ii == esp8266RxBufferLength)clrEsp8266RxBuffer();
}
} void clrEsp8266RxBuffer(void)
{
memset(esp8266RxBuffer, 0, esp8266RxBufferLength); //清空
ii = 0;
}

ARDUINO MEGA2560 经过ESP8266 WIFI模块上传温湿度数据到 OneNet 服务器的更多相关文章

  1. 关于uboot中tftp上传内存数据到tftp服务器

    uboot下的tftp下载功能是非常重要和常见的功能.但是偶尔有些特殊需求的人需要使用uboot的tftp具有上传功能.默认的uboot没有tftp上传功能,如果需要修改uboot代码.使用时键入第4 ...

  2. 用ESP8266 WIFI模块连接服务器,并实现与服务器相互通讯

    最近在做一个智能锁的项目,该项目要求实现在任何地方(当然是要有网络的)可以在手机上用APP开锁.而我负责的部分主要是实现底层与服务器连接,并且要能相互通讯.考虑了很多问题,最终选择了用ESP8266 ...

  3. WiFi文件上传框架SGWiFiUpload

    背景 在iOS端由于文件系统的封闭性,文件的上传变得十分麻烦,一个比较好的解决方案是通过局域网WiFi来传输文件并存储到沙盒中. 简介 SGWiFiUpload是一个基于CocoaHTTPServer ...

  4. 2、网络并发编程--套接字编程、黏包问题、struct模块、制作简易报头、上传文件数据

    昨日内容回顾 面向对象复习(json序列化类) 对象.类.父类的概念 三大特性:封装 继承 多态 双下开头的方法(达到某个条件自动触发) __init__:对象实例化自动触发 __str__:对象执行 ...

  5. PHP文件上传至另一台服务器

    PHP程序上传文件时,想指定上传到另一台服务器. move_uploaded_file这个方法第二个参数指定的存放路径需要和php程序文件一个服务器,没办法指定其他服务器的地址,本人才疏学浅,哪位大哥 ...

  6. 用java 代码下载Samba服务器上的文件到本地目录以及上传本地文件到Samba服务器

    引入: 在我们昨天架设好了Samba服务器上并且创建了一个 Samba 账户后,我们就迫不及待的想用JAVA去操作Samba服务器了,我们找到了一个框架叫 jcifs,可以高效的完成我们工作. 实践: ...

  7. 使用Hue上传hive数据

    大概逻辑是先上传hdfs数据,然后创建hive外部表,关联到hdfs上传数据的位置. 截图比较概要,但是用起来很简单 1.创建路径和上传文件 2.创建外部表

  8. bootstrap上传表单的时候上传的数据默认是0 一定要小心

    bootstrap上传表单的时候上传的数据默认是0 一定要小心

  9. 移动商城第四篇【Controller配置、添加品牌之文件上传和数据校验】

    Controller层配置 编写SpringMVC的配置文件 springmvc.xml <?xml version="1.0" encoding="UTF-8&q ...

随机推荐

  1. Dynamics CRM 2015/2016 Web API:Unbound Action 和 Bound Action

    上篇文章介绍了Bound/Unbound Function.今天我们来看看Action吧.像我之前说的:Function和Action之前的差别能够简单理解为.Function不改动数据,可是Acti ...

  2. C语言 | 基础知识点笔记

    函数 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ...

  3. Deferred Shader GBuffer 感性认识。。。

  4. nightwatch-js -- test group

    Test group 可以将你的测试脚本划分到组中,并根据需要运行它们.要将测试组合在一起,只需将它们放在相同的子文件夹中,文件夹的名字即是组的名字.例如:lib/├── selenium-serve ...

  5. 安装Glass Box代理程序

    安装玻璃盒代理程序 目前版本的玻璃代理程序主要支持主流 Java EE 应用程序服务器(如 JBoss,Tomcat,WebLogic 和 WebSphere).玻璃盒代理程序可以自动化安装,但考虑到 ...

  6. unity4.6 Beta版 UI控件之Button

    近期需求,须要用到4.6版本号uGui了,所以抽时间来学习学习,就UI控件在Unity工具里创建预设这块来说相比較于NGUI,我认为是没有什么太大的差别的. 比方:Canvas--Camera . T ...

  7. go http请求基础

    1.请求方法: get post get 加请求参数,请求参数会加到url后面 post加请求参数,请求参数会放在body里面 请求方式:1.直接在url后面加参数  如:http://www.tes ...

  8. Atitit.5gl 第五代语言编程语言 PROLOG教程  人工智能语言的标准 与实现

    Atitit.5gl 第五代语言编程语言 PROLOG教程  人工智能语言的标准 与实现 1. 第五代语言就是自然语言又被称为知识库语言或人工智能语言,1 2. 人工智能语言特点2 2.1. 试探法2 ...

  9. Httpclient 实现带参文件上传

    这里直接贴出的是我封装好的doPostFile方法,httpclient 的版本是3.1. public static String doPostFile(String url, Part[] par ...

  10. json字符串传值到后台出现乱码的问题的解决方法

    1.原因:前台的编码是ISO-8859-1,后台的编码是UTF-8,所以会冲突 2.解决方法:先用ISO-8859-1解码成字节数组,再转成UTF-8编码格式 String strw = new St ...