本次使用的单片机型号为:ESP8266-NodeMCU
开发环境:Arudino IDE
使用云平台:NLECloud - 新大陆物联网云平台
使用的通讯协议:ndp.nlecloud.com,端口:8600,8601(TLS)
使用的温湿度传感器:DHT11
传感器连接示意图:
效果展示:
源代码:
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <DHT.h>
#define RED_LED D3
#define GREEN_LED D2
#define Dht 12 //GPIO12--D6
//新大陆服务器地址
#define TCP_server_ADDR1 "ndp.nlecloud.com"
#define TCP_server_ADDR2 "117.78.1.201"
//新大陆TCP连接端口
#define TCP_server_port1 "8600"
#define TCP_server_port2 "8700"
#define TCP_server_port3 "8800"
//连接自己的WiFi的名字和地址
#define WiFi_SSID "wulianwang"
#define WiFi_PASSWORD "wulianwang"
//设置上传数据的速率(1s<=upspeed<=60s)
#define upspeed 2*1000
//设置最大字节个数
#define MAX_PACKETSIZE 512
//设置心跳值 15s
#define KEEP_liveTime 15*1000
//设置重连时长
#define Reconnect_Time 2*1000
WiFiClient TCPclient; //以WiFi为媒创建一个TCPclien的对象
bool preTCPconnect=false; //TCP连接标志
unsigned long long preHeartTick = 0; //心跳连接
unsigned long preTCPStartTick = 0; //客户端连接
String TcpClient_Buff = ""; //存储收的数据
unsigned int TcpClient_BuffIndex = 0; //增加指数
unsigned long TcpClient_preTick = 0;
DHT dht(Dht,DHT11); //选择采集引脚和DHT的型号
int temp=0; //存温度数据
int hum=0; //存湿度数据
char cmd=0; //存每次收数据
void yin_init() //初始化引脚
{
pinMode(RED_LED,OUTPUT);
pinMode(GREEN_LED,OUTPUT);
pinMode(Dht,INPUT);
}
void cai_dht() //采温湿度
{
dht.begin(); //dht初始化
}
void serial_port() //串口
{
Serial.begin(9600);
}
void start_wifi_connect() //WiFi设置
{
WiFi.disconnect();
//1.STA模式:该模块通过路由器连接网络,手机或者电脑实现该设备的远程控制。
//2.AP模式:该模块作为热点,手机或者电脑连接wifi与该模块通信,实现局域网的无线控制。
//3.STA+AP模式:两种模式共存,既可以通过路由器连接到互联网,也可以作为WiFi热点,使其他设备连接到这个模块,实现广域网与局域网的无缝切换。
WiFi.mode(WIFI_STA);
WiFi.begin(WiFi_SSID,WiFi_PASSWORD);
}
void wifi_tick() //开始连接WiFi
{
static bool StartSTAFlag=false; //检查是否需要初始化WiFi
static bool TaskStart=false; //检查是否连接成功
int time=1; //连接的时长
if(!StartSTAFlag)
{
StartSTAFlag=true;
start_wifi_connect();
Serial.printf("\n堆大小:%d\r\n",ESP.getFreeHeap());
}
//等待WiFi连接
Serial.print("开始连接WiFi:");
while(WiFi.status()!=WL_CONNECTED)
{
Serial.print(time++);
Serial.print("秒");
Serial.print(' ');
delay(1000);
}
//WiFi连接成功后
if(TaskStart==false)
{
TaskStart=true;
Serial.print("\r\nESP8266本机IP地址:");
Serial.println(WiFi.localIP());
start_TCP_connect();
}
}
void sendto_TCPserver(String cmd) //发送数据到TCP服务器
{
if(TCPclient.connected())
{
TCPclient.print(cmd);
Serial.print("发送到TCP服务器的字符串:");
Serial.println(cmd);
}
else
{
Serial.println("客户端未读取");
return ;
}
}
void start_TCP_connect() //开始连接服务器
{
if(TCPclient.connect(TCP_server_ADDR1,atoi(TCP_server_port1))) //尝试连接服务器,成功返回1,失败返回0
{
Serial.print("连接成功,服务器和端口号:");
Serial.printf("%s:%d\n",TCP_server_ADDR1,atoi(TCP_server_port1));
//用于存储构建的JSON报文,以DynamicJsonDocument方式声明的对象将存储在堆内存中
DynamicJsonDocument doc(2*1024);
//构建一个JSON_Value字符串存储没有反序化之前的报文
String JSON_Value = "{\"t\":\"1\",\"device\":\"zhubaoli\",\"Key\":\"578fd5fdd1c448dc8494c587e012fcba\",\"ver\":\"v1.1\"}";
//反序化JSON_Value字符串为JSON报文格式,存入doc中
deserializeJson(doc,JSON_Value);
sendto_TCPserver(JSON_Value);
preTCPconnect=true;
preHeartTick = millis();
TCPclient.setNoDelay(true);
}
else
{
TCPclient.stop();
preTCPconnect=false;
Serial.print("连接服务器失败:");
Serial.print(TCP_server_ADDR1); //打印服务器的地址
}
preTCPStartTick=millis();
}
void cai_DHT11() 采集数据并上传
{
if(millis()-preHeartTick>=upspeed)
{
preHeartTick=millis();
DynamicJsonDocument doc(1024);
//构建input字符串
String input = "{\"t\":\"3\",\"datatype\":1,\"datas\":{\"Temperature\":temp,\"Humidity\":hum}}";
//转换json字符串转成json格式报文,先反序字符串得出json报文
deserializeJson(doc,input);
Serial.print("发送到TCP客户端的数据:");
Serial.println(input);
//获取将JSON字符串经过显示类型转换为JSON对象的报文主体
JsonObject obj = doc.as<JsonObject>();
//解析元素,再将温湿度数据存入对应的元素
temp=dht.readTemperature();
hum=dht.readHumidity();
obj["datas"]["Temperature"]=temp;
obj["datas"]["Humidity"]=hum;
String output; //存发更新温湿度的数据
//序列化新的数据
serializeJson(doc,output);
sendto_TCPserver(output); //发送给云平台
}
}
void State_TCPClient_Tick() //检查数据,发送心跳
{
if(WiFi.status()!=WL_CONNECTED) //检查wifi是否断开,断开后重连
return ;
if(TCPclient.connected()) //没有断开连接
{
if(TCPclient.available()) //收数据
{
cmd=TCPclient.read(); //客户端读取服务端的数据
TcpClient_Buff=TcpClient_Buff+cmd;
TcpClient_BuffIndex++;
TcpClient_preTick=millis();
if(TcpClient_BuffIndex>MAX_PACKETSIZE-1)
{
TcpClient_BuffIndex=MAX_PACKETSIZE-2; //清空间
TcpClient_preTick=TcpClient_preTick-200;
}
preHeartTick=millis();
}
if(millis()-preHeartTick>=KEEP_liveTime) //检查心跳连接
{
preHeartTick=millis();
Serial.println("保持心跳:");
sendto_TCPserver("$#AT#");
}
}
else
{
if(preTCPconnect==true)
{
preTCPconnect=false;
preTCPStartTick=millis();
Serial.println("TCP客户端连接失败");
TCPclient.stop();
}
else if(millis()-preTCPStartTick>Reconnect_Time)
start_TCP_connect();
}
if((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick>=200))
{
//数据就绪
TCPclient.flush();
Serial.print("Buff");
Serial.println(TcpClient_Buff);
TcpClient_Buff="";
TcpClient_BuffIndex = 0;
}
cai_DHT11();
}
void setup() {
// put your setup code here, to run once:
yin_init();
cai_dht();
serial_port();
//start_wifi_connect();
wifi_tick();
}
void loop() {
// put your main code here, to run repeatedly:
State_TCPClient_Tick();
}