mirror of
https://github.com/schinken/esp8266-geigercounter.git
synced 2024-11-22 08:30:21 +01:00
209 lines
No EOL
6 KiB
C++
209 lines
No EOL
6 KiB
C++
#include "wifi.h"
|
|
|
|
#include <ESP8266WiFi.h>
|
|
#include <DNSServer.h>
|
|
#include <ESP8266WebServer.h>
|
|
#include <ArduinoJson.h>
|
|
#include <WiFiManager.h>
|
|
#include <PubSubClient.h>
|
|
#include <SoftwareSerial.h>
|
|
|
|
#include "settings.h"
|
|
|
|
uint8_t mqttRetryCounter = 0;
|
|
|
|
|
|
WiFiManager wifiManager;
|
|
WiFiClient wifiClient;
|
|
PubSubClient mqttClient;
|
|
|
|
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, sizeof(mqtt_server));
|
|
WiFiManagerParameter custom_mqtt_user("user", "MQTT username", username, sizeof(username));
|
|
WiFiManagerParameter custom_mqtt_pass("pass", "MQTT password", password, sizeof(password));
|
|
|
|
unsigned long lastMqttConnectionAttempt = millis();
|
|
const long mqttConnectionInterval = 60000;
|
|
|
|
unsigned long statusPublishPreviousMillis = millis();
|
|
const long statusPublishInterval = 30000;
|
|
|
|
char identifier[24];
|
|
#define FIRMWARE_PREFIX "esp8266-geigercounter"
|
|
#define AVAILABILITY_ONLINE "online"
|
|
#define AVAILABILITY_OFFLINE "offline"
|
|
char MQTT_TOPIC_AVAILABILITY[128];
|
|
char MQTT_TOPIC_CPM[128];
|
|
char MQTT_TOPIC_USV[128];
|
|
|
|
char MQTT_TOPIC_AUTOCONF_CPM[128];
|
|
char MQTT_TOPIC_AUTOCONF_USV[128];
|
|
|
|
SoftwareSerial geigerCounterSerial(PIN_UART_RX, PIN_UART_TX);
|
|
|
|
|
|
bool shouldSaveConfig = false;
|
|
|
|
void saveConfigCallback () {
|
|
shouldSaveConfig = true;
|
|
}
|
|
|
|
void setup() {
|
|
delay(3000);
|
|
Serial.begin(9600);
|
|
delay(2000);
|
|
Serial.println("\n");
|
|
Serial.println("Hello from esp8266-geigercounter");
|
|
Serial.printf("Core Version: %s\n", ESP.getCoreVersion().c_str());
|
|
Serial.printf("Boot Version: %u\n", ESP.getBootVersion());
|
|
Serial.printf("Boot Mode: %u\n", ESP.getBootMode());
|
|
Serial.printf("CPU Frequency: %u MHz\n", ESP.getCpuFreqMHz());
|
|
Serial.printf("Reset reason: %s\n", ESP.getResetReason().c_str());
|
|
|
|
geigerCounterSerial.begin(9600);
|
|
|
|
snprintf(identifier, sizeof(identifier), "GEIGERCTR-%X", ESP.getChipId());
|
|
snprintf(MQTT_TOPIC_AVAILABILITY, 127, "%s/%s/status", FIRMWARE_PREFIX, identifier);
|
|
snprintf(MQTT_TOPIC_CPM, 127, "%s/%s_cpm/state", FIRMWARE_PREFIX, identifier);
|
|
snprintf(MQTT_TOPIC_USV, 127, "%s/%s_usv/state", FIRMWARE_PREFIX, identifier);
|
|
|
|
snprintf(MQTT_TOPIC_AUTOCONF_CPM, 127, "homeassistant/sensor/%s/%s_cpm/config", FIRMWARE_PREFIX, identifier);
|
|
snprintf(MQTT_TOPIC_AUTOCONF_USV, 127, "homeassistant/sensor/%s/%s_usv/config", FIRMWARE_PREFIX, identifier);
|
|
|
|
|
|
|
|
WiFi.hostname(identifier);
|
|
|
|
loadConfig();
|
|
setupWifi();
|
|
mqttClient.setServer(mqtt_server, 1883);
|
|
mqttClient.setKeepAlive(10);
|
|
mqttClient.setBufferSize(2048);
|
|
|
|
Serial.print("Hostname: ");
|
|
Serial.println(identifier);
|
|
Serial.print("\nIP: ");
|
|
Serial.println(WiFi.localIP());
|
|
|
|
Serial.println("-- Current GPIO Configuration --");
|
|
Serial.print("PIN_UART_RX: ");
|
|
Serial.println(PIN_UART_RX);
|
|
|
|
//Disable blue LED
|
|
pinMode(LED_BUILTIN, OUTPUT);
|
|
digitalWrite(LED_BUILTIN, HIGH);
|
|
|
|
mqttReconnect();
|
|
}
|
|
|
|
|
|
void loop() {
|
|
mqttClient.loop();
|
|
|
|
handleUart();
|
|
|
|
if (statusPublishInterval <= (millis() - statusPublishPreviousMillis)) {
|
|
statusPublishPreviousMillis = millis();
|
|
updateRadiationValues();
|
|
}
|
|
|
|
if (!mqttClient.connected() && (mqttConnectionInterval <= (millis() - lastMqttConnectionAttempt)) ) {
|
|
lastMqttConnectionAttempt = millis();
|
|
mqttReconnect();
|
|
}
|
|
}
|
|
|
|
void setupWifi() {
|
|
wifiManager.setDebugOutput(false);
|
|
wifiManager.setSaveConfigCallback(saveConfigCallback);
|
|
|
|
wifiManager.addParameter(&custom_mqtt_server);
|
|
wifiManager.addParameter(&custom_mqtt_user);
|
|
wifiManager.addParameter(&custom_mqtt_pass);
|
|
|
|
WiFi.hostname(identifier);
|
|
wifiManager.autoConnect(identifier);
|
|
mqttClient.setClient(wifiClient);
|
|
|
|
strcpy(mqtt_server, custom_mqtt_server.getValue());
|
|
strcpy(username, custom_mqtt_user.getValue());
|
|
strcpy(password, custom_mqtt_pass.getValue());
|
|
|
|
if (shouldSaveConfig) {
|
|
saveConfig();
|
|
} else {
|
|
//For some reason, the read values get overwritten in this function
|
|
//To combat this, we just reload the config
|
|
//This is most likely a logic error which could be fixed otherwise
|
|
loadConfig();
|
|
}
|
|
}
|
|
|
|
void resetWifiSettingsAndReboot() {
|
|
wifiManager.resetSettings();
|
|
delay(3000);
|
|
ESP.restart();
|
|
}
|
|
|
|
void mqttReconnect() {
|
|
for (int attempt = 0; attempt < 3; ++attempt) {
|
|
if (mqttClient.connect(identifier, username, password, MQTT_TOPIC_AVAILABILITY, 1, true, AVAILABILITY_OFFLINE)) {
|
|
mqttClient.publish(MQTT_TOPIC_AVAILABILITY, AVAILABILITY_ONLINE, true);
|
|
|
|
Serial.println("Connected to MQTT Server");
|
|
|
|
publishAutoConfig();
|
|
break;
|
|
} else {
|
|
Serial.println("Failed to connect to MQTT Server :(");
|
|
delay(5000);
|
|
}
|
|
}
|
|
}
|
|
|
|
boolean isMqttConnected() {
|
|
return mqttClient.connected();
|
|
}
|
|
|
|
void publishAutoConfig() {
|
|
char mqttPayload[2048];
|
|
DynamicJsonDocument device(256);
|
|
StaticJsonDocument<64> identifiersDoc;
|
|
JsonArray identifiers = identifiersDoc.to<JsonArray>();
|
|
|
|
identifiers.add(identifier);
|
|
|
|
device["identifiers"] = identifiers;
|
|
device["manufacturer"] = "MightyOhm LLC";
|
|
device["model"] = "Geiger Counter";
|
|
device["name"] = identifier;
|
|
device["sw_version"] = "2023.08.0";
|
|
|
|
|
|
DynamicJsonDocument cpmSensorPayload(512);
|
|
|
|
cpmSensorPayload["device"] = device.as<JsonObject>();
|
|
cpmSensorPayload["availability_topic"] = MQTT_TOPIC_AVAILABILITY;
|
|
cpmSensorPayload["state_topic"] = MQTT_TOPIC_CPM;
|
|
cpmSensorPayload["name"] = "CPM";
|
|
cpmSensorPayload["unit_of_measurement"] = "CPM";
|
|
cpmSensorPayload["state_class"] = "measurement";
|
|
cpmSensorPayload["unique_id"] = identifier + String("_cpm");
|
|
|
|
serializeJson(cpmSensorPayload, mqttPayload);
|
|
mqttClient.publish(MQTT_TOPIC_AUTOCONF_CPM, mqttPayload, true);
|
|
|
|
DynamicJsonDocument usvSensorPayload(512);
|
|
|
|
usvSensorPayload["device"] = device.as<JsonObject>();
|
|
usvSensorPayload["availability_topic"] = MQTT_TOPIC_AVAILABILITY;
|
|
usvSensorPayload["state_topic"] = MQTT_TOPIC_USV;
|
|
usvSensorPayload["name"] = "uSv";
|
|
usvSensorPayload["unit_of_measurement"] = "µSv/h";
|
|
usvSensorPayload["state_class"] = "measurement";
|
|
usvSensorPayload["unique_id"] = identifier + String("_uSv");
|
|
|
|
serializeJson(usvSensorPayload, mqttPayload);
|
|
mqttClient.publish(MQTT_TOPIC_AUTOCONF_USV, mqttPayload, true);
|
|
|
|
Serial.println("Published MQTT Autoconf");
|
|
} |