Created
June 10, 2025 18:22
-
-
Save whitebrandy/a28f6a8add61ea6207f2672721eab71a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#include <WiFi.h> | |
#include <Wire.h> | |
#include <MQTT.h> | |
#define uS_TO_S_FACTOR 1000000ULL | |
#define TIME_TO_SLEEP 3600 | |
#define BUTTON_PIN_BITMASK (1ULL << GPIO_NUM_1) | |
const char* ssid = "XXX"; | |
const char* password = "XXX"; | |
const char* mqtt_server = "IP"; | |
const char* battery_topic = "backdoor/sensor/voltage"; | |
const char* battery_p_topic = "backdoor/sensor/percent"; | |
const char* lock_topic = "backdoor/sensor/lockstatus"; | |
WiFiClient net; | |
MQTTClient client; | |
int lockPin = 1; | |
int lockstatus = -1; | |
RTC_DATA_ATTR unsigned long lastUpdate = 0; | |
void(* panic_reset) (void) = 0; | |
void flickerled(void) { | |
int count; | |
int status; | |
int _delay; | |
unsigned long start = millis(); | |
unsigned long current; | |
pinMode(LED_BUILTIN, OUTPUT); | |
pinMode(lockPin, INPUT); | |
while(true) { | |
current = millis(); | |
if ((current - start) > 60000) | |
break; | |
status = !digitalRead(lockPin); | |
if (status == 0) | |
_delay = 100; | |
else | |
_delay = 1000; | |
for (int i = 0; i < 5; i++) { | |
digitalWrite(LED_BUILTIN, HIGH); | |
delay(_delay); | |
digitalWrite(LED_BUILTIN, LOW); | |
delay(_delay); | |
} | |
digitalWrite(LED_BUILTIN, LOW); | |
} | |
} | |
void initWifi() { | |
WiFi.mode(WIFI_STA); | |
WiFi.begin(ssid, password); | |
int count = 0; | |
Serial.printf("Connecting to network: %s\n", ssid); | |
while(WiFi.status() != WL_CONNECTED) { | |
Serial.print('.'); | |
Serial.print("Still trying to connect to network!"); | |
delay(100); | |
count++; | |
if (count == 100) | |
ESP.restart(); | |
} | |
Serial.println(); | |
Serial.printf("Got IP address:"); | |
Serial.println(WiFi.localIP()); | |
} | |
void print_wakeup_reason() { | |
esp_sleep_wakeup_cause_t wakeup_reason; | |
wakeup_reason = esp_sleep_get_wakeup_cause(); | |
switch(wakeup_reason) | |
{ | |
case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break; | |
case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break; | |
case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break; | |
case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break; | |
case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break; | |
default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break; | |
} | |
} | |
float get_battery_voltage() { | |
uint32_t Vbatt = 0; | |
for(int i = 0; i < 16; i++) { | |
Vbatt += analogReadMilliVolts(A0); // Read and accumulate ADC voltage | |
} | |
float Vbattf = 2 * Vbatt / 16 / 1000.0; // Adjust for 1:2 divider and convert to volts | |
Serial.println(Vbattf, 3); // Output voltage to 3 decimal places | |
delay(100); | |
return Vbattf; // Wait for 1 second | |
} | |
int get_battery_percent(float voltage) { | |
if (voltage > 4) | |
return 100; | |
if ((voltage <= 4) && (voltage > 3.95)) | |
return 95; | |
if ((voltage <= 3.95) && (voltage > 3.9)) | |
return 92; | |
if ((voltage <= 3.9) && (voltage > 3.8)) | |
return 85; | |
if ((voltage <= 3.8) && (voltage > 3.7)) | |
return 79; | |
if ((voltage <= 3.7) && (voltage > 3.6)) | |
return 61; | |
if ((voltage <= 3.6) && (voltage > 3.5)) | |
return 43; | |
if ((voltage <= 3.5) && (voltage > 3.4)) | |
return 15; | |
if ((voltage <= 3.4) && (voltage > 3.3)) | |
return 3; | |
if (voltage <= 3.3) | |
return 0; | |
} | |
void initMQTT() { | |
Serial.println("Attempting to connect to MQTT Broker at: "); | |
Serial.println(mqtt_server); | |
client.begin(mqtt_server, 1883, net); | |
int count = 0; | |
while (!client.connect("BackdoorSensor", "mqtt", "beelink")) { | |
Serial.print("."); | |
Serial.print("Backdoor MQTT still pending!"); | |
delay(100); | |
count++; | |
if (count == 100) | |
ESP.restart(); | |
} | |
Serial.println("Connected!"); | |
} | |
void SendMQTTMessage(const char *topic, char* val, int qos) { | |
Serial.printf("Publishing topic:"); | |
Serial.println(topic); | |
Serial.printf("Publishing value:"); | |
Serial.println(val); | |
for (int i=0; i < 1; i++) { | |
client.publish(topic, val, 0, qos); | |
delay(500); | |
} | |
} | |
void setup() { | |
Serial.begin(115200); | |
pinMode(A0, INPUT); // Configure A0 as ADC input | |
pinMode(lockPin, INPUT); // GPIO1 as lockstatus | |
char message[4]; | |
float voltage; | |
int percent; | |
Serial.print("Flickering LED..."); | |
flickerled(); | |
Serial.print("Flickering LED..."); | |
print_wakeup_reason(); | |
esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR); | |
Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) + | |
" Seconds"); | |
voltage = get_battery_voltage(); | |
percent = get_battery_percent(voltage); | |
dtostrf(voltage, 6, 3, message); | |
// Network part | |
initWifi(); | |
initMQTT(); | |
Serial.println("Sending Battery Topic - Voltage"); | |
SendMQTTMessage(battery_topic, message, 0); | |
dtostrf(percent,3,0,message); | |
Serial.println("Sending Battery Topic - Percent"); | |
SendMQTTMessage(battery_p_topic, message, 0); | |
lockstatus = !digitalRead(lockPin); | |
dtostrf(lockstatus,2,0,message); | |
Serial.println("Sending lock topic"); | |
SendMQTTMessage(lock_topic, message, 1); | |
if (lockstatus == 0) { //unlocked | |
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_LOW); | |
Serial.println("Sleeping to wake up on pin GPIO1 HIGH"); | |
} else { | |
esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH); | |
Serial.println("Sleeping to wake up on pin GPIO1 LOW"); | |
} | |
Serial.println("Going to sleep now"); | |
//reread lock status. We will update mqtt status on the next run | |
Serial.flush(); | |
esp_deep_sleep_start(); | |
Serial.println("This will never be printed"); | |
} | |
void loop() { | |
#if 0 | |
uint32_t Vbatt = 0; | |
for(int i = 0; i < 16; i++) { | |
Vbatt += analogReadMilliVolts(A0); // Read and accumulate ADC voltage | |
} | |
float Vbattf = 2 * Vbatt / 16 / 1000.0; // Adjust for 1:2 divider and convert to volts | |
Serial.println(Vbattf, 3); // Output voltage to 3 decimal places | |
delay(1000); // Wait for 1 second | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment