#include <ArduinoJson.h>
#include "PubSubClient.h"
#include <WiFi.h>
//要连接的WiFi热点名、WiFi热点密码
#define WIFI_AP "Wokwi-GUEST"
#define WIFI_PASSWORD ""
//要修改以下三个变量的内容:根据自己在ThingsBoard服务器上创建的设备填写
//clientId: 添加设备时的客户端ID
//userName: 用户名
//password: 密码
const char* clientId="";
const char* userName="";
const char* password="";
#define lightPin 2
#define lightSensor A0
int counter =0;
//不要修改!这是CPS技术与创客实践课程的物联网云服务器网址、端口号
char thingsboardServer[] = "thingsboard.cloud";
int port = 1883;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
int status = WL_IDLE_STATUS;
void setup() {
pinMode(lightPin, OUTPUT);
Serial.begin(115200);
InitWiFi();
client.setServer( thingsboardServer, port );
client.setCallback(on_message);
}
void loop() {
if ( !client.connected() ) reconnect();
client.loop();
if(counter>=20){
counter=0;
/*2秒钟上报1次传感器数据*/
int value = analogRead(lightSensor);
Serial.print("Light sensor:");
Serial.println(value);
// 准备JSON格式的数据payload
StaticJsonDocument<200> jsonBuffer;
JsonObject data = jsonBuffer.to<JsonObject>();
data["sensor"] = value;
char payload[256];
serializeJson(data,payload,sizeof(payload));
String strPayload = String(payload);
Serial.print("light sensor: ");
Serial.println(strPayload);
client.publish("v1/devices/me/telemetry", strPayload.c_str());
} else {
counter++;
delay(100);
}
}
void InitWiFi() {
Serial.println("Connecting to AP ...");
// 连接WiFi
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_AP, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
void reconnect() {
// 循环直到重新连接成功
while (!client.connected()) {
status = WiFi.status();
if ( status != WL_CONNECTED) {
WiFi.begin(WIFI_AP, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to AP");
}
Serial.print("Connecting to IoT Server ...");
// 连接物联网云服务器,使用(clientId, username, password)
if ( client.connect(clientId, userName, password) ) {
Serial.println( "[DONE]" );
client.subscribe("v1/devices/me/rpc/request/+");
} else {
Serial.print( "[FAILED] [ rc = " );
Serial.print( client.state() );
Serial.println( " : retrying in 5 seconds]" );
// 重连前,等待5秒
delay( 5000 );
}
}
}
// 回调函数:当从服务器收到PUBLISH消息时触发
void on_message(char* topic, byte* payload, unsigned int length) {
Serial.println("On message");
char json[length + 1];
strncpy (json, (char*)payload, length);
json[length] = '\0';
Serial.print("Topic: ");
Serial.println(topic);
Serial.print("Message: ");
Serial.println(json);
// Decode JSON request
JsonDocument data;
DeserializationError error = deserializeJson(data, json);
if (error)
{
Serial.println("parseObject() failed");
return;
}
// 检查请求的方法method
String methodName = String((const char*)data["method"]);
if (methodName.equals("light")) {
// 应答Hi消息
String responseTopic = String(topic);
responseTopic.replace("request", "response");
// 检查请求的参数params
bool params = data["params"];
Serial.println(params);
if(params) {
digitalWrite(lightPin, HIGH);
Serial.println("light on");
client.publish(responseTopic.c_str(), "{\"light\":\"on!\"}");
}
else {
digitalWrite(lightPin, LOW);
Serial.println("light off");
client.publish(responseTopic.c_str(), "{\"light\":\"off!\"}");
}
} else {
// 应答"Unknow command"消息
String responseTopic = String(topic);
Serial.println("Error: Unknown command.");
responseTopic.replace("request", "response");
client.publish(responseTopic.c_str(), "{\"Error\":\"Unknown command\"}");
}
}