使用来自 mqtt 回调的数据创建 IF 语句的正确方法
Correct way to create IF statement using data from mqtt callback
我试图在我的代码中使用回调函数的输出来触发一个动作。基本上,我将在 "reedTopic" 上安装一个门传感器,它需要在允许发送 "topic" 的有效载荷之前报告 "OFF"。 "topic" 有效负载是车库门开启器的开关,因此来自 "topic" 的数据将始终保持不变。
目标是当插入我车的esp8266-01连接到无线网络时,它会检测"reedTopic"的状态,如果不等于"OFF"它不会触发 "topic" 负载。
我想在代码中完全设置此自动化,而不必依赖其他软件(如 Node-Red 或 HomeAssistant)来完成这项工作。
我也很确定我没有完全理解回调函数以及它应该如何使用,尤其是在这种情况下。我仍然是一个 Arduino 新手,所以这真的是我的第一个项目。我也很确定那里有一些垃圾代码,因为大多数代码是从 Arduino IDE 中的 pubsubclient 处理程序的示例拼接在一起的。
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
const char* ssid = "******";
const char* password = "******";
const char* host = "CarPresence";
const char* update_path = "/";
const char* update_username = "*****";
const char* update_password = "*****";
char* topic = "cmnd/GarageDoor/POWER";
const char* willTopic = "cmnd/GarageDoor/POWER";
char* reedTopic = "cmnd/GarageDoor/POWER2";
char* server = "192.168.1.138";
byte willQoS = 1;
const char* willMessage = "1";
boolean willRetain = false;
boolean retained = true;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);
void callback(char* reedTopic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(reedTopic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
if (strcmp((char* )reedTopic, "OFF") == 0) {
client.connect("CarPresence", willTopic, willQoS, willRetain, willMessage);
client.publish(topic, "The Garage door is CLOSED... Opening...");
client.publish(topic, "1");
while (WiFi.status() == WL_CONNECTED) {
delay(5000);
client.println(reedTopic);
client.publish(topic, "Ah ah ah ah staying alive staying alive...");
}
}
if (strcmp((char* )reedTopic, "ON") == 0) {
client.publish(topic, "The Garage door is OPEN... Aborting...");
while (WiFi.status() == WL_CONNECTED) {
delay(5000);
client.println(reedTopic);
client.publish(topic, "Dying... I'm dying...");
}
}
Serial.println();
}
String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5)
result += ':';
}
return result;
}
void setup() {
Serial.begin(115200);
delay(10);
client.setCallback(callback);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
client.connect("CarPresence");
client.subscribe(topic);
client.subscribe(reedTopic, retained);
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();
Serial.printf("HTTPUpdateServer ready! Open http://%s%s in your browser and login with username '%s' and password '%s'\n", host, update_path, update_username, update_password);
// Generate client name based on MAC address and last 8 bits of microsecond counter
String clientName = "CarPresence";
Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);
if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topics are: ");
Serial.println(topic);
Serial.println(reedTopic);
if (client.publish(topic, "Hello from ESP8266")) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}
void loop() {
httpServer.handleClient();
client.setCallback(callback);
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
Serial.print(".");
}
}
大部分代码都有效。最大的问题是围绕 reedTopic 反馈的 IF 语句。代码直接从它身边吹过并执行了主题有效载荷。
我在 GitHub 上设法从 PubSubClient 的作者那里得到了一些帮助。后来我在 Arduino 论坛上找到了我需要的其他内容。下面是我完成的代码。
// Setup your sonoff //
// Flash your sonoff switch with tasmota //
// Associate the tasmotized sonoff with your WiFi network //
// Load the webpage for the sonoff and setup your mqtt topics //
// Go into module setup and set GPIO14 to Switch2 //
// Go into the console and type "SwitchMode2 1" (without quotes) //
// Lastly, in the console type "PulseTime 1" (without quotes) //
// Setup credentials in the code //
// Replace asterisks next to ssid & password with WiFi credentials //
// Replace asterisks next to update_username & update_password with creds //
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
const char* ssid = "******";
const char* password = "******";
const char* host = "CarPresence";
const char* update_path = "/";
const char* update_username = "******";
const char* update_password = "******";
char* topic = "cmnd/GarageDoor/POWER";
const char* willTopic = "cmnd/GarageDoor/POWER";
char* reedTopic = "cmnd/GarageDoor/POWER2";
char* server = "192.168.1.138";
byte willQoS = 1;
const char* willMessage = "1";
boolean willRetain = false;
boolean retained = true;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("CarPresence")) {
Serial.println("connected");
// set callback and subscribe to topics
client.setCallback(callback);
client.subscribe("cmnd/GarageDoor/POWER");
client.subscribe("cmnd/GarageDoor/POWER2");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void callback(char* reedTopic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(reedTopic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
payload[length] = '[=10=]';
String message = (char*)payload;
if(message == "ON"){
client.publish(topic, "Garage Door is CLOSED");
client.publish(topic, "1");
delay(10000);
while(message != "ON"){
break;
}
}
if(message == "OFF"){
client.publish(topic, "Garage Door is OPEN");
delay(10000);
while(message != "OFF"){
break;
}
}
}
String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5)
result += ':';
}
return result;
}
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();
Serial.println("HTTPUpdateServer ready!");
// Generate client name based on MAC address and last 8 bits of microsecond counter
String clientName = "CarPresence";
client.setServer(server, 1883);
client.setCallback(callback);
client.connect("CarPresence", willTopic, willQoS, willRetain, willMessage);
client.subscribe(topic);
client.subscribe(reedTopic, retained);
Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);
if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topics are: ");
Serial.println(topic);
Serial.println(reedTopic);
if (client.publish(topic, "Hello from ESP8266")) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
reconnect();
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
httpServer.handleClient();
client.publish(topic, "Keeping Alive");
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
Serial.print(".");
}
}
该代码也将发布在 GitHub 上的要点中。
https://gist.github.com/hyukishi
@Jeffrey Grantham,谢谢!!
关于如何将有效载荷转化为字符串的简短回答。
在 Serial.println();
之后的回调函数中
void callback(char *topic, byte *payload, unsigned int length)
{
//Print message received
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println();
添加这些关键命令以将负载转换为字符串!
payload[length] = '[=11=]';
String message = (char*)payload;
然后使用 strcmp() 函数将字符串与您的变量或字符串进行比较。
if (strcmp(topic, "mySwitch") == 0)
{
if(message == "true"){
digitalWrite(RELAY_PIN_1, HIGH);
}
if(message == "false"){
digitalWrite(RELAY_PIN_1, LOW);
}
}
.
.
.
code below omitted...
我试图在我的代码中使用回调函数的输出来触发一个动作。基本上,我将在 "reedTopic" 上安装一个门传感器,它需要在允许发送 "topic" 的有效载荷之前报告 "OFF"。 "topic" 有效负载是车库门开启器的开关,因此来自 "topic" 的数据将始终保持不变。
目标是当插入我车的esp8266-01连接到无线网络时,它会检测"reedTopic"的状态,如果不等于"OFF"它不会触发 "topic" 负载。
我想在代码中完全设置此自动化,而不必依赖其他软件(如 Node-Red 或 HomeAssistant)来完成这项工作。
我也很确定我没有完全理解回调函数以及它应该如何使用,尤其是在这种情况下。我仍然是一个 Arduino 新手,所以这真的是我的第一个项目。我也很确定那里有一些垃圾代码,因为大多数代码是从 Arduino IDE 中的 pubsubclient 处理程序的示例拼接在一起的。
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
const char* ssid = "******";
const char* password = "******";
const char* host = "CarPresence";
const char* update_path = "/";
const char* update_username = "*****";
const char* update_password = "*****";
char* topic = "cmnd/GarageDoor/POWER";
const char* willTopic = "cmnd/GarageDoor/POWER";
char* reedTopic = "cmnd/GarageDoor/POWER2";
char* server = "192.168.1.138";
byte willQoS = 1;
const char* willMessage = "1";
boolean willRetain = false;
boolean retained = true;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);
void callback(char* reedTopic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(reedTopic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
if (strcmp((char* )reedTopic, "OFF") == 0) {
client.connect("CarPresence", willTopic, willQoS, willRetain, willMessage);
client.publish(topic, "The Garage door is CLOSED... Opening...");
client.publish(topic, "1");
while (WiFi.status() == WL_CONNECTED) {
delay(5000);
client.println(reedTopic);
client.publish(topic, "Ah ah ah ah staying alive staying alive...");
}
}
if (strcmp((char* )reedTopic, "ON") == 0) {
client.publish(topic, "The Garage door is OPEN... Aborting...");
while (WiFi.status() == WL_CONNECTED) {
delay(5000);
client.println(reedTopic);
client.publish(topic, "Dying... I'm dying...");
}
}
Serial.println();
}
String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5)
result += ':';
}
return result;
}
void setup() {
Serial.begin(115200);
delay(10);
client.setCallback(callback);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
client.connect("CarPresence");
client.subscribe(topic);
client.subscribe(reedTopic, retained);
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();
Serial.printf("HTTPUpdateServer ready! Open http://%s%s in your browser and login with username '%s' and password '%s'\n", host, update_path, update_username, update_password);
// Generate client name based on MAC address and last 8 bits of microsecond counter
String clientName = "CarPresence";
Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);
if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topics are: ");
Serial.println(topic);
Serial.println(reedTopic);
if (client.publish(topic, "Hello from ESP8266")) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
abort();
}
}
void loop() {
httpServer.handleClient();
client.setCallback(callback);
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
Serial.print(".");
}
}
大部分代码都有效。最大的问题是围绕 reedTopic 反馈的 IF 语句。代码直接从它身边吹过并执行了主题有效载荷。
我在 GitHub 上设法从 PubSubClient 的作者那里得到了一些帮助。后来我在 Arduino 论坛上找到了我需要的其他内容。下面是我完成的代码。
// Setup your sonoff //
// Flash your sonoff switch with tasmota //
// Associate the tasmotized sonoff with your WiFi network //
// Load the webpage for the sonoff and setup your mqtt topics //
// Go into module setup and set GPIO14 to Switch2 //
// Go into the console and type "SwitchMode2 1" (without quotes) //
// Lastly, in the console type "PulseTime 1" (without quotes) //
// Setup credentials in the code //
// Replace asterisks next to ssid & password with WiFi credentials //
// Replace asterisks next to update_username & update_password with creds //
#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
const char* ssid = "******";
const char* password = "******";
const char* host = "CarPresence";
const char* update_path = "/";
const char* update_username = "******";
const char* update_password = "******";
char* topic = "cmnd/GarageDoor/POWER";
const char* willTopic = "cmnd/GarageDoor/POWER";
char* reedTopic = "cmnd/GarageDoor/POWER2";
char* server = "192.168.1.138";
byte willQoS = 1;
const char* willMessage = "1";
boolean willRetain = false;
boolean retained = true;
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("CarPresence")) {
Serial.println("connected");
// set callback and subscribe to topics
client.setCallback(callback);
client.subscribe("cmnd/GarageDoor/POWER");
client.subscribe("cmnd/GarageDoor/POWER2");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void callback(char* reedTopic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(reedTopic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
payload[length] = '[=10=]';
String message = (char*)payload;
if(message == "ON"){
client.publish(topic, "Garage Door is CLOSED");
client.publish(topic, "1");
delay(10000);
while(message != "ON"){
break;
}
}
if(message == "OFF"){
client.publish(topic, "Garage Door is OPEN");
delay(10000);
while(message != "OFF"){
break;
}
}
}
String macToStr(const uint8_t* mac)
{
String result;
for (int i = 0; i < 6; ++i) {
result += String(mac[i], 16);
if (i < 5)
result += ':';
}
return result;
}
void setup() {
Serial.begin(115200);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
httpUpdater.setup(&httpServer, update_path, update_username, update_password);
httpServer.begin();
Serial.println("HTTPUpdateServer ready!");
// Generate client name based on MAC address and last 8 bits of microsecond counter
String clientName = "CarPresence";
client.setServer(server, 1883);
client.setCallback(callback);
client.connect("CarPresence", willTopic, willQoS, willRetain, willMessage);
client.subscribe(topic);
client.subscribe(reedTopic, retained);
Serial.print("Connecting to ");
Serial.print(server);
Serial.print(" as ");
Serial.println(clientName);
if (client.connect((char*) clientName.c_str())) {
Serial.println("Connected to MQTT broker");
Serial.print("Topics are: ");
Serial.println(topic);
Serial.println(reedTopic);
if (client.publish(topic, "Hello from ESP8266")) {
Serial.println("Publish ok");
}
else {
Serial.println("Publish failed");
}
}
else {
Serial.println("MQTT connect failed");
Serial.println("Will reset and try again...");
reconnect();
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
httpServer.handleClient();
client.publish(topic, "Keeping Alive");
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
Serial.print(".");
}
}
该代码也将发布在 GitHub 上的要点中。 https://gist.github.com/hyukishi
@Jeffrey Grantham,谢谢!!
关于如何将有效载荷转化为字符串的简短回答。 在 Serial.println();
之后的回调函数中void callback(char *topic, byte *payload, unsigned int length)
{
//Print message received
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++)
{
Serial.print((char)payload[i]);
}
Serial.println();
添加这些关键命令以将负载转换为字符串!
payload[length] = '[=11=]';
String message = (char*)payload;
然后使用 strcmp() 函数将字符串与您的变量或字符串进行比较。
if (strcmp(topic, "mySwitch") == 0)
{
if(message == "true"){
digitalWrite(RELAY_PIN_1, HIGH);
}
if(message == "false"){
digitalWrite(RELAY_PIN_1, LOW);
}
}
.
.
.
code below omitted...