Hello all, i have a question maybe about datatypes.. I'm using several ESP8266 and ESP-now protocol with several temp sensors, i'm using a sketch based on an Andreas spiess sketch to receive messages from remote sensors and then send out by mqtt.
My first issue is that i want to send the mqtt topic from the remote sensor to the gateway, so that each separate sensor will instruct the 'mqtt gateway' which topic it will forward the data on..
My problem is that i have a poor understanding of datatypes. The sketch that i base this on uses a struct, and i can successfully transfer the temperature and a station number in 2 seperate floats, but i just don't have a clue where to start with the topic, i've tried Char* and i've tried String, but the Char crashed the sketch on the gateway, and the String outputs a weird symbol on the receiving side like this -> ▒ <-
Programming with arduino ide.
This is the sketch coming from an individual temp node
#include <ESP8266WiFi.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_PIN 2
OneWire oneWire(ONE_WIRE_PIN);
DallasTemperature sensors(&oneWire);
float tempSensor1;
uint8_t sensor1[8] = { 0x28, 0xFF, 0x25, 0x95, 0x92, 0x16, 0x04, 0x42 }; // 28FF259592160442
extern "C" {
#include <espnow.h>
#include "user_interface.h"
}
uint8_t remoteMac[] = {0x1A, 0xFE, 0x34, 0xE1, 0x1E, 0xC2};
#define WIFI_CHANNEL 1
#define SLEEP_SECS 20 // sleep in seconds, 900 seconds is 15 minutes
#define SEND_TIMEOUT 100 // 245 millis seconds timeout
// keep in sync with slave struct
struct __attribute__((packed)) SENSOR_DATA {
float station;
float temp1;
//
String topic1;
} sensorData;
void setup() {
Serial.begin(115200); Serial.println();
sensors.begin();
readSensor();
if (esp_now_init() != 0) {
Serial.println("*** ESP_Now init failed");
gotoSleep();
}
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_add_peer(remoteMac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);
esp_now_register_send_cb([](uint8_t* mac, uint8_t sendStatus) {
//Serial.printf("send_cb, send done, status = %i\n", sendStatus);
gotoSleep();
});
uint8_t bs[sizeof(sensorData)];
memcpy(bs, &sensorData, sizeof(sensorData));
esp_now_send(remoteMac, bs, sizeof(sensorData));
}
void loop() {
if (millis() > SEND_TIMEOUT) {
gotoSleep();
}
}
void readSensor() {
sensors.requestTemperatures();
sensorData.station = 1;
sensorData.temp1 = sensors.getTempC(sensor1);
sensorData.topic1 = "ESP/hello";
Serial.printf("temp1=%01f\n", sensorData.temp1);
Serial.println(sensorData.topic1);
}
void gotoSleep() {
int sleepSecs = SLEEP_SECS + ((uint8_t)RANDOM_REG32 / 8);
Serial.printf("Awake for %i ms, going to sleep for %i secs...\n", millis(), sleepSecs);
ESP.deepSleep(sleepSecs * 1000000, RF_NO_CAL);
}
And this is the "gateway / Relay " code.
/**
*
* Author: Andreas Spiess, 2017
* Slightly adapted by Diy_bloke 2020
This sketch receives ESP-Now message and sends it as an MQTT messge
It is heavily based on of Anthony's gateway setch sketch
https://github.com/HarringayMakerSpace/ESP-Now
Anthony Elder
*/
#include <ESP8266WiFi.h>
#include "PubSubClient.h"
extern "C" {
#include "user_interface.h"
#include <espnow.h>
}
//-------- Customise the above values --------
//#define COMMANDTOPIC "ESPNow/command"
#define SERVICETOPIC "ESPNow/service"
#define SENDTOPIC "ESPNow/cheese"
/* Set a private Mac Address
* http://serverfault.com/questions/40712/what-range-of-mac-addresses-can-i-safely-use-for-my-virtual-machines
* Note: the point of setting a specific MAC is so you can replace this Gateway ESP8266 device with a new one
* and the new gateway will still pick up the remote sensors which are still sending to the old MAC
*/
uint8_t mac[] = {0xEC, 0xFA, 0xBC, 0x9B, 0xF5, 0x6D};// your MAC
void initVariant() {
//wifi_set_macaddr(SOFTAP_IF, &mac[0]);
}
char *ssid = "***********"; // Set you WiFi SSID
char *password = "*********"; // Set you WiFi password
IPAddress server(192, 168, 1, 77);//your MQTT Broker address
//const char deviceTopic[] = "ESPNOW/"; //I guess this isn't used
WiFiClient wifiClient;
PubSubClient client(server, 1883, wifiClient);
String deviceMac;
// keep in sync with ESP_NOW sensor struct
struct __attribute__((packed)) SENSOR_DATA {
float station;
float temp1;
String topic1;
} sensorData;
volatile boolean haveReading = false;
//char* SENDTOPIC = sensorData.topic;
int heartBeat;
//////////////////////////////////////////////////////////////////////////////////////////
//
/////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
Serial.println("ESP_Now Controller");
Serial.println();
WiFi.mode(WIFI_AP);
Serial.print("This node NOW mac: "); Serial.println(WiFi.softAPmacAddress());
Serial.print("This node STA mac: "); Serial.println(WiFi.macAddress());
initEspNow();
Serial.println("Setup done");
}
void loop() {
if (millis()-heartBeat > 30000) {
Serial.println("Waiting for ESP-NOW messages...");
heartBeat = millis();
}
if (haveReading) {
haveReading = false; //<<<<<<<<<<<<<<<<<<<<<<<
wifiConnect();
reconnectMQTT();
sendToBroker();
client.disconnect();
delay(200);
ESP.restart(); // <----- Reboots to re-enable ESP-NOW
}
}
void sendToBroker() { //
Serial.println(sensorData.temp1);
Serial.println(sensorData.topic1);
String payload = "{";
payload += "\"station\":\"" + String(sensorData.station);
payload += "\",\"temp\":\""+String(sensorData.temp1);
payload += "\",\"topic\":\""+String(sensorData.topic1); // i hope this wont need to be sent
payload += "\"}";
Serial.println(payload);
publishMQTT(SENDTOPIC,payload);
}
void initEspNow() {
if (esp_now_init()!=0) {
Serial.println("*** ESP_Now init failed");
ESP.restart();
}
esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
esp_now_register_recv_cb([](uint8_t *mac, uint8_t *data, uint8_t len) {
deviceMac = "";
deviceMac += String(mac[0], HEX);
deviceMac += String(mac[1], HEX);
deviceMac += String(mac[2], HEX);
deviceMac += String(mac[3], HEX);
deviceMac += String(mac[4], HEX);
deviceMac += String(mac[5], HEX);
memcpy(&sensorData, data, sizeof(sensorData));
// Serial.println("Message received from device: ");
Serial.println(deviceMac);
Serial.print("Received Topic: ");
Serial.print(sensorData.topic1);
Serial.println("#");
// Serial.printf(" Temp=%0.2f, Sta=%0.0f, Topic=%s\n", sensorData.temp1, sensorData.station, sensorData.topic1);
haveReading = true;
});
}
void wifiConnect() {
WiFi.mode(WIFI_STA);
Serial.println();
Serial.print("Connecting to "); Serial.print(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.print("\nWiFi connected, IP address: "); Serial.println(WiFi.localIP());
}
void publishMQTT(String topic, String message) {
Serial.println("Publish");
if (!client.connected()) {
reconnectMQTT();
}
client.publish(SENDTOPIC, message.c_str());
}
void reconnectMQTT() {
Serial.println(" Loop until we're reconnected");
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP-NOWClient-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish(SERVICETOPIC, "I am alive");
// ... and resubscribe
// client.subscribe("inTopic");
} else {
Serial.print("failed, rc = ");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
Sorry it's very messy, i'm still copying pasting to get things working, and usually tidy up after