Skip to content

Instantly share code, notes, and snippets.

@Gamer08YT
Created August 9, 2023 12:00
Show Gist options
  • Select an option

  • Save Gamer08YT/369364481727008ee18c31b69aea45c7 to your computer and use it in GitHub Desktop.

Select an option

Save Gamer08YT/369364481727008ee18c31b69aea45c7 to your computer and use it in GitHub Desktop.
#include <Arduino.h>
#include "Ethernet.h"
#include <ArduinoHA.h>
#define ARDUINOHA_DEBUG;
//#include "ArduinoOTA.h"
//#include "InternalStorage.h"
// Store MAC Address of Device.
byte macIO[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
// Store EthernetServer Instance.
EthernetServer serverIO(80);
EthernetClient client;
// Define Home Assistant Credentials.
HADevice device;
// Define Home Assistant MQTT Instance.
HAMqtt mqtt(client, device);
// Store Refill Trigger.
HANumber trigger("switch_refill");
void setupLAN();
void setupOTA();
void handleOTA();
void handleWeb();
void setupHA();
void setupMQTT();
/**
* @brief Initializes the variables and resources required for the setup.
*
* This function should be called once at the beginning of the program execution
* to initialize the necessary variables and resources.
*
* @details
* This function sets up any global variables and resources that are needed
* before the main code execution starts.
*
* Example usage:
* @code
* setup();
* @endcode
*
* @note
* It is recommended to call this function from the main() function.
*/
void setup() {
// Begin Serial Console.
Serial.begin(9600);
// Print Debug Message.
Serial.println("Starting Hauswasserwerk...");
// Setup LAN Connection.
setupLAN();
// Wait for a short Period.
delay(250);
// Setup HomeAssistant.
setupHA();
// Wait for a short Period.
delay(500);
// Setup MQTT.
setupMQTT();
// Setup OTA Server.
setupOTA();
}
/**
* @brief This function is called when a successful connection is established.
*
* This function is invoked when a connection to a remote device is successfully established.
* It can be used to perform any necessary actions or setup required after a successful connection.
*
* @note This function should be implemented by the user.
*
* @param void No parameters are required for this function.
*
* @return void This function does not return any value.
*
* @see onDisconnected()
*/
void onConnected() {
Serial.println("Connected to MQTT Server.");
}
/**
* @brief Handles the received message from the specified topic.
*
* This function is called whenever a message is received on the specified topic.
* It takes the received topic, payload, and payload length as input parameters.
*
* @param topic The topic on which the message was received.
* @param payload The payload of the received message.
* @param length The length of the payload in bytes.
*/
void onMessage(const char *topic, const uint8_t *payload, uint16_t length) {
Serial.println("Received ");
Serial.print(topic);
Serial.println(" - ");
//(payload);
}
/**
* @brief Sets up the MQTT connection with the MQTT broker.
*
* This function initializes the necessary resources and establishes a
* connection with the MQTT broker. It performs the configuration settings
* required for a successful MQTT connection.
*
* @note The function assumes that the necessary parameters like broker URL,
* credentials, client ID, etc. are already set before calling this function.
* Ensure that the required parameters are correctly set prior to calling
* this function.
*
* @see setBrokerURL()
* @see setCredentials()
* @see setClientID()
* @see setKeepAlive()
*
* @return void
*/
void setupMQTT() {
// Add MQTT Listener.
mqtt.onMessage(onMessage);
mqtt.onConnected(onConnected);
// Connect to HomeAssistant.
mqtt.begin("homeassistant.local", "wasserwerk", "wasserwerk");
// Print Debug Message.
Serial.println("Connecting to HomeAssistant MQTT Server.");
}
/**
* @brief Initial setup for Home Automation
*
* This function sets up the necessary variables and configurations for Home Automation.
* It initializes the required devices, sensors, and controllers.
* After calling this function, the home automation system is ready to be used.
*
* @details
* The setupHA() function performs the following tasks:
* 1. Initializes the communication protocols and configurations for controlling devices.
* 2. Configures and connects to sensors for collecting data.
* 3. Initializes and configures the Home Automation Controller.
* 4. Sets up the necessary event handlers for monitoring and responding to events.
*
* @note
* This function should be called once at the beginning of the Home Automation system.
* After calling this function, the main loop of the Home Automation system should be implemented.
* Make sure to configure and handle events as required for the specific Home Automation use case.
*
* @see loopHA() for the main loop of the Home Automation system.
* @see handleEvent() for handling specific events in the Home Automation system.
*/
void setupHA() {
// Set ID of Device.
device.setUniqueId(macIO, sizeof(macIO));
// Prepare for Home Assistant.
device.setName("Wasserwerk");
device.setSoftwareVersion("1.0.0");
device.setModel("ATmega2560");
device.setManufacturer("Jan Heil (www.byte-store.de)");
device.enableSharedAvailability();
device.enableLastWill();
// Prepare Power Trigger.
trigger.setMax(100);
trigger.setMin(10);
trigger.setName("Refill Trigger");
trigger.setUnitOfMeasurement("%");
trigger.setDeviceClass("moisture");
trigger.setMode(HANumber::ModeBox);
//trigger.setCurrentState(Device::getTrigger());
//trigger.onCommand(MQTT::onTrigger);
// Print Debug Message.
Serial.println("Finished registration in HomeAssistant.");
}
/**
* @brief Sets up OTA (Over-The-Air) update functionality
*
* This function initializes the OTA update functionality, which allows the firmware
* of the device to be updated remotely over a network connection. It sets up
* the required OTA callbacks, configures the OTA parameters, and starts the OTA
* update service.
*
* Usage: Call this function in the setup() function of your Arduino sketch to
* enable OTA updates for your device.
*
* OTA provides a convenient way to remotely update firmware, ensuring the latest
* version of the code is running on the device. It eliminates the need for manual
* firmware updates via USB or other means, simplifying the process for both
* developers and end users.
*
* @note This function should only be called once in the setup() function.
*
* @return void
*/
void setupOTA() {
// Begin OTA Server with Internal Storage.
//ArduinoOTA.begin(Ethernet.localIP(), "ByteWasserwerk", "@ByteWasserwerk2023", InternalStorage);
}
/**
* \brief Sets up the local area network (LAN) configuration.
*
* This function initializes the necessary variables and settings for
* configuring and establishing a local area network (LAN).
*
* \note This function assumes that the necessary hardware and software
* requirements for LAN setup are already in place.
*
* \note The specific implementation of this function may vary depending
* on the platform and network architecture being used.
*
* \return No return value.
*/
void setupLAN() {
// Select Ethernet Board.
//Ethernet.init(10);
// Start Ethernet Connection and Server via DHCP.
if (Ethernet.begin(macIO) == 0) {
// Print Debug Message.
Serial.println("Failed to configure Ethernet using DHCP.");
// Check if Hardware exits.
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
// Print Hardware Missing.
Serial.println("Ethernet Hardware was not found.");
} else if (Ethernet.linkStatus() == LinkOFF) {
// Print Unplugged.
Serial.println("Ethernet cable is not connected.");
}
// Wait until DHCP resolved.
while (true) {
delay(1);
}
}
// Print Success Message.
Serial.print("Successfully connected with Network IP-Address ");
Serial.println(Ethernet.localIP());
}
/**
* @brief Executes a loop continuously until exit condition is met.
*
* The loop() function is a placeholder to demonstrate the structure of a loop execution.
* It continues to execute until an exit condition is met. You can define various conditions
* and actions inside the loop to perform repetitive tasks.
*
* @details
* This is a generic loop function that can be used as a starting point in your code.
* It does not provide any specific functionality, but it can be customized to suit your
* program requirements. Please refer to the examples and documentation to learn how
* to use this function effectively in your program.
*
* @warning
* Be cautious while implementing infinite loops and ensure there is a mechanism to break
* the loop when necessary. Otherwise, it may result in an infinite execution and may lead
* to system locks or freezes.
*
* @param none
* @retval none
*
* @see exitCondition()
* @see performAction()
*
*/
void loop() {
// Keep Ethernet Maintained.
Ethernet.maintain();
// Handle OTA Poll.
//handleOTA();
// Handle MQTT Stream.
mqtt.loop();
// Handle WebServer Connections.
//handleWeb();
}
/**
* @brief A method to handle Over-the-Air (OTA) firmware updates.
*
* This method is responsible for managing and processing OTA firmware updates
* for the target device. It performs the necessary tasks to initiate and complete
* the firmware update process using the OTA mechanism.
*
* @remarks This method should be called to handle OTA updates periodically or
* based on certain triggers/events.
*
* @return void
*/
void handleOTA() {
// Check for OTA Updates.
//ArduinoOTA.poll();
}
/**
* @brief Handles the web request and performs necessary actions.
*
* This function is responsible for handling the web request and performing all the necessary actions
* based on the request and its parameters. The function follows a certain algorithm to process the
* request and produces the desired output.
*
* @details
* This function can be called to handle any web request and it will perform the following steps:
* - Parse the request parameters and validate them.
* - Determine the type of request and perform specific action based on the request type.
* - Process the data and generate the response accordingly.
* - Send the response back to the client.
*
* It is important to note that this function assumes a working and established connection with the client.
* The function expects that the necessary resources and network infrastructure are properly set up.
*
* @pre
* - A valid web request is received from the client.
*
* @post
* - The web request is handled and the appropriate response is sent back to the client.
*
* @note
* - This function handles a wide range of request types and can perform different actions depending on the request.
* - Customization and extension of this function is possible by modifying the specific action blocks.
*
* @throw
* - This function may throw errors or exceptions in case of invalid or malformed requests.
*
* @return
* - This function does not return any value.
*/
void handleWeb() {
// Listen for new Client Connections.
EthernetClient clientIO = serverIO.available();
// Check if Client is not null/undefined.
if (clientIO) {
// Print Debug Message.
Serial.println("Client connected to Web Server");
// an HTTP request ends with a blank line
bool currentLineIsBlank = true;
while (clientIO.connected()) {
if (clientIO.available()) {
char c = clientIO.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the HTTP request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard HTTP response header
clientIO.println("HTTP/1.1 200 OK");
clientIO.println("Content-Type: text/html");
clientIO.println(
"Connection: close"); // the connection will be closed after completion of the response
//clientIO.println("Refresh: 5"); // refresh the page automatically every 5 sec
clientIO.println();
clientIO.println("<!DOCTYPE HTML>");
clientIO.println(
R"(<html data-bs-theme="dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>ByteWasserwerk</title><link rel="stylesheet" href="http://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css"></head><body>)");
clientIO.println(
"<div class=\"container my-5\"><div class=\"bg-body border border-dashed p-5 position-relative rounded-5 text-center text-muted\"><h1 class=\"text-body-emphasis\">Wasser<b>werk</b></h1><p class=\"col-lg-6 mb-4 mx-auto\">Das Wasserwerk ist betriebsbereit und die Einstellungen können über den Button unten eingesehen werden. Das System wurde von Jan Heil (www.byte-store.de) entwickelt und programmiert.</p><a href=\"./config\" class=\"btn btn-primary mb-5 px-5\"type=\"button\">Konfiguration</a></div></div>");
/*clientIO.println(
R"(<div class="container"><footer class="align-items-center d-flex border-top flex-wrap justify-content-between my-4 py-3"><div class="align-items-center d-flex col-md-4"><a class="mb-3 mb-md-0 text-body-secondary lh-1 me-2 text-decoration-none"href="/"></a><span class="mb-3 mb-md-0 text-body-secondary">Copyright by 2023 Jan Heil (www.byte-store.de)</span></div></footer></div>)");
*/
clientIO.println("</body></html>");
clientIO.flush();
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// Wait a while for the Web Browser.
delay(1);
// Close the Connection.
clientIO.stop();
// Print Debug Message.
Serial.println("Client disconnected from Web Server");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment