Last active
February 1, 2024 04:08
-
-
Save sstallion/4c263769306c5fc2fb87d65e11a809d9 to your computer and use it in GitHub Desktop.
Arduino Sketch for an Aquarium Light in Home Assistant
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 <SPI.h> | |
#include <WiFiNINA.h> | |
#include <ArduinoHA.h> | |
namespace { | |
constexpr auto WIFI_SSID = "<SSID>"; | |
constexpr auto WIFI_PASS = "<PASSWORD>"; | |
constexpr auto MQTT_BROKER = "<HOSTNAME>"; | |
constexpr auto MQTT_USER = "<USERNAME>"; | |
constexpr auto MQTT_PASS = "<PASSWORD>"; | |
constexpr auto BUTTON_PIN = 2; | |
constexpr auto RED_PIN = 10; | |
constexpr auto GREEN_PIN = 11; | |
constexpr auto BLUE_PIN = 9; | |
WiFiClient client; | |
HADevice device; | |
HAMqtt mqtt{client, device}; | |
HALight light{ "light", HALight::RGBFeature }; | |
// Interrupts are used to handle button input rather than polling due to | |
// network-related delays, which can result in missed button presses. The | |
// following flag is used to indicate when loop() should publish a state | |
// change triggered by a button press: | |
volatile bool publishCurrentState; | |
void printHex(byte value) { | |
if (value < 0xF) { | |
Serial.print("0"); | |
} | |
Serial.print(value, HEX); | |
} | |
void printMACAddress(byte mac[]) { | |
for (auto i = WL_MAC_ADDR_LENGTH - 1; i >= 0; i--) { | |
printHex(mac[i]); | |
if (i > 0) { | |
Serial.print(":"); | |
} | |
} | |
} | |
void writeRGB(byte red, byte green, byte blue) { | |
analogWrite(RED_PIN, red); | |
analogWrite(GREEN_PIN, green); | |
analogWrite(BLUE_PIN, blue); | |
} | |
void setCurrentState(bool state) { | |
if (state) { | |
auto& color = light.getCurrentRGBColor(); | |
writeRGB(color.red, color.green, color.blue); | |
} else { | |
writeRGB(0, 0, 0); | |
} | |
light.setCurrentState(state); | |
} | |
void toggleCurrentState() { | |
static unsigned long last; // debounce input | |
if (auto t = millis() - last; t > 250) { | |
setCurrentState(!light.getCurrentState()); | |
publishCurrentState = true; | |
last = millis(); | |
} | |
} | |
void onStateCommand(bool state, HALight* /*sender*/) { | |
Serial.print("Received state command: "); | |
Serial.println(state ? "on" : "off"); | |
setCurrentState(state); | |
} | |
void onRGBColorCommand(HALight::RGBColor color, HALight* /*sender*/) { | |
Serial.print("Received RGB color command: #"); | |
printHex(color.red); | |
printHex(color.green); | |
printHex(color.blue); | |
Serial.println(); | |
light.setCurrentRGBColor(color); | |
} | |
} // namespace | |
void setup() { | |
pinMode(BUTTON_PIN, INPUT_PULLUP); | |
pinMode(RED_PIN, OUTPUT); | |
pinMode(GREEN_PIN, OUTPUT); | |
pinMode(BLUE_PIN, OUTPUT); | |
Serial.begin(9600); | |
byte mac[WL_MAC_ADDR_LENGTH]; | |
WiFi.macAddress(mac); | |
Serial.print("MAC Address: "); | |
printMACAddress(mac); | |
Serial.println(); | |
device.setUniqueId(mac, sizeof(mac)); | |
device.setName("Fish Tank"); | |
device.setManufacturer("<MFR>"); | |
device.setModel("<MODEL>"); | |
device.enableSharedAvailability(); | |
device.enableLastWill(); | |
light.setName("Fish Tank"); | |
light.setIcon("mdi:fish"); | |
light.setOptimistic(true); | |
light.onStateCommand(onStateCommand); | |
light.onRGBColorCommand(onRGBColorCommand); | |
auto defaultRGBColor = HALight::RGBColor{ 255, 255, 255 }; | |
light.setCurrentRGBColor(defaultRGBColor); | |
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), toggleCurrentState, FALLING); | |
byte status; | |
do { | |
Serial.print("Connecting to SSID: "); | |
Serial.println(WIFI_SSID); | |
status = WiFi.begin(WIFI_SSID, WIFI_PASS); | |
} while (status != WL_CONNECTED); | |
Serial.print("Signal Strength (dBm): "); | |
Serial.println(WiFi.RSSI()); | |
Serial.print("IP Address: "); | |
Serial.println(WiFi.localIP()); | |
Serial.print("Netmask: "); | |
Serial.println(WiFi.subnetMask()); | |
Serial.print("Gateway: "); | |
Serial.println(WiFi.gatewayIP()); | |
Serial.print("Connecting to MQTT Broker: "); | |
Serial.println(MQTT_BROKER); | |
mqtt.begin(MQTT_BROKER, MQTT_USER, MQTT_PASS); | |
} | |
void loop() { | |
mqtt.loop(); | |
if (publishCurrentState) { | |
noInterrupts(); | |
auto state = light.getCurrentState(); | |
publishCurrentState = false; | |
interrupts(); | |
Serial.print("Publishing current state: "); | |
Serial.println(state ? "on" : "off"); | |
light.setState(state, true); // force | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment