#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <WiFi.h>
void InitWiFi(void);
void on_message(char* topic, byte* payload, unsigned int length);
void reconnect();
String get_light_status();
void set_light_status(boolean enabled);
//要连接的WiFi热点名、WiFi热点密码
#define WIFI_AP "Wokwi-GUEST"
#define WIFI_PASSWORD ""
//要修改以下三个变量的内容:根据自己在ThingsBoard服务器上创建的设备填写
//clientId: 添加设备时的客户端ID
//tenantName: 用户名
//tenantPassword: 密码
const char* clientId="";
const char* tenantName="";
const char* tenantPassword="";
#define LIGHT_PIN 2
//灯初始状态是熄灭的
boolean lightState = false;
//不要修改!这是CPS技术与创客实践课程的物联网云服务器网址、端口号
char thingsboardServer[] = "broker.emqx.io";
int port = 1883;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
int status = WL_IDLE_STATUS;
void setup() {
Serial.begin(115200);
// 设置灯连接的引脚2作为输出引脚
pinMode(LIGHT_PIN, OUTPUT);
delay(10);
InitWiFi();
client.setServer( thingsboardServer, port );
client.setCallback(on_message);
}
void loop() {
if ( !client.connected() ) {
reconnect();
}
client.loop();
}
// 回调函数:当从服务器收到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.print("deserializeJson() returned ");
Serial.println(error.c_str());
return;
}
// 检查请求的方法method
String methodName = String((const char*)data["method"]);
if (methodName.equals("getLightStatus")) {
// 应答灯状态
String responseTopic = String(topic);
responseTopic.replace("request", "response");
client.publish(responseTopic.c_str(), get_light_status().c_str());
} else if (methodName.equals("setLightStatus")) {
// 更新灯状态并应答
set_light_status(data["params"]["enabled"]);
String responseTopic = String(topic);
responseTopic.replace("request", "response");
client.publish(responseTopic.c_str(), get_light_status().c_str());
client.publish("v1/devices/me/attributes", get_light_status().c_str());
}
}
String get_light_status() {
// 准备JSON格式的数据payload
JsonDocument data;
data["enabled"] = lightState;
// char payload[256];
//data.printTo(payload, sizeof(payload));
//String strPayload = String(payload);
String strPayload;
serializeJson(data, strPayload);
Serial.print("Turn light: ");
Serial.println(strPayload);
return strPayload;
}
void set_light_status(boolean enabled) {
// 更新灯
digitalWrite(LIGHT_PIN, enabled);
// 更新灯状态变量
lightState = enabled;
}
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, tenantName, tenantPassword) ) {
Serial.println( "[DONE]" );
// 订阅RPC请求
client.subscribe("v1/devices/me/rpc/request/+");
// 发送当前灯状态
Serial.println("Sending current light status ...");
client.publish("v1/devices/me/attributes", get_light_status().c_str());
} else {
Serial.print( "[FAILED] [ rc = " );
Serial.print( client.state() );
Serial.println( " : retrying in 5 seconds]" );
// 重连前,等待5秒
delay( 5000 );
}
}
}