2015-12-23 22:49:57 +01:00
|
|
|
#include <ESP8266WiFi.h>
|
2017-03-05 17:32:39 +01:00
|
|
|
#include <ArduinoOTA.h>
|
2020-06-28 14:36:37 +02:00
|
|
|
#include <SoftwareSerial.h>
|
|
|
|
#include <DNSServer.h>
|
|
|
|
#include <ESP8266WebServer.h>
|
|
|
|
|
|
|
|
#include "dep/pubsubclient-2.7/src/PubSubClient.cpp"
|
|
|
|
#include "dep/WiFiManager-0.15.0/WiFiManager.cpp"
|
|
|
|
#include "dep/SimpleTimer-schinken/SimpleTimer.cpp"
|
|
|
|
|
2015-12-23 22:49:57 +01:00
|
|
|
|
|
|
|
#include "settings.h"
|
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
#ifdef USE_HA_AUTODISCOVERY
|
|
|
|
#define FIRMWARE_PREFIX "esp8266-geigercounter"
|
|
|
|
char MQTT_TOPIC_LAST_WILL[128];
|
|
|
|
char MQTT_TOPIC_CPM_MEASUREMENT[128];
|
|
|
|
char MQTT_TOPIC_USV_MEASUREMENT[128];
|
|
|
|
#endif
|
|
|
|
|
2015-12-23 22:49:57 +01:00
|
|
|
WiFiClient wifiClient;
|
|
|
|
PubSubClient mqttClient;
|
|
|
|
SoftwareSerial geigerCounterSerial(PIN_UART_RX, PIN_UART_TX);
|
|
|
|
SimpleTimer timer;
|
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
uint8_t mqttRetryCounter = 0;
|
2015-12-23 22:49:57 +01:00
|
|
|
String serialInput = "";
|
|
|
|
char serialInputHelper[RECV_LINE_SIZE];
|
|
|
|
|
|
|
|
int lastCPM = 0, currentCPM = 0;
|
|
|
|
float lastuSv = 0, currentuSv = 0;
|
|
|
|
|
2020-09-23 13:10:11 +02:00
|
|
|
char hostname[24];
|
2016-02-20 22:21:44 +01:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
void setup() {
|
2020-06-28 15:58:05 +02:00
|
|
|
delay(3000);
|
2015-12-23 22:49:57 +01:00
|
|
|
Serial.begin(115200);
|
2020-06-28 15:58:05 +02:00
|
|
|
delay(2000);
|
2020-06-28 14:36:37 +02:00
|
|
|
Serial.println("\n");
|
|
|
|
Serial.println("Hello from esp8266-geigercounter");
|
2020-06-28 15:58:05 +02:00
|
|
|
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());
|
|
|
|
delay(3000);
|
2020-06-28 14:36:37 +02:00
|
|
|
|
2015-12-23 22:49:57 +01:00
|
|
|
geigerCounterSerial.begin(BAUD_GEIGERCOUNTER);
|
2017-03-11 11:39:51 +01:00
|
|
|
|
2020-06-28 15:58:05 +02:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
int32_t chipid = ESP.getChipId();
|
|
|
|
|
|
|
|
Serial.print("MQTT_MAX_PACKET_SIZE: ");
|
|
|
|
Serial.println(MQTT_MAX_PACKET_SIZE);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HOSTNAME
|
2020-09-23 13:10:11 +02:00
|
|
|
strncpy(hostname, HOSTNAME, sizeof(hostname));
|
2020-06-28 14:36:37 +02:00
|
|
|
#else
|
2020-09-23 13:10:11 +02:00
|
|
|
snprintf(hostname, sizeof(hostname), "GEIGERCTR-%X", chipid);
|
2020-06-28 14:36:37 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef USE_HA_AUTODISCOVERY
|
|
|
|
snprintf(MQTT_TOPIC_LAST_WILL, 127, "%s/%s/presence", FIRMWARE_PREFIX, hostname);
|
|
|
|
snprintf(MQTT_TOPIC_CPM_MEASUREMENT, 127, "%s/%s/%s_%s/state", FIRMWARE_PREFIX, hostname, hostname, "cpm");
|
|
|
|
snprintf(MQTT_TOPIC_USV_MEASUREMENT, 127, "%s/%s/%s_%s/state", FIRMWARE_PREFIX, hostname, hostname, "uSv");
|
|
|
|
#endif
|
2015-12-23 22:49:57 +01:00
|
|
|
|
2020-06-28 15:58:05 +02:00
|
|
|
Serial.print("Connecting to WiFi");
|
|
|
|
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
unsigned long wifiConnectStart = millis();
|
|
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
|
|
if (WiFi.status() == WL_CONNECT_FAILED) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (millis() - wifiConnectStart > 10000) {
|
|
|
|
WiFiManager wifiManager;
|
|
|
|
#ifdef CONF_WIFI_PASSWORD
|
|
|
|
wifiManager.autoConnect(hostname, CONF_WIFI_PASSWORD);
|
|
|
|
#else
|
|
|
|
wifiManager.autoConnect(hostname);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
delay(100);
|
|
|
|
Serial.print(".");
|
|
|
|
}
|
|
|
|
|
|
|
|
Serial.print("\nIP: ");
|
|
|
|
Serial.println(WiFi.localIP());
|
2020-06-28 14:36:37 +02:00
|
|
|
|
|
|
|
WiFi.hostname(hostname);
|
2017-03-05 17:32:39 +01:00
|
|
|
mqttClient.setClient(wifiClient);
|
2017-03-11 11:39:51 +01:00
|
|
|
mqttClient.setServer(MQTT_HOST, 1883);
|
2020-06-28 14:36:37 +02:00
|
|
|
|
|
|
|
ArduinoOTA.setHostname(hostname);
|
2017-03-05 17:32:39 +01:00
|
|
|
ArduinoOTA.setPassword(OTA_PASSWORD);
|
|
|
|
ArduinoOTA.begin();
|
2015-12-23 22:49:57 +01:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
Serial.print("Hostname: ");
|
|
|
|
Serial.println(hostname);
|
|
|
|
|
|
|
|
Serial.println("-- Current GPIO Configuration --");
|
|
|
|
Serial.print("PIN_UART_RX: ");
|
|
|
|
Serial.println(PIN_UART_RX);
|
|
|
|
|
|
|
|
mqttConnect();
|
2015-12-23 23:18:40 +01:00
|
|
|
timer.setInterval(UPDATE_INTERVAL_SECONDS * 1000L, updateRadiationValues);
|
2015-12-23 22:49:57 +01:00
|
|
|
}
|
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
void mqttConnect() {
|
|
|
|
while (!mqttClient.connected()) {
|
|
|
|
|
|
|
|
bool mqttConnected = false;
|
|
|
|
if (MQTT_USERNAME && MQTT_PASSWORD) {
|
|
|
|
mqttConnected = mqttClient.connect(hostname, MQTT_USERNAME, MQTT_PASSWORD, MQTT_TOPIC_LAST_WILL, 1, true, MQTT_LAST_WILL_PAYLOAD_DISCONNECTED);
|
|
|
|
} else {
|
|
|
|
mqttConnected = mqttClient.connect(hostname, MQTT_TOPIC_LAST_WILL, 1, true, MQTT_LAST_WILL_PAYLOAD_DISCONNECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mqttConnected) {
|
|
|
|
Serial.println("Connected to MQTT Broker");
|
|
|
|
mqttClient.publish(MQTT_TOPIC_LAST_WILL, MQTT_LAST_WILL_PAYLOAD_CONNECTED, true);
|
|
|
|
mqttRetryCounter = 0;
|
|
|
|
|
|
|
|
#ifdef USE_HA_AUTODISCOVERY
|
|
|
|
setupHAAutodiscovery();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
} else {
|
|
|
|
Serial.println("Failed to connect to MQTT Broker");
|
|
|
|
|
|
|
|
if (mqttRetryCounter++ > MQTT_MAX_CONNECT_RETRY) {
|
|
|
|
Serial.println("Restarting uC");
|
|
|
|
ESP.restart();
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(2000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-23 22:49:57 +01:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
#ifdef USE_HA_AUTODISCOVERY
|
|
|
|
#define AUTOCONFIG_PAYLOAD_TPL_USV "{\
|
|
|
|
\"stat_t\":\"%s/%s/%s_uSv/state\",\
|
|
|
|
\"avty_t\":\"%s/%s/presence\",\
|
|
|
|
\"unique_id\":\"%s_uSv\",\
|
|
|
|
\"name\":\"%s uSv\",\
|
|
|
|
\"unit_of_meas\":\"µSv/h\",\
|
|
|
|
\"dev\": {\
|
|
|
|
\"identifiers\":\"%s\",\
|
|
|
|
\"name\":\"%s\",\
|
|
|
|
\"manufacturer\":\"MightyOhm LLC\",\
|
|
|
|
\"model\":\"Geiger Counter\"\
|
|
|
|
}\
|
|
|
|
}"
|
|
|
|
#define AUTOCONFIG_PAYLOAD_TPL_CPM "{\
|
|
|
|
\"stat_t\":\"%s/%s/%s_cpm/state\",\
|
|
|
|
\"avty_t\":\"%s/%s/presence\",\
|
|
|
|
\"unique_id\":\"%s_cpm\",\
|
|
|
|
\"name\":\"%s CPM\",\
|
|
|
|
\"unit_of_meas\":\"CPM\",\
|
|
|
|
\"dev\": {\
|
|
|
|
\"identifiers\":\"%s\",\
|
|
|
|
\"name\":\"%s\",\
|
|
|
|
\"manufacturer\":\"MightyOhm LLC\",\
|
|
|
|
\"model\":\"Geiger Counter\"\
|
|
|
|
}\
|
|
|
|
}"
|
|
|
|
|
|
|
|
void setupHAAutodiscovery() {
|
|
|
|
char autoconfig_topic_cpm[128];
|
|
|
|
char autoconfig_payload_cpm[1024];
|
|
|
|
char autoconfig_topic_usv[128];
|
|
|
|
char autoconfig_payload_usv[1024];
|
|
|
|
|
|
|
|
snprintf(
|
|
|
|
autoconfig_topic_cpm,
|
|
|
|
127,
|
|
|
|
"%s/sensor/%s/%s_cpm/config",
|
|
|
|
HA_DISCOVERY_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname
|
|
|
|
);
|
|
|
|
|
|
|
|
snprintf(
|
|
|
|
autoconfig_topic_usv,
|
|
|
|
127,
|
|
|
|
"%s/sensor/%s/%s_usv/config",
|
|
|
|
HA_DISCOVERY_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname
|
|
|
|
);
|
|
|
|
|
|
|
|
snprintf(
|
|
|
|
autoconfig_payload_cpm,
|
|
|
|
1023,
|
|
|
|
|
|
|
|
AUTOCONFIG_PAYLOAD_TPL_CPM,
|
|
|
|
|
|
|
|
FIRMWARE_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
FIRMWARE_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname
|
|
|
|
);
|
|
|
|
|
|
|
|
snprintf(
|
|
|
|
autoconfig_payload_usv,
|
|
|
|
1023,
|
|
|
|
|
|
|
|
AUTOCONFIG_PAYLOAD_TPL_USV,
|
|
|
|
|
|
|
|
FIRMWARE_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
FIRMWARE_PREFIX,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname,
|
|
|
|
hostname
|
|
|
|
);
|
|
|
|
|
|
|
|
if(
|
|
|
|
mqttClient.publish(autoconfig_topic_cpm, autoconfig_payload_cpm, true) &&
|
|
|
|
mqttClient.publish(autoconfig_topic_usv, autoconfig_payload_usv, true)
|
|
|
|
){
|
|
|
|
Serial.println("Autoconf publish successful");
|
|
|
|
} else {
|
|
|
|
Serial.println("Autoconf publish failed. Is MQTT_MAX_PACKET_SIZE large enough?");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
timer.run();
|
|
|
|
mqttConnect();
|
|
|
|
mqttClient.loop();
|
2020-06-28 15:58:05 +02:00
|
|
|
ESP.wdtFeed();
|
2020-06-28 14:36:37 +02:00
|
|
|
|
|
|
|
if (geigerCounterSerial.available()) {
|
|
|
|
char in = (char) geigerCounterSerial.read();
|
|
|
|
|
|
|
|
serialInput += in;
|
|
|
|
|
|
|
|
if (in == '\n') {
|
|
|
|
serialInput.toCharArray(serialInputHelper, RECV_LINE_SIZE);
|
|
|
|
parseReceivedLine(serialInputHelper);
|
|
|
|
|
|
|
|
serialInput = "";
|
|
|
|
}
|
2015-12-23 22:49:57 +01:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
// Just in case the buffer gets to big, start from scratch
|
|
|
|
if (serialInput.length() > RECV_LINE_SIZE + 10) {
|
|
|
|
serialInput = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
Serial.write(in);
|
|
|
|
}
|
2020-06-28 15:58:05 +02:00
|
|
|
|
2020-06-28 14:36:37 +02:00
|
|
|
ArduinoOTA.handle();
|
|
|
|
}
|
|
|
|
|
|
|
|
void updateRadiationValues() {
|
2016-02-20 22:21:44 +01:00
|
|
|
char tmp[8];
|
|
|
|
|
|
|
|
if (currentCPM != lastCPM) {
|
|
|
|
String(currentCPM).toCharArray(tmp, 8);
|
2020-06-28 14:36:37 +02:00
|
|
|
Serial.print("Sending CPM: ");
|
2016-02-20 22:21:44 +01:00
|
|
|
Serial.println(tmp);
|
2020-06-28 14:36:37 +02:00
|
|
|
mqttClient.publish(MQTT_TOPIC_CPM_MEASUREMENT, tmp, true);
|
2016-02-20 22:21:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (currentuSv != lastuSv) {
|
|
|
|
String(currentuSv).toCharArray(tmp, 8);
|
2020-06-28 14:36:37 +02:00
|
|
|
Serial.print("Sending uSv: ");
|
2016-02-20 22:21:44 +01:00
|
|
|
Serial.println(tmp);
|
2020-06-28 14:36:37 +02:00
|
|
|
mqttClient.publish(MQTT_TOPIC_USV_MEASUREMENT, tmp, true);
|
2016-02-20 22:21:44 +01:00
|
|
|
}
|
2015-12-23 22:49:57 +01:00
|
|
|
|
2016-02-20 22:21:44 +01:00
|
|
|
lastCPM = currentCPM;
|
|
|
|
lastuSv = currentuSv;
|
2015-12-23 22:49:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void parseReceivedLine(char* input) {
|
2016-02-20 22:21:44 +01:00
|
|
|
|
|
|
|
char segment = 0;
|
|
|
|
char *token;
|
|
|
|
|
|
|
|
float uSv = 0;
|
|
|
|
float cpm = 0;
|
|
|
|
|
|
|
|
token = strtok(input, delimiter);
|
|
|
|
|
|
|
|
while (token != NULL) {
|
|
|
|
|
|
|
|
switch (segment) {
|
|
|
|
|
|
|
|
// This is just for validation
|
|
|
|
case IDX_CPS_KEY: if (strcmp(token, "CPS") != 0) return; break;
|
|
|
|
case IDX_CPM_KEY: if (strcmp(token, "CPM") != 0) return; break;
|
|
|
|
case IDX_uSv_KEY: if (strcmp(token, "uSv/hr") != 0) return; break;
|
|
|
|
|
|
|
|
case IDX_CPM:
|
2020-06-28 15:58:05 +02:00
|
|
|
Serial.printf("\nCurrent CPM: %s\n", token);
|
2016-02-20 22:21:44 +01:00
|
|
|
cpm = String(token).toInt();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case IDX_uSv:
|
|
|
|
Serial.printf("Current uSv/hr: %s\n", token);
|
|
|
|
uSv = String(token).toFloat();
|
|
|
|
break;
|
2015-12-23 22:49:57 +01:00
|
|
|
}
|
|
|
|
|
2016-02-20 22:21:44 +01:00
|
|
|
if (segment > 7) {
|
|
|
|
// Invalid! There should be no more than 7 segments
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
token = strtok(NULL, delimiter);
|
|
|
|
segment++;
|
|
|
|
}
|
|
|
|
|
|
|
|
currentuSv = uSv;
|
|
|
|
currentCPM = cpm;
|
2020-06-28 15:58:05 +02:00
|
|
|
}
|