Files
Geiger-interface/geiger_interface.ino
Bartosz Mazurczak ebd10751fa add radmon support
2025-01-12 19:46:34 +01:00

402 lines
11 KiB
C++

#define ESP_DRD_USE_LITTLEFS true
#define DRD_TIMEOUT 10
#define DRD_ADDRESS 0
#define JSON_CONFIG_FILE "/config.json"
#define TUBE_NAME "J305"
#define TUBE_FACTOR 0.00812
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define i2c_Address 0x3c
#define OLED_RESET -1
#include <ESP_DoubleResetDetector.h>
#include <LittleFS.h>
#include <WiFiManager.h>
#include <FS.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <HTTPClient.h>
#include "time.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
DoubleResetDetector* drd;
WiFiClient espClient; // connection for MQTT
WiFiClient espClient2; // connection fot HTTP Client
PubSubClient client(espClient);
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Initialize LittleFS
void initLittleFS() {
if (!LittleFS.begin(true)) {
Serial.println("An error has occurred while mounting LittleFS");
}
Serial.println("LittleFS mounted successfully");
}
char mqttServer[50] = "";
char mqttUser[50] = "";
char mqttPass[50] = "";
char gmcAccountID[50] = "";
char gmcDeviceID[50] = "";
char rmUser[50] = "";
char rmPass[50] = "";
bool shouldSaveConfig = false;
char buf[10];
char buf2[10];
unsigned long time_now = 0;
unsigned long time_now2 = 0;
unsigned long mold = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis_60s = 0;
const long interval_60s = 60000;
unsigned long previousMillis_10m = 0;
const long interval_10m = 600000;
const byte interruptPin = 13;
volatile unsigned long GeigerCounts = 0;
void ICACHE_RAM_ATTR handleInterrupt() {
GeigerCounts++;
}
const char* ntpServer = "europe.pool.ntp.org";
const long gmtOffset_sec = 3600; // GMT +1 = 3600
const int daylightOffset_sec = 3600;
String GMCMap_Request_payload = "http://www.GMCmap.com/log2.asp";
String GMCMap_Request = "";
String GMCMap_Data = "";
String GMCMap = "NONE";
struct tm timeinfo;
void saveConfigFile()
{
Serial.println(F("Saving config"));
StaticJsonDocument<512> json;
json["mqttServer"] = mqttServer;
json["mqttUser"] = mqttUser;
json["mqttPass"] = mqttPass;
json["gmcAccountID"] = gmcAccountID;
json["gmcDeviceID"] = gmcDeviceID;
json["rmUser"] = rmUser;
json["rmPass"] = rmPass;
File configFile = FileFS.open(JSON_CONFIG_FILE, "w");
if (!configFile)
{
Serial.println("failed to open config file for writing");
}
serializeJsonPretty(json, Serial);
if (serializeJson(json, configFile) == 0)
{
Serial.println(F("Failed to write to file"));
}
configFile.close();
}
bool loadConfigFile()
{
//read configuration from FS json
Serial.println("mounting FS...");
if (FileFS.begin(false) || FileFS.begin(true))
{
Serial.println("mounted file system");
if (FileFS.exists(JSON_CONFIG_FILE))
{
//file exists, reading and loading
Serial.println("reading config file");
File configFile = FileFS.open(JSON_CONFIG_FILE, "r");
if (configFile)
{
Serial.println("opened config file");
StaticJsonDocument<512> json;
DeserializationError error = deserializeJson(json, configFile);
serializeJsonPretty(json, Serial);
if (!error)
{
Serial.println("\nparsed json");
strcpy(mqttServer, json["mqttServer"]);
strcpy(mqttUser, json["mqttUser"]);
strcpy(mqttPass, json["mqttPass"]);
strcpy(gmcAccountID, json["gmcAccountID"]);
strcpy(gmcDeviceID, json["gmcDeviceID"]);
strcpy(rmUser, json["rmUser"]);
strcpy(rmPass, json["rmPass"]);
return true;
}
else
{
Serial.println("failed to load json config");
}
}
}
}
else
{
Serial.println("failed to mount FS");
}
//end read
return false;
}
void saveConfigCallback()
{
Serial.println("Should save config");
shouldSaveConfig = true;
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("GeigerClient")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void lcdPrint(String x) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setCursor(0, 10);
display.println(x);
display.display();
}
void lcdUpdate() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SH110X_WHITE);
display.setCursor(0, 0);
display.println(printLocalTime());
display.println("uSv/h: " + String(buf2));
display.println("CPM: " + String(buf));
display.display();
}
String printLocalTime()
{
//if(!getLocalTime(&timeinfo)){
// Serial.println("Failed to obtain time");
// return "Failed to obtain time";
//}
char buffer[80];
//strftime(buffer, 80, "%H:%M:%S %d-%m-%Y ", &timeinfo);
strftime(buffer, 80, "%H:%M <|> %d-%m-%Y ", &timeinfo);
return String(buffer);
}
void radmonUpload(int cpm) {
const char *cmdFormat = "http://radmon.org/radmon.php?function=submit&user=%s&password=%s&value=%d&unit=CPM";
char url[256];
HTTPClient http2;
// create the request URL
sprintf(url, cmdFormat, rmUser, rmPass, cpm);
Serial.print("[HTTP] begin: ");
Serial.println(url);
if (http2.begin(espClient2, url)) {
Serial.print("[HTTP] GET...");
// start connection and send HTTP header
int httpCode = http2.GET();
// HTTP header has been sent and server response header has been handled
Serial.printf(" code: %d\n", httpCode);
// httpCode will be negative on error
if (httpCode > 0) {
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http2.getString();
Serial.println(payload);
}
}
else {
Serial.printf("[HTTP] GET failed, error: %s\n", http2.errorToString(httpCode).c_str());
}
http2.end();
}
}
void setup() {
// WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
// it is a good practice to make sure your code sets wifi mode how you want it.
Serial.begin(115200);
pinMode( interruptPin, INPUT );
attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, FALLING );
initLittleFS();
display.begin(i2c_Address, true);
lcdPrint("Geiger Interace");
drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS);
bool forceConfig = false;
if (drd->detectDoubleReset()) {
Serial.println("Double Reset Detected");
forceConfig = true;
}
WiFiManager wm;
wm.setSaveConfigCallback(saveConfigCallback);
WiFiManagerParameter custom_mqttServer("mqttServer", "MQTT Server", mqttServer, 50);
WiFiManagerParameter custom_mqttUser("mqttUser", "MQTT User", mqttUser, 50);
WiFiManagerParameter custom_mqttPass("mqttPass", "MQTT Password", mqttPass, 50);
WiFiManagerParameter custom_gmcAccountID("gmcAccountID", "GMC MAP Account ID", gmcAccountID, 50);
WiFiManagerParameter custom_gmcDeviceID("gmcDeviceID", "GMC MAP Device ID", gmcDeviceID, 50);
WiFiManagerParameter custom_rmUser("rmUser", "RadMon User", rmUser, 50);
WiFiManagerParameter custom_rmPass("rmPass", "RadMon Password", rmPass, 50);
wm.addParameter(&custom_mqttServer);
wm.addParameter(&custom_mqttUser);
wm.addParameter(&custom_mqttPass);
wm.addParameter(&custom_gmcAccountID);
wm.addParameter(&custom_gmcDeviceID);
wm.addParameter(&custom_rmUser);
wm.addParameter(&custom_rmPass);
// wm.resetSettings();
bool res;
res = wm.autoConnect();
if (!res) {
Serial.println("Failed to connect");
// ESP.restart();
} else {
Serial.println("connected...yeey :)");
if (forceConfig)
{
if (!wm.startConfigPortal())
{
Serial.println("failed to connect and hit timeout");
delay(3000);
ESP.restart();
delay(5000);
}
}
}
strcpy(mqttServer, custom_mqttServer.getValue());
strcpy(mqttUser, custom_mqttUser.getValue());
strcpy(mqttPass, custom_mqttPass.getValue());
strcpy(gmcAccountID, custom_gmcAccountID.getValue());
strcpy(gmcDeviceID, custom_gmcDeviceID.getValue());
strcpy(rmUser, custom_rmUser.getValue());
strcpy(rmPass, custom_rmPass.getValue());
Serial.println("The values in the file are: ");
Serial.println("\tmqtt_server : " + String(mqttServer));
Serial.println("\tmqtt_user : " + String(mqttUser));
Serial.println("\tmqtt_pass : " + String(mqttPass));
Serial.println("\tgmc_AccountID : " + String(gmcAccountID));
Serial.println("\tgmc_DeviceID : " + String(gmcDeviceID));
Serial.println("\trm_User : " + String(rmUser));
Serial.println("\trm_Pass : " + String(rmPass));
if (shouldSaveConfig)
{
Serial.println("saving config");
saveConfigFile();
}
loadConfigFile();
client.setServer(mqttServer, 1883);
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
}
void loop() {
drd->loop();
// if MQTT server provided
if (String(mqttServer) != "") {
if (!client.connected()) {
reconnect();
}
if(millis() >= time_now + 5000){
time_now += 5000;
client.publish("esp32/heartbeat", "PING");
}
if (millis() >= mold + 60000) {
ltoa(GeigerCounts, buf, 10);
dtostrf(GeigerCounts*TUBE_FACTOR, -4, 2, buf2);
client.publish("esp32/CPM", buf);
client.publish("esp32/uSv", buf2);
GeigerCounts = 0;
mold += 60000;
lcdUpdate();
}
client.loop();
}
getLocalTime(&timeinfo);
if (timeinfo.tm_sec == 0){
lcdUpdate();
}
// if GMC IDs provided
if (String(gmcAccountID) != "") {
currentMillis = millis();
if (currentMillis - previousMillis_10m >= interval_10m) {
previousMillis_10m = currentMillis;
Serial.print("[HTTP] begin...\n");
GMCMap_Request = GMCMap_Request_payload + "?AID=" + gmcAccountID + "&GID=" + gmcDeviceID + "&CPM=" + buf + "&ACPM=" + buf + "&uSV=" + buf2;
Serial.println(GMCMap_Request);
HTTPClient http;
if (http.begin(espClient2, GMCMap_Request)) { // HTTP
Serial.print("[HTTP] GET...\n");
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
if (payload.indexOf("ERR0") > 0) GMCMap = "OK";
if (payload.indexOf("ERR1") > 0) GMCMap = "Error! User is not found";
if (payload.indexOf("ERR2") > 0) GMCMap = "Error! Geiger Counter is not found";
if (payload.indexOf("Warning") > 0) GMCMap = "Warning! The Geiger Counter location changed, please confirm the location";
Serial.println(GMCMap);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
GMCMap = http.errorToString(httpCode).c_str();
}
http.end();
} else {
Serial.println("[HTTP] Unable to connect");
GMCMap = "Unable to connect";
}
}
}
}