|
1 | | -// |
2 | | -// Created by gene on 13/05/25. |
3 | | -// |
| 1 | +/* |
| 2 | + * HomeGenie-Mini (c) 2018-2025 G-Labs |
| 3 | + * |
| 4 | + * |
| 5 | + * This file is part of HomeGenie-Mini (HGM). |
| 6 | + * |
| 7 | + * HomeGenie-Mini is free software: you can redistribute it and/or modify |
| 8 | + * it under the terms of the GNU General Public License as published by |
| 9 | + * the Free Software Foundation, either version 3 of the License, or |
| 10 | + * (at your option) any later version. |
| 11 | + * |
| 12 | + * HomeGenie-Mini is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU General Public License |
| 18 | + * along with HomeGenie-Mini. If not, see <http://www.gnu.org/licenses/>. |
| 19 | + * |
| 20 | + * |
| 21 | + * Authors: |
| 22 | + * - Generoso Martello <gene@homegenie.it> |
| 23 | + * |
| 24 | + */ |
4 | 25 |
|
5 | 26 | #ifndef HOMEGENIE_MINI_CONFIGURATION_H |
6 | 27 | #define HOMEGENIE_MINI_CONFIGURATION_H |
7 | 28 |
|
| 29 | +#include "defs.h" |
| 30 | + |
| 31 | +#include <ui/Dashboard.h> |
| 32 | +#include <ui/drivers/RoundDisplay.h> |
| 33 | +#include <ui/drivers/StandardDisplay.h> |
| 34 | +#include <ui/activities/utilities/SystemInfoActivity.h> |
| 35 | + |
| 36 | +#ifdef BOARD_HAS_PSRAM |
| 37 | +#include <ui/activities/control/SwitchControlActivity.h> |
| 38 | +#ifndef DISABLE_LVGL |
| 39 | +#include <ui/activities/control/ColorControlActivity.h> |
| 40 | +#include <ui/activities/control/LevelControlActivity.h> |
| 41 | +#endif |
| 42 | +#include <ui/activities/examples/AnalogClockActivity.h> |
| 43 | +#include <ui/activities/examples/GaugeExampleActivity.h> |
| 44 | +#include <ui/activities/monitor/CameraDisplayActivity.h> |
| 45 | +#include <ui/activities/utilities/DigitalClockActivity.h> |
| 46 | +#endif |
| 47 | + |
| 48 | +#include "smart-sensor/CommonSensors.h" |
| 49 | +#include "display/activities/SensorValuesActivity.h" |
| 50 | + |
| 51 | +//#include "io/BatterySensor.h" |
| 52 | +#include "io/InertialSensor.h" |
| 53 | + |
| 54 | + |
| 55 | +using namespace Service; |
| 56 | +#ifdef BOARD_HAS_PSRAM |
| 57 | +using namespace UI::Activities::Control; |
| 58 | +using namespace UI::Activities::Examples; |
| 59 | +using namespace UI::Activities::Monitor; |
| 60 | +#endif |
| 61 | +using namespace UI::Activities::Utilities; |
| 62 | + |
| 63 | +namespace DisplayConfig = DisplayApi::Configuration; |
| 64 | +namespace DisplayOption = DisplayApi::Options; |
| 65 | + |
| 66 | + |
| 67 | +Dashboard* dashboard; |
| 68 | + |
| 69 | + |
| 70 | +// UI options update listener |
| 71 | +static class : public ModuleParameter::UpdateListener { |
| 72 | +public: |
| 73 | + void onUpdate(ModuleParameter* option) override { |
| 74 | +#ifdef ENABLE_SCREEN_SAVER |
| 75 | + if (option->is(DisplayOption::Display_ScreenSaverTimeout)) { |
| 76 | + dashboard->setScreenSaverTimeout(option->value.toInt() * 1000); |
| 77 | + } |
| 78 | +#endif |
| 79 | + if (option->is(DisplayOption::Display_Brightness)) { |
| 80 | + dashboard->setBrightness(option->value.toInt()); |
| 81 | + } |
| 82 | + } |
| 83 | +} dashboardOptionUpdateListener; |
| 84 | + |
| 85 | + |
| 86 | +void initDashboard(DisplayDriver* displayDriver, Module* module) { |
| 87 | + dashboard = new Dashboard(displayDriver); |
| 88 | +#ifdef ENABLE_SCREEN_SAVER |
| 89 | + auto timeoutMs = Config::getSetting(DisplayConfig::ScreenSaver::TimeoutSeconds, "15"); |
| 90 | + int screenSaverTimeoutMs = timeoutMs.toInt() * 1000; |
| 91 | + dashboard->setScreenSaverTimeout(screenSaverTimeoutMs); |
| 92 | + module->addWidgetOption( |
| 93 | + // name, value |
| 94 | + DisplayOption::Display_ScreenSaverTimeout, timeoutMs.c_str(), |
| 95 | + // type |
| 96 | + UI_WIDGETS_FIELD_TYPE_SLIDER |
| 97 | + // label |
| 98 | + ":screensaver_timeout" |
| 99 | + // min:max:default |
| 100 | + ":0:120:15" |
| 101 | + )->withConfigKey(DisplayConfig::ScreenSaver::TimeoutSeconds)->addUpdateListener(&dashboardOptionUpdateListener); |
| 102 | +#endif |
| 103 | + module->addWidgetOption( |
| 104 | + // name, value |
| 105 | + DisplayOption::Display_Brightness, timeoutMs.c_str(), |
| 106 | + // type |
| 107 | + UI_WIDGETS_FIELD_TYPE_SLIDER |
| 108 | + // label |
| 109 | + ":display_brightness" |
| 110 | + // min:max:default |
| 111 | + ":1:127:64" |
| 112 | + )->withConfigKey(DisplayConfig::Display::Brightness)->addUpdateListener(&dashboardOptionUpdateListener); |
| 113 | +} |
| 114 | + |
| 115 | +void addDashboardActivities(String &list) { |
| 116 | + int currentIndex = 0; |
| 117 | + int nextCommaIndex = 0; |
| 118 | + |
| 119 | + while (currentIndex < list.length()) { |
| 120 | + nextCommaIndex = list.indexOf(',', currentIndex); |
| 121 | + |
| 122 | + String currentElement; |
| 123 | + if (nextCommaIndex == -1) { |
| 124 | + currentElement = list.substring(currentIndex); |
| 125 | + currentIndex = list.length(); // exit loop |
| 126 | + } else { |
| 127 | + currentElement = list.substring(currentIndex, nextCommaIndex); |
| 128 | + currentIndex = nextCommaIndex + 1; |
| 129 | + } |
| 130 | + currentElement.trim(); |
| 131 | + if (currentElement.length() > 0) { |
| 132 | + |
| 133 | + String elementName; |
| 134 | + String elementOptions = ""; |
| 135 | + int colonIndex = currentElement.indexOf(':'); |
| 136 | + if (colonIndex == -1) { |
| 137 | + elementName = currentElement; |
| 138 | + } else { |
| 139 | + elementName = currentElement.substring(0, colonIndex); |
| 140 | + elementOptions = currentElement.substring(colonIndex + 1); |
| 141 | + } |
| 142 | + elementName.trim(); |
| 143 | + elementOptions.trim(); |
| 144 | + |
| 145 | + // This Activity shows basic system info |
| 146 | + // and buttons to rotate the display |
| 147 | + // or reconfigure the device connection |
| 148 | + static int systemInfoCount = 0; |
| 149 | + if (elementName == "SystemInfo") { |
| 150 | + // single instance activity |
| 151 | + if (systemInfoCount++ == 0) { |
| 152 | + auto systemInfo = new SystemInfoActivity(); |
| 153 | + dashboard->addActivity(systemInfo); |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + // This Activity shows device name, date/time and |
| 158 | + // temperature + humidity if DHT sensor is enabled |
| 159 | + static int sensorValuesCount = 0; |
| 160 | + if (elementName == "SensorValues") { |
| 161 | + // single instance activity |
| 162 | + if (sensorValuesCount++ == 0) { |
| 163 | + auto miniModule = HomeGenie::getInstance()->getDefaultModule(); |
| 164 | + auto sensorValues = new SensorValuesActivity(miniModule); |
| 165 | + dashboard->addActivity(sensorValues); |
| 166 | + } |
| 167 | + } |
| 168 | + |
| 169 | +#ifdef BOARD_HAS_PSRAM |
| 170 | + // A cute "pac-man" clock |
| 171 | + static int digitalClockCount = 0; |
| 172 | + if (elementName == "DigitalClock") { |
| 173 | + // single instance activity |
| 174 | + if (digitalClockCount++ == 0) { |
| 175 | + auto digitalClock = new DigitalClockActivity(); |
| 176 | + dashboard->addActivity(digitalClock); |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + // UI control to switch on/off or set level of |
| 181 | + // user-definable devices. Each button emits events |
| 182 | + // that can be automated using the device Scheduler. |
| 183 | + // It can be configured using HomeGenie Panel app. |
| 184 | + if (elementName == "SwitchControl") { |
| 185 | + String address = "D1"; |
| 186 | + if (elementOptions.length() > 0) { |
| 187 | + address = elementOptions; |
| 188 | + } |
| 189 | + auto switchControl = new SwitchControlActivity(address.c_str()); |
| 190 | + dashboard->addActivity(switchControl); |
| 191 | +#ifndef DISABLE_AUTOMATION |
| 192 | + // Adds scheduler programs to handle Level events |
| 193 | + setupLevelControlActivitySchedule(&switchControl->module); |
| 194 | +#endif |
| 195 | + } |
| 196 | + |
| 197 | +#ifndef DISABLE_LVGL |
| 198 | + // Similar to the SwitchControl but using LVGL |
| 199 | + if (elementName == "LevelControl") { |
| 200 | + String address = "M1"; |
| 201 | + if (elementOptions.length() > 0) { |
| 202 | + address = elementOptions; |
| 203 | + } |
| 204 | + auto levelControl = new LevelControlActivity(address.c_str()); |
| 205 | + dashboard->addActivity(levelControl); |
| 206 | +#ifndef DISABLE_AUTOMATION |
| 207 | + // Adds scheduler programs to handle Level events |
| 208 | + setupLevelControlActivitySchedule(&levelControl->module); |
| 209 | +#endif |
| 210 | + } |
| 211 | + // Color control |
| 212 | + if (elementName == "ColorControl") { |
| 213 | + String address = "H1"; |
| 214 | + if (elementOptions.length() > 0) { |
| 215 | + address = elementOptions; |
| 216 | + } |
| 217 | + auto colorControl = new ColorControlActivity(address.c_str()); |
| 218 | + dashboard->addActivity(colorControl); |
| 219 | +#ifndef DISABLE_AUTOMATION |
| 220 | + // Adds scheduler programs to handle ColorHsv events |
| 221 | + setupColorControlActivitySchedule(&colorControl->module); |
| 222 | +#endif |
| 223 | + } |
| 224 | +#endif // DISABLE_LVGL |
| 225 | + // Displays a remote camera via HTTP images feed, |
| 226 | + // or local camera directly connected to the ESP32. |
| 227 | + static int cameraDisplayCount = 0; |
| 228 | + if (elementName == "CameraDisplay") { |
| 229 | + String address = "V1"; |
| 230 | + if (elementOptions.length() > 0) { |
| 231 | + address = elementOptions; |
| 232 | + } |
| 233 | + auto cameraDisplay = new CameraDisplayActivity(address.c_str()); |
| 234 | + if (cameraDisplayCount++ == 0) { |
| 235 | + // The first instance is reserved for |
| 236 | + // onboard ESP32 camera module if enabled |
| 237 | + if (Config::getSetting(Camera_Sensor::SensorType).equals("esp32-cam")) { |
| 238 | + cameraDisplay->isEsp32Camera = true; |
| 239 | + } |
| 240 | + } |
| 241 | + dashboard->addActivity(cameraDisplay); |
| 242 | + } |
| 243 | + |
| 244 | + // UI examples adapted from LovyanGFX library |
| 245 | + static int analogClockCount = 0; |
| 246 | + if (elementName == "AnalogClock") { |
| 247 | + // single instance activity |
| 248 | + if (analogClockCount++ == 0) { |
| 249 | + auto analogClock = new AnalogClockActivity(); |
| 250 | + dashboard->addActivity(analogClock); |
| 251 | + } |
| 252 | + } |
| 253 | + static int gaugeExampleCount = 0; |
| 254 | + if (elementName == "GaugeExample") { |
| 255 | + // single instance activity |
| 256 | + if (gaugeExampleCount++ == 0) { |
| 257 | + auto gaugeExample = new GaugeExampleActivity(); |
| 258 | + dashboard->addActivity(gaugeExample); |
| 259 | + } |
| 260 | + } |
| 261 | + |
| 262 | +#endif // BOARD_HAS_PSRAM |
| 263 | + } |
| 264 | + } |
| 265 | + |
| 266 | +} |
| 267 | + |
8 | 268 | #endif //HOMEGENIE_MINI_CONFIGURATION_H |
0 commit comments