Я использую ESP32 для публикации sh данных. Код работает почти все время, но иногда он перестает публиковать данные. Вот код, который я использую. Ниже вы видите ту часть, где я сталкиваюсь с этой проблемой. Было бы здорово, если у кого-то есть решение.
#include "BLEDevice.h"
#include <ArduinoJson.h>
#include <WiFi.h>
#include <WiFiManager.h>
#include <HTTPClient.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
#include <ESPmDNS.h>
#include <OneWire.h>
#include <DallasTemperature.h>
void connectWifi();
String gethttp();
void disconnectWifi();
void connectMqtt();
void hibernate();
void delayedHibernate(void *parameter);
void disconnectMqtt();
void publish_mqtt(String mqtt_topic);
void decode_json (String payload);
void handle_flora(String devname, String macaddress);
void handshake();
void check_wifi_mqtt();
BLEClient* getFloraClient(BLEAddress floraAddress);
BLERemoteService* getFloraService(BLEClient* floraClient);
bool forceFloraServiceDataMode(BLERemoteService* floraService);
bool readFloraDataCharacteristic(BLERemoteService* floraService, float *temperature, float *moisture, float *light, float *conductivity);
bool readFloraBatteryCharacteristic(BLERemoteService* floraService, float *battery);
bool processFloraService(BLERemoteService* floraService, char* deviceMacAddress, float *temperature, float *moisture, float *light, float *conductivity, float *battery);
bool processFloraDevice(BLEAddress floraAddress, char* deviceMacAddress, float *temperature, float *moisture, float *light, float *conductivity, float *battery);
#define RETRY 3 //Number of times a process gets repeated upon failure
static BLEUUID serviceUUID("00001204-0000-1000-8000-00805f9b34fb");
static BLEUUID uuid_version_battery("00001a02-0000-1000-8000-00805f9b34fb");
static BLEUUID uuid_sensor_data("00001a01-0000-1000-8000-00805f9b34fb");
static BLEUUID uuid_write_mode("00001a00-0000-1000-8000-00805f9b34fb");
char JSONmessageBuffer[4000];
int flora_counter = 0;
#define ONE_WIRE_BUS 4
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DynamicJsonBuffer outputbuff;
JsonObject& out = outputbuff.createObject();
JsonObject& Status = out .createNestedObject("Status");
JsonObject& StatusSNS = out.createNestedObject("StatusSNS");
JsonObject& StatusSTS = out.createNestedObject("StatusSTS");
TaskHandle_t hibernateTaskHandle = NULL;
WiFiClient espClient;
PubSubClient client(espClient);
void setup()
{
Serial.begin(115200);
delay(1000);
connectWifi();
connectMqtt();
handshake();
String pay_load = gethttp();
if (pay_load != "failed")
{
flora_counter = 0;
decode_json(pay_load);
Serial.println (JSONmessageBuffer);
}
disconnectWifi();
disconnectMqtt();
}
void loop()
{
delay(10000);
ESP.restart();
delay(5000);
}
void connectWifi()
{
String hostname = "ESP32_" + WiFi.macAddress();
WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
WiFi.setHostname(hostname.c_str());
WiFiManager wifiManager;
if (!wifiManager.autoConnect("Sudoware_ESP", ""))
{
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.restart();
delay(5000);
}
Serial.println("Wifi Connected");
Serial.print("local ip ");
Serial.println(WiFi.localIP());
}
String gethttp()
{
Serial.println("gethttp");
Serial.println(WiFi.localIP());
HTTPClient http;
String apihit = "http://192.168.73.1/get_esp_config.php?mac=" + WiFi.macAddress();
String payload = "";
http.begin(apihit.c_str()); //Specify the URL
int httpCode = http.GET(); //Make the request
if (httpCode > 0)
{
payload = http.getString();
Serial.println(httpCode);
Serial.println(payload);
}
else
{
payload = "failed";
}
http.end(); //Free the resources
Serial.println("payload: " + payload);
return payload;
}
void disconnectWifi()
{
WiFi.disconnect(true);
Serial.println("WiFi disonnected");
}
void connectMqtt()
{
Serial.println("Connecting to MQTT...");
Serial.print("local ip ");
Serial.println(WiFi.localIP());
client.setServer("192.168.73.1", 1883);
while (!client.connected())
{
if (!client.connect("", "", ""))
{
Serial.print("MQTT connection failed:" );
Serial.print(client.state());
Serial.println(" Retrying..." );
delay(1000);
}
}
Serial.println("MQTT connected");
Serial.println("");
}
//void hibernate()
//{
// esp_sleep_enable_timer_wakeup(SLEEP_DURATION * 1000000ll);
// Serial.println("Going to sleep now.");
// delay(100);
// esp_deep_sleep_start();
//}
//
//void delayedHibernate(void *parameter)
//{
// delay(EMERGENCY_HIBERNATE * 1000); // delay for five minutes
// Serial.println("Something got stuck, entering emergency hibernate...");
// hibernate();
//}
void disconnectMqtt()
{
client.disconnect();
Serial.println("MQTT disconnected");
}
**void publish_mqtt(String mqtt_topic)
{
//Change mqtt topic to character
out.printTo(JSONmessageBuffer);
Serial.println(JSONmessageBuffer);
int count = 0;
check_wifi_mqtt();
while (count <= 3 and !client.publish(mqtt_topic.c_str(), JSONmessageBuffer, true))
{
count += 1;
check_wifi_mqtt();
Serial.println("Error sending message and count is: ");
Serial.print(count);
Serial.println("");
}
if (count > 3)
{
esp_sleep_enable_timer_wakeup(10 * 1000000ll);
Serial.println("Restarting in 10 seconds");
delay(100);
esp_deep_sleep_start();
}
Serial.println("Success sending message");
}**
BLEClient* getFloraClient(BLEAddress floraAddress)
{
BLEClient* floraClient = BLEDevice::createClient();
if (!floraClient->connect(floraAddress))
{
Serial.println("- Connection failed, skipping");
return nullptr;
}
Serial.println("- Connection successful");
return floraClient;
}
BLERemoteService* getFloraService(BLEClient* floraClient)
{
BLERemoteService* floraService = nullptr;
try
{
floraService = floraClient->getService(serviceUUID);
}
catch (...)
{
// something went wrong
}
if (floraService == nullptr)
{
Serial.println("- Failed to find data service");
}
else
{
Serial.println("- Found data service");
}
return floraService;
}
bool forceFloraServiceDataMode(BLERemoteService* floraService)
{
BLERemoteCharacteristic* floraCharacteristic;
// get device mode characteristic, needs to be changed to read data
Serial.println("- Force device in data mode");
floraCharacteristic = nullptr;
try
{
floraCharacteristic = floraService->getCharacteristic(uuid_write_mode);
}
catch (...)
{
// something went wrong
}
if (floraCharacteristic == nullptr)
{
Serial.println("-- Failed, skipping device");
return false;
}
// write the magic data
uint8_t buf[2] = {0xA0, 0x1F};
floraCharacteristic->writeValue(buf, 2, true);
delay(500);
return true;
}
bool readFloraDataCharacteristic(BLERemoteService* floraService, float *temperature, float *moisture, float *light, float *conductivity)
{
BLERemoteCharacteristic* floraCharacteristic = nullptr;
// get the main device data characteristic
Serial.println("- Access characteristic from device");
try
{
floraCharacteristic = floraService->getCharacteristic(uuid_sensor_data);
}
catch (...)
{
// something went wrong
}
if (floraCharacteristic == nullptr)
{
Serial.println("-- Failed, skipping device");
return false;
}
// read characteristic value
Serial.println("- Read value from characteristic");
std::string value;
try
{
value = floraCharacteristic->readValue();
}
catch (...)
{
// something went wrong
Serial.println("-- Failed, skipping device");
return false;
}
const char *val = value.c_str();
Serial.print("Hex: ");
for (int i = 0; i < 16; i++)
{
Serial.print((int)val[i], HEX);
Serial.print(" ");
}
Serial.println(" ");
int16_t* temp_raw = (int16_t*)val;
*temperature = (*temp_raw) / ((float)10.0);
Serial.print("-- Temperature: ");
Serial.println(*temperature);
*moisture = (float)val[7];
Serial.print("-- Moisture: ");
Serial.println(*moisture);
*light = (float)val[3] + (float)val[4] * 256;
Serial.print("-- Light: ");
Serial.println(*light);
*conductivity = (float)val[8] + (float)val[9] * 256;
Serial.print("-- Conductivity: ");
Serial.println(*conductivity);
return true;
}
bool readFloraBatteryCharacteristic(BLERemoteService* floraService, float *battery)
{
BLERemoteCharacteristic* floraCharacteristic = nullptr;
// get the device battery characteristic
Serial.println("- Access battery characteristic from device");
try
{
floraCharacteristic = floraService->getCharacteristic(uuid_version_battery);
}
catch (...)
{
// something went wrong
}
if (floraCharacteristic == nullptr)
{
Serial.println("-- Failed, skipping battery level");
return false;
}
// read characteristic value
Serial.println("- Read value from characteristic");
std::string value;
try
{
value = floraCharacteristic->readValue();
}
catch (...)
{
// something went wrong
Serial.println("-- Failed, skipping battery level");
return false;
}
const char *val2 = value.c_str();
*battery = (float)val2[0];
Serial.print("-- Battery: ");
Serial.println(*battery);
return true;
}
bool processFloraService(BLERemoteService* floraService, char* deviceMacAddress, float *temperature, float *moisture, float *light, float *conductivity, float *battery)
{
// set device in data mode
if (!forceFloraServiceDataMode(floraService))
{
return false;
}
bool dataSuccess = readFloraDataCharacteristic(floraService, temperature, moisture, light, conductivity);
bool batterySuccess = readFloraBatteryCharacteristic(floraService, battery);
return dataSuccess && batterySuccess;
}
bool processFloraDevice(BLEAddress floraAddress, char* deviceMacAddress, float *temperature, float *moisture, float *light, float *conductivity, float *battery)
{
Serial.print(" Processing Flora device at ");
Serial.print(floraAddress.toString().c_str());
Serial.print(" Flora counter: ");
Serial.print(flora_counter);
// connect to flora ble server
BLEClient* floraClient = getFloraClient(floraAddress);
if (floraClient == nullptr)
{
return false;
}
// connect data service
BLERemoteService* floraService = getFloraService(floraClient);
if (floraService == nullptr)
{
floraClient->disconnect();
return false;
}
// process devices data
bool success = processFloraService(floraService, deviceMacAddress, temperature, moisture, light, conductivity, battery);
// disconnect from device
floraClient->disconnect();
return success;
}
void handle_flora (String devname, String deviceMacAddress)
{
float temperature, moisture, light, conductivity, battery;
Serial.println("Initialize BLE client...");
BLEDevice::init("");
BLEDevice::setPower(ESP_PWR_LVL_P7);
// process devices
BLEAddress floraAddress(deviceMacAddress.c_str());
if (processFloraDevice(floraAddress, const_cast<char*>(deviceMacAddress.c_str()), &temperature, &moisture, &light, &conductivity, &battery))
{
JsonObject& StatusSNS_FLORA = StatusSNS.createNestedObject(devname);
StatusSNS_FLORA["Temperature"] = temperature;
StatusSNS_FLORA["Moisture"] = moisture;
StatusSNS_FLORA["Light"] = light;
StatusSNS_FLORA["Conductivity"] = conductivity;
StatusSNS_FLORA["Battery"] = battery;
}
delay(1000);
}
void handle_dallas_ufire(String devname)
{
sensors.begin();
sensors.requestTemperatures();
float tempC = sensors.getTempCByIndex(0);
JsonObject& StatusSNS_dallas_ufire = StatusSNS.createNestedObject(devname);
StatusSNS_dallas_ufire["Temperature"] = tempC;
}
void handshake()
{
String topic_hand = "" + WiFi.macAddress();
Serial.println("");
Serial.println(topic_hand);
char* boolval = "true";
if (client.publish(topic_hand.c_str(), boolval, true))
{
Serial.println("Handshake Successfull");
}
}
void check_wifi_mqtt()
{
Serial.println("Wifi status: " );
int status_wifi = WiFi.status();
Serial.println(status_wifi);
if (status_wifi != 3)
{
connectWifi();
}
bool mqtt_status = client.connected();
if (mqtt_status != 0)
{
if (!client.connect("", "", ""))
{
Serial.print("MQTT connection failed:" );
Serial.print(client.state());
Serial.println(" Retrying..." );
delay(1000);
}
}
}
void decode_json (String payload)
{
DynamicJsonBuffer jsonBuffer;
Serial.println("Parsing JSON Object");
//payload = "{\"topic\":\"flora1x\",\"enabled\":\"1\",\"settings\":[{\"name\":\"asd\",\"type\":\"flora\",\"others\":\"c4:7c:8d:63:ce:02\"},{\"name\":\"asd\",\"type\":\"temperature\",\"others\":\"\"}]}";
JsonObject& doc = jsonBuffer.parseObject(payload);
doc.printTo(Serial);
if (!doc.success())
{
Serial.println("parseObject() failed");
}
else
{
Serial.println("ParseObject() successfull");
}
if (doc["enabled"])
{
Status["FriendlyName"] = "h2o";
Status["Topic"] = doc["topic"];
Status["Power"] = 0;
StatusSNS["Time"] = "2019-11-07T02:06:13";
StatusSTS["Time"] = "2018.02.15 01:00:50";
StatusSTS["Uptime"] = "1 02:33:26";
StatusSTS["Vcc"] = 3.504;
StatusSTS["POWER"] = "OFF";
String MQTT_TOPIC = doc["topic"];
Serial.println (MQTT_TOPIC);
JsonArray& dev_status = doc["settings"];
for (JsonObject& results : dev_status)
{
String sensor_type = results["type"];
if (sensor_type == "flora")
{
flora_counter++;
String devname = results["name"];
String deviceMacAddress = results["others"];
handle_flora(devname, deviceMacAddress);
}
else if (sensor_type == "dallas")
{
String devname = results["name"];
handle_dallas_ufire(devname);
}
}
publish_mqtt(MQTT_TOPIC);
}
}
В этой части кода я сталкиваюсь с проблемой
void publish_mqtt(String mqtt_topic)
{
//Change mqtt topic to character
out.printTo(JSONmessageBuffer);
Serial.println(JSONmessageBuffer);
int count = 0;
check_wifi_mqtt();
while (count <= 3 and !client.publish(mqtt_topic.c_str(), JSONmessageBuffer, true))
{
count += 1;
check_wifi_mqtt();
Serial.println("Error sending message and count is: ");
Serial.print(count);
Serial.println("");
}
if (count > 3)
{
esp_sleep_enable_timer_wakeup(10 * 1000000ll);
Serial.println("Restarting in 10 seconds");
delay(100);
esp_deep_sleep_start();
}
Serial.println("Success sending message");
}
Хотелось бы услышать ответ от кого-то, кто мог бы есть решение для этого. Хотя код будет работать только для следующей итерации, но мне любопытно выяснить причину проблемы root.