Light_controller_box/Light_Controller.ino
2025-05-23 10:27:05 +10:00

769 lines
30 KiB
C++

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <FastLED.h> // Include the FastLED library
#include "esp_sleep.h" // Include ESP-IDF deep sleep functions
#include <WiFi.h> // Include WiFi library
#include <PubSubClient.h> // Include PubSubClient library
#include <ArduinoJson.h> // Include ArduinoJson library for creating JSON (install via Library Manager)
// Define the pins for our analog inputs
const int colorSliderPin = 32; // ESP32 pin connected to the color slider (one pot)
const int brightnessPotPin = 34; // ESP32 pin connected to the brightness potentiometer
// Define the pins for our digital inputs (buttons)
const int ttpButton0Pin = 27; // ESP32 pin connected to the HTTM Capacitive Button (On/Off)
const int ttpButton1Pin = 26; // ESP32 pin connected to the TTP223 Touch Key Button (Target 1)
const int ttpButton2Pin = 25; // ESP32 pin connected to the TTP223 Touch Key Button (Target 2)
const int ttpButton3Pin = 4; // ESP32 pin connected to the TTP223 Touch Key Button (Target 3)
const int ttpButton4Pin = 12;
const int ttpButton5Pin = 15;
// Define the OLED display parameters
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset)
#define SCREEN_ADDRESS 0x3C // I2C address
// Create an Adafruit_SSD1306 display object
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Define the FastLED parameters
#define LED_PIN 13 // ESP32 pin connected to the LED strip data input
#define NUM_LEDS 8 // Number of LEDs in your strip
#define LED_TYPE WS2812B // Your LED strip type
#define COLOR_ORDER GRB // Color order (often GRB for WS2812B)
// Define the array of leds
CRGB leds[NUM_LEDS];
// Variables to store button states
int lastTtpButton0State = HIGH;
int lastTtpButton1State = HIGH;
int lastTtpButton2State = HIGH;
int lastTtpButton3State = HIGH;
int lastTtpButton4State = HIGH;
int lastTtpButton5State = HIGH;
// Variables to store current color and brightness values (RGB 0-255) - Global state
int currentRed = 0;
int currentGreen = 0;
int currentBlue = 0;
int currentBrightness = 0; // Brightness (0-255) - Global state
// Variables to track the current range/section of analog inputs
int currentColorRange = -1; // An index representing the current color/white section
// Variables to store the last range/section that triggered a color update
int lastUpdatedColorRange = -1;
// Define the boundaries for color/white sections (adjust these based on your 2 white + 10 colors = 12 sections)
// Assuming raw analog values from 0 to 4095
const int colorRangeBoundaries[] = {
0, // Start of Warm White Range (Range 0)
400, // End of Warm White Range, Start of Basic White Range (Range 1)
800, // End of Basic White Range, Start of Color 1 (Red) Range (Range 2)
1200, // End of Color 1, Start of Color 2 (Orange) Range (Range 3)
1600, // End of Color 2, Start of Color 3 (Yellow) Range (Range 4)
2000, // End of Color 3, Start of Color 4 (Green) Range (Range 5)
2400, // End of Color 4, Start of Color 5 (Blue) Range (Range 6)
2800, // End of Color 5, Start of Color 6 (Indigo) Range (Range 7)
3200, // End of Color 6, Start of Color 7 (Violet) Range (Range 8)
3600, // End of Color 7, Start of Color 8 Range (Range 9)
4000, // End of Color 8, Start of Color 9 Range (Range 10)
4096 // End of Color 9 Range (Range 11) - Use 4096 as the upper boundary of the last range
};
const int numColorRanges = sizeof(colorRangeBoundaries) / sizeof(colorRangeBoundaries[0]) - 1; // Number of defined ranges (12 in this example)
// Define the RGB values for the start of each color/white range
// This array should have 'numColorRanges' number of entries
struct ColorRange {
int r, g, b;
int colorTemp;
};
// 3. Replace your existing color definitions with these:
const ColorRange colorRangeRGB[] = {
{255, 137, 14, 2200}, // Warm White - Very warm, cozy
{255, 255, 255, 4000}, // Natural White - Clean, neutral
{255, 0, 0, 2700}, // Red - Warm, rich
{255, 165, 0, 3000}, // Orange - Warm, energetic
{255, 255, 0, 3500}, // Yellow - Neutral warm
{0, 255, 0, 5000}, // Green - Cool, natural
{0, 0, 255, 6500}, // Blue - Cool, crisp
{75, 0, 130, 6000}, // Indigo - Cool, deep
{148, 0, 211, 5500}, // Violet - Cool, rich
{255, 0, 127, 3200}, // Pink - Warm, vibrant
{255, 193, 141, 2700}, // Warm Peach
{255, 255, 224, 2500} // Light Warm
};
// Variables for analog input debouncing and sleep timer
unsigned long lastInteractionTime = 0; // Time of the last interaction (analog change or button press)
const unsigned long analogSendDelay = 1000; // Delay in milliseconds before sending analog data after stabilization
const unsigned long sleepDelay = 10000; // Delay in milliseconds before entering sleep (10 seconds)
// Variable to store the currently selected light target (as an integer)
int currentTargetIndex = 0; // 0: White Lamp, 1: Pink Lamp, 2: Desk Lamp
// Array of target names corresponding to the integer index
const char* targetNames[] = {"sam_bed", "jo_bed", "main_light","lounge_lights","all_lights"};
const char* displayNames[] = {"Sams Bed", "Joes Bed", "Main Light","Lounge Lights", "All Lights"};
const int numTargets = sizeof(targetNames) / sizeof(targetNames[0]); // Automatically calculate number of targets
// RTC memory variables (will retain value during deep sleep)
// We need to define these outside any function and use the RTC_DATA_ATTR macro
RTC_DATA_ATTR int savedRed = 0;
RTC_DATA_ATTR int savedGreen = 0;
RTC_DATA_ATTR int savedBlue = 0;
RTC_DATA_ATTR int savedBrightness = 0;
RTC_DATA_ATTR int savedTargetIndex = 0; // Store the integer index in RTC memory
RTC_DATA_ATTR bool savedLightStates[5] = {false, false, false, false, false};
// WiFi and MQTT credentials and topics
const char* ssid = "Aussie Broadband 8729"; // Replace with your SSID
const char* password = "Ffdfmunfca"; // Replace with your WiFi password
const char* mqtt_server = "192.168.20.30"; // Replace with your MQTT broker IP/hostname
const char* mqtt_user = "mqtt-user"; // Replace with your MQTT username (if any)
const char* mqtt_password = "sam4jo"; // Replace with your MQTT password (if any)
// MQTT Topics
const char* mqtt_topic_publish = "homeassistant/lights/change"; // Topic to publish status FROM LoRa devices (we are sending control commands)
// WiFi and MQTT client objects
WiFiClient espClient;
PubSubClient client(espClient);
// Flag to track if a debounced analog update is pending MQTT send
bool analogUpdatePendingSend = false;
// Variables to store the last MAPPED analog values that were SENT via MQTT
int lastSentRed = -1, lastSentGreen = -1, lastSentBlue = -1, lastSentBrightness = -1;
unsigned long lastAnalogSendTime = 0; // Time the last analog MQTT message was sent
// Variables to track the last RAW analog readings that caused a brightness update
int lastUpdatedRawBrightness = -1;
// Define the threshold for change in RAW brightness values
const int rawBrightnessChangeThreshold = 60; // Example threshold, adjust as needed (4096 / 256 = 16 for 0-255 mapped steps)
bool lightStates[5] = {false, false, false, false, false};
void setup() {
delay(500);
Serial.begin(115200);
// Set pin modes for analog inputs
pinMode(colorSliderPin, INPUT);
pinMode(brightnessPotPin, INPUT);
// Set pin modes for digital inputs (buttons)
pinMode(ttpButton0Pin, INPUT_PULLUP); // HTTM button uses INPUT
pinMode(ttpButton1Pin, INPUT_PULLUP); // TTP button likely needs pull-up
pinMode(ttpButton2Pin, INPUT_PULLUP); // TTP button likely needs pull-up
pinMode(ttpButton3Pin, INPUT_PULLUP); // TTP button likely needs pull-up
pinMode(ttpButton4Pin, INPUT_PULLUP); // TTP button likely needs pull-up
pinMode(ttpButton5Pin, INPUT_PULLUP); // TTP button likely needs pull-up
// --- Configure Wake-up Sources ---
const uint64_t wakeup_pin_mask = (1ULL << ttpButton0Pin) | (1ULL << ttpButton1Pin) | (1ULL << ttpButton2Pin) | (1ULL << ttpButton3Pin) | (1ULL << ttpButton4Pin) | (1ULL << ttpButton5Pin);
// Using ANY_HIGH as it compiles in your environment
esp_sleep_enable_ext1_wakeup(wakeup_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
// --- Check Wake-up Cause ---
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
if (wakeup_cause == ESP_SLEEP_WAKEUP_EXT1) {
Serial.println("Wakeup cause: EXT1 (Button)");
for(int i = 0; i < 5; i++) {
lightStates[i] = savedLightStates[i];
}
// Restore state from RTC memory
currentRed = savedRed;
currentGreen = savedGreen;
currentBlue = savedBlue;
currentBrightness = savedBrightness;
currentTargetIndex = savedTargetIndex; // Restore the integer index
// Add a small delay after waking up to help prevent immediate re-triggering
delay(100);
} else if (wakeup_cause == ESP_SLEEP_WAKEUP_TIMER) {
Serial.println("Wakeup cause: Timer");
} else {
Serial.println("Wakeup cause: Other (e.g., Power On Reset)");
// Initialize state if not woken from sleep
currentRed = 0;
currentGreen = 0;
currentBlue = 0;
currentBrightness = 0;
currentTargetIndex = 0; // Default to the first target (White Lamp)
}
// Initialize lastSentMapped values for fresh start or after restore
lastSentRed = currentRed;
lastSentGreen = currentGreen;
lastSentBlue = currentBlue;
lastSentBrightness = currentBrightness;
Serial.println("Starting peripheral test...");
// Initialize the OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
display.clearDisplay();
display.display();
// Initialize the FastLED strip
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
// Set initial brightness based on restored/initial state
FastLED.setBrightness(currentBrightness);
// Set initial color based on restored/initial state
CRGB initialColor = CRGB(currentRed, currentGreen, currentBlue);
fill_solid(leds, NUM_LEDS, initialColor);
FastLED.show(); // Turn off all pixels initially (or show restored state)
// Set text size, color, and cursor position
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
// Display initial message on the OLED including the target name
display.println("Peripheral Test");
display.print("Target: ");
display.println(displayNames[currentTargetIndex]); // Use the display name from the array
display.println("Move controls");
display.println("Press buttons");
display.display();
// Initial display with restored state might take some time.
// No delay needed here for the initial display.
// Initialize lastInteractionTime to current time to prevent immediate sleep
lastInteractionTime = millis();
// --- WiFi and MQTT Setup ---
Serial.println("Connecting to WiFi...");
WiFi.begin(ssid, password);
// Wait for WiFi connection (add a timeout in a real application)
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
client.setServer(mqtt_server, 1883); // Default MQTT port is 1883
// client.setCallback(callback); // Not needed for this application (only publishing)
// Attempt to connect to MQTT broker
reconnectMQTT();
}
// Function to reconnect to MQTT broker
void reconnectMQTT() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect with authentication
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) { // Use a unique client ID
Serial.println("connected");
// Subscribe to topics if needed (not needed for this project based on topics provided)
// client.subscribe(mqtt_topic_subscribe);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" trying again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// Function to publish MQTT message in JSON format
void publishMQTT(int red, int green, int blue, int brightness, const char* targetName, const char* command = NULL) {
if (!client.connected()) {
reconnectMQTT();
}
StaticJsonDocument<128> doc;
if (command != NULL) {
doc["command"] = command;
}
doc["target"] = targetName;
if (command == NULL) {
// Send both color_temp and xy coordinates
doc["color_temp"] = colorRangeRGB[lastUpdatedColorRange].colorTemp;
float x, y;
RGBtoXY(red, green, blue, x, y);
JsonArray xy_color = doc.createNestedArray("xy_color");
xy_color.add(x);
xy_color.add(y);
doc["brightness"] = brightness;
doc["state"] = "ON";
// Update tracked state
for(int i = 0; i < numTargets; i++) {
if(strcmp(targetName, targetNames[i]) == 0) {
lightStates[i] = true;
break;
}
}
}
char jsonBuffer[128];
size_t jsonSize = serializeJson(doc, jsonBuffer);
Serial.print("Attempting to publish JSON payload to topic: ");
Serial.println(mqtt_topic_publish);
Serial.print("Raw JSON payload (");
Serial.print(jsonSize);
Serial.print(" bytes): [");
for (size_t i = 0; i < jsonSize; i++) {
Serial.print(jsonBuffer[i]);
}
Serial.println("]");
if (client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, jsonSize)) {
Serial.println("MQTT message published successfully.");
} else {
Serial.println("MQTT message publishing failed.");
}
}
void RGBtoXY(int r, int g, int b, float &x, float &y) {
float red = r / 255.0f;
float green = g / 255.0f;
float blue = b / 255.0f;
float X = red * 0.649926 + green * 0.103455 + blue * 0.197109;
float Y = red * 0.234327 + green * 0.743075 + blue * 0.022598;
float Z = red * 0.0000000 + green * 0.053077 + blue * 1.035763;
float sum = X + Y + Z;
if (sum > 0) {
x = X / sum;
y = Y / sum;
} else {
x = 0.312;
y = 0.329;
}
}
void loop() {
if (!client.connected()) {
reconnectMQTT(); // Ensure MQTT connection is maintained
}
client.loop(); // MQTT client loop to process incoming/outgoing messages
// --- Read Raw Analog Values ---
int rawColorValue = analogRead(colorSliderPin);
int rawBrightnessValue = analogRead(brightnessPotPin);
// --- Determine Current Color Range ---
int newColorRange = -1;
for (int i = 0; i < numColorRanges; i++) {
if (rawColorValue >= colorRangeBoundaries[i] && rawColorValue < colorRangeBoundaries[i + 1]) {
newColorRange = i;
break; // Found the range, exit the loop
}
}
// Handle the case where the value is at the very end of the range
if (rawColorValue == 4095) {
newColorRange = numColorRanges -1; // Assign to the last range
}
// --- Check for Color Range Change ---
bool colorRangeChanged = false;
if (newColorRange != lastUpdatedColorRange) {
lastUpdatedColorRange = newColorRange; // Update the last updated range
colorRangeChanged = true;
Serial.print("Color Range Changed: ");
Serial.println(newColorRange);
// Update global color state to the RGB value for this range
currentRed = colorRangeRGB[newColorRange].r;
currentGreen = colorRangeRGB[newColorRange].g;
currentBlue = colorRangeRGB[newColorRange].b;
lastInteractionTime = millis(); // Reset timer on color range change
}
// --- Calculate Brightness ---
int mappedBrightness = map(rawBrightnessValue, 0, 4095, 0, 255);
// --- Check for Significant Brightness Change (Raw Value Threshold) ---
// Use a threshold on the RAW brightness value to detect change
static int lastRecordedRawBrightness = -1; // Store the last raw brightness value that caused an update
bool brightnessValueChanged = false;
if (lastRecordedRawBrightness == -1 || abs(rawBrightnessValue - lastRecordedRawBrightness) >= rawBrightnessChangeThreshold) {
lastRecordedRawBrightness = rawBrightnessValue; // Record the raw value that caused this potential update
// Only update the global brightness state if the mapped value is different (handles edge cases)
Serial.print("Brightness (raw change): Raw="); // Modified print
Serial.print(rawBrightnessValue); // Print the raw value
Serial.print(" Mapped="); // Modified print
Serial.println(currentBrightness); // Print the mapped value
if (mappedBrightness != currentBrightness) {
currentBrightness = mappedBrightness; // Update global brightness state
brightnessValueChanged = true;
lastInteractionTime = millis(); // Reset timer on brightness change
Serial.print("Brightness (raw change): ");
Serial.println(currentBrightness);
}
}
// --- Update Display and LEDs if Color Range or Significant Brightness Changed ---
if (colorRangeChanged || brightnessValueChanged) {
// Update OLED Display with current state
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.println("Color/Brightness:");
display.print("R:"); display.print(currentRed);
display.print(" G:"); display.print(currentGreen);
display.print(" B:"); display.println(currentBlue);
display.print("Brightness:"); display.println(currentBrightness);
display.display();
// Update the LED strip color and brightness immediately for visual feedback
CRGB targetColor = CRGB(currentRed, currentGreen, currentBlue);
fill_solid(leds, NUM_LEDS, targetColor);
FastLED.setBrightness(currentBrightness);
FastLED.show();
}
// --- Check for Debounced Analog Update and Send MQTT ---
// This block sends data ONLY after a color range change OR a significant brightness change
// AND enough time has passed since the last interaction.
// The lastAnalogSendTime and lastSent values are global/static
// --- Check for Debounced Analog Update and Send MQTT ---
// This block sends data ONLY after a color range change OR a significant brightness change
// AND enough time has passed since the last interaction.
// The lastAnalogSendTime and lastSent values are global/static
// We need a flag to indicate that an update is pending send
static bool analogUpdatePendingSend = false; // This is already global, just for reference.
// Set the pending send flag if a color range or brightness value changed
if (colorRangeChanged || brightnessValueChanged) {
analogUpdatePendingSend = true; // A change happened, mark for send
}
// Only attempt to send if an update is pending AND enough time has passed since the last Interaction.
if (analogUpdatePendingSend && (millis() - lastInteractionTime >= analogSendDelay)) {
// Check if the current global state is different from the last values that were ACTUALLY SENT.
// lastSentRed, lastSentGreen, lastSentBlue, lastSentBrightness are global/static
if (lastSentRed == -1 || // Handle the very first send
currentRed != lastSentRed ||
currentGreen != lastSentGreen ||
currentBlue != lastSentBlue ||
currentBrightness != lastSentBrightness) {
// If the state is different from the last sent state, publish
Serial.println("Analog input stable (range/brightness change). Sending MQTT data.");
publishMQTT(currentRed, currentGreen, currentBlue, currentBrightness, targetNames[currentTargetIndex]);
// Update the last sent values
lastSentRed = currentRed;
lastSentGreen = currentGreen;
lastSentBlue = currentBlue;
lastSentBrightness = currentBrightness;
lastAnalogSendTime = millis(); // Record the time of this send
analogUpdatePendingSend = false; // Clear the pending send flag
// No need to reset lastInteractionTime here, it was already reset when analogValueChanged was true
}
}
// --- Read and Process Button States ---
int currentTtpButton0State = digitalRead(ttpButton0Pin);
int currentTtpButton1State = digitalRead(ttpButton1Pin);
int currentTtpButton2State = digitalRead(ttpButton2Pin);
int currentTtpButton3State = digitalRead(ttpButton3Pin);
int currentTtpButton4State = digitalRead(ttpButton4Pin);
int currentTtpButton5State = digitalRead(ttpButton5Pin);
// Check if the HTTM button state has changed (On/Off)
if (currentTtpButton0State != lastTtpButton0State) {
delay(50); // Basic debounce delay
if (currentTtpButton0State == LOW) { // Button is pressed
Serial.println("POWER Button (On/Off) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
lightStates[currentTargetIndex] = !lightStates[currentTargetIndex];
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println("On/Off Toggle");
display.display();
// ** Send MQTT message for On/Off toggle **
StaticJsonDocument<64> doc; // Smaller buffer for simple message
doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
doc["command"] = "TOGGLE"; // Example command
doc["command"] = lightStates[currentTargetIndex] ? "lights_on" : "lights_off";
char jsonBuffer[64];
serializeJson(doc, jsonBuffer);
Serial.print("Publishing On/Off toggle for target: ");
Serial.println(targetNames[currentTargetIndex]);
Serial.println(jsonBuffer);
client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("HTTM Button (On/Off) Released");
}
lastTtpButton0State = currentTtpButton0State;
}
// Check if TTP Button 1 (Target 1) state has changed
if (currentTtpButton1State != lastTtpButton1State) {
delay(50); // Basic debounce delay
if (currentTtpButton1State == LOW) { // Button is pressed
Serial.println("TTP Button 1 (Target 1) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
currentTargetIndex = 0; // Set target index to 0 (White Lamp)
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println(displayNames[currentTargetIndex]); // Display the name
display.display();
Serial.print("Current Target Index: ");
Serial.println(currentTargetIndex);
// ** Send MQTT message indicating target change **
// StaticJsonDocument<64> doc;
// doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
//doc["command"] = "SELECT_TARGET"; // Example command
// char jsonBuffer[64];
// serializeJson(doc, jsonBuffer);
// Serial.print("Publishing target change to: ");
// Serial.println(targetNames[currentTargetIndex]);
// Serial.println(jsonBuffer);
// client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("TTP Button 1 (Target 1) Released");
}
lastTtpButton1State = currentTtpButton1State;
}
// Check if TTP Button 2 (Target 2) state has changed
if (currentTtpButton2State != lastTtpButton2State) {
delay(50); // Basic debounce delay
if (currentTtpButton2State == LOW) { // Corrected variable name was 22
Serial.println("TTP Button 2 (Target 2) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
currentTargetIndex = 1; // Set target index to 1 (Pink Lamp)
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println(displayNames[currentTargetIndex]); // Display the name
display.display();
Serial.print("Current Target Index: ");
Serial.println(currentTargetIndex);
// ** Send MQTT message indicating target change **
// StaticJsonDocument<64> doc;
// doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
// doc["command"] = "SELECT_TARGET"; // Example command
// char jsonBuffer[64];
// serializeJson(doc, jsonBuffer);
// Serial.print("Publishing target change to: ");
// Serial.println(targetNames[currentTargetIndex]);
// Serial.println(jsonBuffer);
// client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("TTP Button 2 (Target 2) Released");
}
lastTtpButton2State = currentTtpButton2State;
}
// Check if TTP Button 3 (Target 3) state has changed
if (currentTtpButton3State != lastTtpButton3State) {
delay(50); // Basic debounce delay
if (currentTtpButton3State == LOW) { // Button is pressed
Serial.println("TTP Button 3 (Target 3) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
currentTargetIndex = 2; // Set target index to 2 (Desk Lamp)
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println(displayNames[currentTargetIndex]); // Display the name
display.display();
Serial.print("Current Target Index: ");
Serial.println(currentTargetIndex);
// ** Send MQTT message indicating target change **
// StaticJsonDocument<64> doc;
// doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
// doc["command"] = "SELECT_TARGET"; // Example command
// char jsonBuffer[64];
// serializeJson(doc, jsonBuffer);
// Serial.print("Publishing target change to: ");
// Serial.println(targetNames[currentTargetIndex]);
// Serial.println(jsonBuffer);
// client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("TTP Button 3 (Target 3) Released");
}
lastTtpButton3State = currentTtpButton3State;
}
// Check if TTP Button 4 (Target 4) state has changed
if (currentTtpButton4State != lastTtpButton4State) {
delay(50); // Basic debounce delay
if (currentTtpButton4State == LOW) { // Button is pressed
Serial.println("TTP Button 4 (Target 4) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
currentTargetIndex = 3; // Set target index to 2 (Desk Lamp)
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println(displayNames[currentTargetIndex]); // Display the name
display.display();
Serial.print("Current Target Index: ");
Serial.println(currentTargetIndex);
// ** Send MQTT message indicating target change **
// StaticJsonDocument<64> doc;
// doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
// doc["command"] = "SELECT_TARGET"; // Example command
// char jsonBuffer[64];
// serializeJson(doc, jsonBuffer);
// Serial.print("Publishing target change to: ");
// Serial.println(targetNames[currentTargetIndex]);
// Serial.println(jsonBuffer);
// client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("TTP Button 4 (Target 4) Released");
}
lastTtpButton4State = currentTtpButton4State;
}
// Check if TTP Button 5 (Target 5) state has changed
if (currentTtpButton5State != lastTtpButton5State) {
delay(50); // Basic debounce delay
if (currentTtpButton5State == LOW) { // Button is pressed
Serial.println("TTP Button 5 (Target 5) Pressed");
lastInteractionTime = millis(); // Reset sleep timer on button press
currentTargetIndex = 4; // Set target index to 2 (Desk Lamp)
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(2);
display.println(displayNames[currentTargetIndex]); // Display the name
display.display();
Serial.print("Current Target Index: ");
Serial.println(currentTargetIndex);
// ** Send MQTT message indicating target change **
// StaticJsonDocument<64> doc;
// doc["target"] = targetNames[currentTargetIndex]; // Use the target name from the array
// doc["command"] = "SELECT_TARGET"; // Example command
// char jsonBuffer[64];
// serializeJson(doc, jsonBuffer);
// Serial.print("Publishing target change to: ");
// Serial.println(targetNames[currentTargetIndex]);
// Serial.println(jsonBuffer);
// client.publish(mqtt_topic_publish, (const byte*)jsonBuffer, strlen(jsonBuffer)); // Publish as bytes
} else {
Serial.println("TTP Button 5 (Target 5) Released");
}
lastTtpButton5State = currentTtpButton5State;
}
// --- Check for Sleep Condition ---
// If no interaction (analog change or button press) for sleepDelay
if ((millis() - lastInteractionTime >= sleepDelay) && lastInteractionTime > 0) {
Serial.println("Inactivity detected. Entering deep sleep...");
for(int i = 0; i < 5; i++) {
savedLightStates[i] = lightStates[i];
}
// Save current state to RTC memory before sleeping
savedRed = currentRed;
savedGreen = currentGreen;
savedBlue = currentBlue;
savedBrightness = currentBrightness;
savedTargetIndex = currentTargetIndex; // Save the integer index
display.clearDisplay(); // Clear display before sleeping
display.display();
// Power down peripherals before sleeping to save power
// For FastLED, setting brightness to 0 and showing is a good step for minimum power.
FastLED.setBrightness(0);
FastLED.show();
// Disconnect from WiFi and MQTT before sleeping
WiFi.disconnect(true);
client.disconnect();
Serial.println("Disconnected from WiFi and MQTT.");
// Enter deep sleep, woken by button presses (ANY_HIGH)
esp_deep_sleep_start(); // Corrected function name
}
// Small delay to keep the loop from running too fast when idle
delay(10);
}