一、项目描述
设备将数据上传到阿里云,阿里云下数据到设备
二、使用工具
- 阿里云物联网平台
- arduino
- PZEM-004T
- nodemcu
三、项目过程
1、设备上传数据到阿里云
①在阿里云物联网平台创建产品
根据阿里云的文档开发
🔗链接
②实物连接,并上云
🔗链接
二、云端下发数据,设备接收数据(实现配网)
这里主要是使用了阿里云的topic实现修改nodemcu的wifi信息。
主要分成两种情况:
-
nodemcu处于掉线模式,需要更换网络
-
nodemcu处于在线模式,需要更换网络
实现方法为:将一个备用网络信息写入nodemcu的flash中(多为自己的手机热点信息),这样即时设备断电,这部分数据也不会丢失。若在掉线模式,设备会先尝试连接原来的网络15次,如果没有连接上,就读出flash中预留的网络配置信息,修改wifi信息,重新尝试连接。若在线,则会修改当前网络信息,并重新执行wifiinit方法。
#include <math.h>
#include "DHT.h"
#include <configdb.h>
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <AliyunIoTSDK.h>
#include <PZEM004Tv30.h>
#define PRODUCT_KEY ""
#define DEVICE_NAME ""
#define DEVICE_SECRET ""
#define REGION_ID "cn-shanghai"
#define DEVICE_KEY ""
#define WIFI_SSID "301"
#define WIFI_PASSWD "13912015808"
#define DHTPIN 3
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
AliyunIoTSDK iot;
static WiFiClient espClient;
PZEM004Tv30 pzem(D1,D2);
class MyConfiguration
{
public:
char *wifiName;
char *wifiPass;
};
ConfigDB<MyConfiguration> configDB;
unsigned long lastMsMain = 0;
int count = 0;
DynamicJsonDocument doc(1024);
void setup() {
Serial.begin(115200);
MyConfiguration defaultCfg = {"301","13912015808"};
bool isPreviusConfigStored = configDB.storeDefaultIfNotLoad(defaultCfg);
Serial.println(isPreviusConfigStored);
while(WiFi.status() != WL_CONNECTED){
MyConfiguration newCfg = configDB.load();
String str1= newCfg.wifiName;
String str2 = newCfg.wifiPass;
char *wifiName2=(char*)str1.c_str();
char *wifiPassword2=(char*)str2.c_str();
wifiInit(wifiName2, wifiPassword2);
}
dht.begin(); //DHT开始工作
AliyunIoTSDK::begin(espClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET, REGION_ID);
AliyunIoTSDK::bindData("electric",powerCallback);
}
void loop() {
AliyunIoTSDK::loop();
if (millis() - lastMsMain >= 3000)
{
lastMsMain = millis();
doc["humi"] = dht.readHumidity();//读湿度
doc["temp"] = dht.readTemperature();//读温度,默认为摄氏度
doc["voltage"] = pzem.voltage();
doc["current"] = pzem.current();
doc["power"] = pzem.power();
doc["energy"] = pzem.energy();
String output;
serializeJson(doc, output);
const char *str = output.c_str();
delay(2000);
AliyunIoTSDK::send(str);
}
}
void wifiInit(char *ssid,char *passphrase)
{
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,passphrase);
while(WiFi.status() != WL_CONNECTED){
count++;
delay(1000);
Serial.println(count);
Serial.println(ssid);
if(count>15){
Serial.println(count);
count=0;
setWiFiInfo("***","*********");
break;
}
delay(1000);
}
Serial.println("Connected to AP");
}
void setWiFiInfo(char *wifiname,char *wifipass){
MyConfiguration newCfg1 = configDB.load();
newCfg1.wifiName=wifiname;
newCfg1.wifiPass=wifipass;
configDB.save(newCfg1);
}
void powerCallback(JsonVariant p)
{
String wifiName = p["wifiName"];
String wifiPassword = p["wifiPassword"];
char *wifiName1=(char*)wifiName.c_str();
char *wifiPassword1=(char*)wifiPassword.c_str();
if(wifiName1&&wifiPassword1){
setWiFiInfo(wifiName1,wifiPassword1);
WiFi.disconnect();
}
wifiInit(wifiName1,wifiPassword1);
}
四、遇到问题及解决方法
-
关于将数据写入nodemcu的flash中
使用github上的一个库:ConfigDB,里面有一些读取、写入flash的方法。 -
阿里云的数据json类型转化为char* 类型
String wifiName = p["wifiName"];
char *wifiName1=(char*)wifiName.c_str();