简述

原来写了一个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. 标准库Allocator的简易实现(二)

    自己实现Allocator并不难,其实只需要改变allocate和deallocate,来实现自己的内存分配策略.   下面是一个std::allocator的模拟实现 #ifndef ALLOCAT ...

  2. Archlinux风扇设置

    在笔记本(ThinkPad T440)连续两天因过热而死机后, 对内核的风扇控制算法果断失去信心. 风扇的用户层控制接口是 /proc/acpi/ibm/fan, 但为防止用户控制不当烧坏机器, 默认 ...

  3. WebService的缓存机制

    分类: .NET ASP 2010-11-13 10:00 849人阅读 评论(0) 收藏 举报 webservicestring数据库nullapplicationweb服务 WebService的 ...

  4. jQuery表单 Ajax向PHP服务端发送文件请求并返回数据

    ImageAjaxUpLoad.htm <!DOCTYPE html> <head> <meta charset='utf-8'> <title>< ...

  5. ios程序,顶部和底部产生空白——程序不能全屏运行

    在开发过程中,遇到过这样的问题,整个程序不能以全屏状态运行,顶部和底部出现空白,如下图所示: 这样的原因是:设置的启动页不合适,设置大小合适的启动页就好了

  6. spark入门(helloworld插件)

    1 http://www.cnblogs.com/openfire/archive/2013/04/26/3044722.html 2 在bulid文件夹下,(注意为主目录不是插件下的bulid.xm ...

  7. OSX: 命令行制作U盘Recovery HD

    使用命令行操作,非常easy,可是操作不当非常危急! 免责声明:假设操作不当造成的数据丢失,本人概不负责. 为什么? 不是有OSX恢复磁盘助理嘛?是的.假设仅仅想使用GUI的软件.能够去苹果官方站点: ...

  8. sprint3 【每日scrum】 TD助手站立会议第八天

    站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 调整闹钟和整个项目的显示效果,最后做出了微信界面滑动的显示效果 整合原来做过的功能,并做相应的改进,整合其他的功能 在界面的设计和用户交互上始 ...

  9. Hibernate二次学习二----------session.flush、session.doWork

    目录 1. session 2. session.flush 3. session.doWork 4. 完整代码 5. 总结 © 版权声明:本文为博主原创文章,转载请注明出处 1. session H ...

  10. JSTL JSP页面推断某个cookie的值和读取值....

    <c:if test="${cookie['woshop'].value eq '1'}">                 <div>           ...