├── .github └── FUNDING.yml ├── .gitignore ├── LICENSE ├── README.md ├── examples ├── DATracking │ └── DATracking.ino ├── DataWriter │ └── DataWriter.ino ├── FullSystem │ └── FullSystem.ino └── SimpleLDR │ └── SimpleLDR.ino ├── extra ├── LCD-I2C-Address-Jumpers.jpg └── dht12.pdf ├── keywords.txt ├── library.json ├── library.properties ├── src ├── HelioActivation.cpp ├── HelioActivation.h ├── HelioActuators.cpp ├── HelioActuators.h ├── HelioAttachments.cpp ├── HelioAttachments.h ├── HelioAttachments.hpp ├── HelioCallback.hh ├── HelioData.cpp ├── HelioData.h ├── HelioDatas.cpp ├── HelioDatas.h ├── HelioDefines.h ├── HelioDrivers.cpp ├── HelioDrivers.h ├── HelioFactory.cpp ├── HelioFactory.h ├── HelioInlines.hh ├── HelioInterfaces.h ├── HelioInterfaces.hpp ├── HelioLogger.cpp ├── HelioLogger.h ├── HelioMeasurements.cpp ├── HelioMeasurements.h ├── HelioModules.cpp ├── HelioModules.h ├── HelioObject.cpp ├── HelioObject.h ├── HelioPanels.cpp ├── HelioPanels.h ├── HelioPins.cpp ├── HelioPins.h ├── HelioPublisher.cpp ├── HelioPublisher.h ├── HelioRails.cpp ├── HelioRails.h ├── HelioScheduler.cpp ├── HelioScheduler.h ├── HelioSensors.cpp ├── HelioSensors.h ├── HelioStreams.cpp ├── HelioStreams.h ├── HelioStrings.cpp ├── HelioStrings.h ├── HelioTriggers.cpp ├── HelioTriggers.h ├── HelioUtils.cpp ├── HelioUtils.h ├── HelioUtils.hpp ├── Helioduino.cpp ├── Helioduino.h ├── Helioduino.hpp ├── full │ ├── HelioduinoUI.cpp │ └── HelioduinoUI.h ├── min │ ├── HelioduinoUI.cpp │ └── HelioduinoUI.h └── shared │ ├── HelioDisplayDrivers.cpp │ ├── HelioDisplayDrivers.h │ ├── HelioDisplayDrivers.hpp │ ├── HelioInputDrivers.cpp │ ├── HelioInputDrivers.h │ ├── HelioMenus.cpp │ ├── HelioMenus.h │ ├── HelioOverviews.cpp │ ├── HelioOverviews.h │ ├── HelioOverviews.hpp │ ├── HelioRemoteControls.cpp │ ├── HelioRemoteControls.h │ ├── HelioUIData.cpp │ ├── HelioUIData.h │ ├── HelioUIDefines.h │ ├── HelioUIInlines.hh │ ├── HelioUIStrings.cpp │ ├── HelioUIStrings.h │ ├── HelioduinoUI.cpp │ ├── HelioduinoUI.h │ ├── screens │ ├── HelioMenuActuators.cpp │ ├── HelioMenuActuators.h │ ├── HelioMenuAlerts.cpp │ ├── HelioMenuAlerts.h │ ├── HelioMenuCalibrations.cpp │ ├── HelioMenuCalibrations.h │ ├── HelioMenuHome.cpp │ ├── HelioMenuHome.h │ ├── HelioMenuInformation.cpp │ ├── HelioMenuInformation.h │ ├── HelioMenuPanels.cpp │ ├── HelioMenuPanels.h │ ├── HelioMenuPowerRails.cpp │ ├── HelioMenuPowerRails.h │ ├── HelioMenuScheduling.cpp │ ├── HelioMenuScheduling.h │ ├── HelioMenuSensors.cpp │ ├── HelioMenuSensors.h │ ├── HelioMenuSettings.cpp │ ├── HelioMenuSettings.h │ ├── HelioOverviewGFX.cpp │ ├── HelioOverviewGFX.h │ ├── HelioOverviewGFX.hpp │ ├── HelioOverviewLCD.cpp │ ├── HelioOverviewLCD.h │ ├── HelioOverviewOLED.cpp │ ├── HelioOverviewOLED.h │ ├── HelioOverviewTFT.cpp │ └── HelioOverviewTFT.h │ ├── tcMenu_Display_AdaFruitGfx.cpp │ ├── tcMenu_Display_AdaFruitGfx.h │ ├── tcMenu_Display_AdaFruitGfx.hpp │ ├── tcMenu_Display_LiquidCrystal.cpp │ ├── tcMenu_Display_LiquidCrystal.h │ ├── tcMenu_Display_TfteSpi.cpp │ ├── tcMenu_Display_TfteSpi.h │ ├── tcMenu_Display_U8g2.cpp │ ├── tcMenu_Display_U8g2.h │ ├── tcMenu_Extra_BspUserSettings.h │ ├── tcMenu_Extra_StChromaArt.cpp │ ├── tcMenu_Extra_StChromaArt.h │ ├── tcMenu_Font_AdafruitGFXArial14.h │ ├── tcMenu_Font_tcUnicodeArial14.h │ ├── tcMenu_Input_AdaTouchDriver.cpp │ ├── tcMenu_Input_AdaTouchDriver.h │ ├── tcMenu_Input_ESP32TouchKeysAbstraction.cpp │ ├── tcMenu_Input_ESP32TouchKeysAbstraction.h │ ├── tcMenu_Remote_EthernetTransport.cpp │ ├── tcMenu_Remote_EthernetTransport.h │ ├── tcMenu_Remote_SerialTransport.cpp │ ├── tcMenu_Remote_SerialTransport.h │ ├── tcMenu_Remote_SimhubConnector.cpp │ ├── tcMenu_Remote_SimhubConnector.h │ ├── tcMenu_Remote_WiFiTransport.cpp │ ├── tcMenu_Remote_WiFiTransport.h │ ├── tcMenu_Theme_CoolBlueModern.h │ ├── tcMenu_Theme_CoolBlueTraditional.h │ ├── tcMenu_Theme_DarkModeModern.h │ ├── tcMenu_Theme_DarkModeTraditional.h │ ├── tcMenu_Theme_MonoBordered.h │ └── tcMenu_Theme_MonoInverse.h └── tests ├── EnumConversionTests └── EnumConversionTests.ino └── EnumTrieExportToCPP └── EnumTrieExportToCPP.ino /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: nachtrave 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS generated files # 2 | ###################### 3 | .DS_Store 4 | .DS_Store? 5 | ._* 6 | .Spotlight-V100 7 | .Trashes 8 | Icon? 9 | ehthumbs.db 10 | Thumbs.db 11 | pad 12 | SmokeTest1 13 | 14 | # Generic: 15 | ############### 16 | *.bak 17 | .vscode 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2023 NachtRaveVL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /examples/SimpleLDR/SimpleLDR.ino: -------------------------------------------------------------------------------- 1 | // Simple-SolarTracker-Arduino Simple Light Dependent Resistor (LDR) Example 2 | // 3 | // The Simple LDR Example sketch shows how a simple Helioduino system can be setup using 4 | // the most minimal of work. In this sketch only that which you actually use is built 5 | // into the final compiled binary, making it an ideal lean choice for those who don't 6 | // need anything fancy. This sketch has no UI or input control, but with a simple buzzer 7 | // and some additional sensors the system can control another axis for a gimballed system. 8 | // 9 | // LDR setups are great for beginners, and has the advantage of being able to be built out 10 | // of commonly available materials. A positional servo is used to tilt the panel, which 11 | // is mounted horizontally facing the general direction of the sun. 12 | 13 | #include 14 | 15 | #define SETUP_PIEZO_BUZZER_PIN -1 // Piezo buzzer pin, else -1 16 | #define SETUP_AXIS_SERVO_PIN A0 // Axis servo write pin (analog) 17 | #define SETUP_LDR_LOWER_PIN A1 // Lower LDR read pin (analog) 18 | #define SETUP_LDR_UPPER_PIN A2 // Upper LDR read pin (analog) 19 | 20 | #define SETUP_SERVO_MIN_DEG -90 // Minimum degrees of axial servo 21 | #define SETUP_SERVO_MAX_DEG 90 // Maximum degrees of axial servo 22 | 23 | #define SETUP_PANEL_TYPE Horizontal // Panel type (Horizontal, Vertical, Gimballed, Equatorial) 24 | #define SETUP_PANEL_HOME {0.0f,0.0f} // Panel home position (azimuth,elevation or RA,declination) 25 | #define SETUP_PANEL_OFFSET {0.0f,0.0f} // Panel offset position (azi,ele or RA,dec) 26 | 27 | Helioduino helioController(SETUP_PIEZO_BUZZER_PIN); // Controller using default setup aside from buzzer pin, if defined 28 | 29 | float _SETUP_PANEL_HOME[] = SETUP_PANEL_HOME; 30 | float _SETUP_PANEL_OFFSET[] = SETUP_PANEL_OFFSET; 31 | 32 | void setup() { 33 | // Setup base interfaces 34 | #ifdef HELIO_ENABLE_DEBUG_OUTPUT 35 | Serial.begin(115200); // Begin USB Serial interface 36 | while (!Serial) { ; } // Wait for USB Serial to connect 37 | #endif 38 | 39 | // Initializes controller with LDR environment (saves some time/space), no logging, eeprom, SD, or anything else. 40 | helioController.init(Helio_SystemMode_Balancing); 41 | 42 | // Adds a simple horizontal LDR balanced solar panel, and sets up any specified offsets. 43 | auto panel = helioController.addLDRBalancingPanel(JOIN(Helio_PanelType,SETUP_PANEL_TYPE)); 44 | panel->setHomePosition(_SETUP_PANEL_HOME); 45 | panel->setAxisOffset(_SETUP_PANEL_OFFSET); 46 | 47 | // Adds a simple positional servo at SETUP_AXIS_SERVO_PIN, installed to control the vertical elevation of the panel. 48 | auto axisServo = helioController.addPositionalServo(SETUP_AXIS_SERVO_PIN, SETUP_SERVO_MIN_DEG, SETUP_SERVO_MAX_DEG); 49 | axisServo->setParentPanel(panel, Helio_PanelAxis_Elevation); 50 | 51 | // Adds a light intensity sensor at SETUP_LDR_LOWER_PIN, installed on the lower side of the panel. 52 | auto ldrLower = helioController.addLightIntensitySensor(SETUP_LDR_LOWER_PIN); 53 | panel->setLDRSensor(ldrLower, Helio_PanelLDR_VerticalMin); // will provide downwards control 54 | 55 | // Adds a light intensity sensor at SETUP_LDR_UPPER_PIN, installed on the upper side of the panel. 56 | auto ldrUpper = helioController.addLightIntensitySensor(SETUP_LDR_UPPER_PIN); 57 | panel->setLDRSensor(ldrUpper, Helio_PanelLDR_VerticalMax); // will provide upwards control 58 | 59 | // Launches controller into main operation. 60 | helioController.launch(); 61 | } 62 | 63 | void loop() 64 | { 65 | // Helioduino will manage most updates for us. 66 | helioController.update(); 67 | } 68 | -------------------------------------------------------------------------------- /extra/LCD-I2C-Address-Jumpers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NachtRaveVL/Simple-SolarTracker-Arduino/2fb314024e02f384c14614458d21e998c950d13d/extra/LCD-I2C-Address-Jumpers.jpg -------------------------------------------------------------------------------- /extra/dht12.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NachtRaveVL/Simple-SolarTracker-Arduino/2fb314024e02f384c14614458d21e998c950d13d/extra/dht12.pdf -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ================================== 2 | CLASSES 3 | ================================== 4 | 5 | ================================== 6 | FUNCTIONS 7 | ================================== 8 | 9 | ================================== 10 | CONSTANTS 11 | ================================== 12 | 13 | ================================== 14 | DATA TYPES 15 | ================================== 16 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Simple-SolarTracker-Arduino", 3 | "version": "0.6.8.0", 4 | "keywords": "solar,solar-tracking,solartracking,solarpanel,solar-panel,panel,sun,sun-tracking,suntracking,scheduler,tracking,diy,automation,controller,monitor,system", 5 | "description": "Helioduino: Simple automation controller for solar tracking systems.", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "NachtRaveVL", 10 | "email": "nachtravevl@gmail.com", 11 | "url": "https://github.com/NachtRaveVL", 12 | "maintainer": true 13 | } 14 | ], 15 | "homepage": "https://github.com/NachtRaveVL/Simple-SolarTracker-Arduino/", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://github.com/NachtRaveVL/Simple-SolarTracker-Arduino.git" 19 | }, 20 | "examples": [ 21 | ], 22 | "frameworks": ["arduino", "espidf", "mbed"], 23 | "platforms": ["avr", "sam", "samd", "teensy", "espressif8266", "espressif32"] 24 | } 25 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=Simple-SolarTracker-Arduino 2 | version=0.6.8.0 3 | author=NachtRaveVL 4 | maintainer=NachtRaveVL 5 | sentence=Helioduino: Simple automation controller for solar tracking systems. 6 | paragraph=Allows one to set up a system of panels, servos, LDRs, relays, and other objects useful in controlling both single and dual axis sun tracking solar panel systems, and provides data monitoring & collection abilities while operating panel axis servos and/or linear actuators across the day as the sun moves to maintain optimal panel alignment. Works with a large variety of widely-available aquarium/hobbyist equipment, including popular GPS, RTC, EEPROM, SD card, WiFi, and other modules compatible with Arduino. Can be setup to calculate sun position accurately as possible or to auto-balance two opposing photoresistors per panel axis. With the right setup Helioduino can automatically do things like: drive large panels with multiple in-step linear actuators, engaging axis brakes to prevent large panels from moving/taking strain off motors that can then disengage, spray/wipe panels on routine to keep panels clean, deploy panels at sunrise and retract at sunset or when its too windy out, remind when to realign panels, or even provide panel heating during cold temperatures or when ice is detected. 7 | category=Other 8 | url=https://github.com/NachtRaveVL/Simple-SolarTracker-Arduino 9 | architectures=* 10 | depends=Adafruit BusIO,Adafruit FT6206 Library,Adafruit GFX Library,Adafruit GPS Library,Adafruit ILI9341,Adafruit ST7735 and ST7789 Library,Adafruit TouchScreen,Adafruit Unified Sensor,ArduinoJson,ArxContainer,ArxSmartPtr,DHT sensor library,I2C_EEPROM,IoAbstraction,LiquidCrystalIO,MQTT,OneWire,RTClib,SimpleCollections,SD,SolarCalculator,TaskManagerIO,tcUnicodeHelper,tcMenu,TFT_eSPI,Time,U8g2,WiFiEspAT,WiFiNINA_Generic,WiFi101,XPT2046_Touchscreen 11 | includes=Helioduino.h -------------------------------------------------------------------------------- /src/HelioActivation.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Activations 4 | */ 5 | 6 | #include "Helioduino.h" 7 | 8 | HelioActivationHandle::HelioActivationHandle(SharedPtr actuatorIn, Helio_DirectionMode direction, float intensity, millis_t duration, bool force) 9 | : activation(direction, constrain(intensity, 0.0f, 1.0f), duration, (force ? Helio_ActivationFlags_Forced : Helio_ActivationFlags_None)), 10 | actuator(nullptr), checkTime(0), elapsed(0) 11 | { 12 | operator=(actuatorIn); 13 | } 14 | 15 | HelioActivationHandle::HelioActivationHandle(const HelioActivationHandle &handle) 16 | : actuator(nullptr), activation(handle.activation), checkTime(0), elapsed(0) 17 | { 18 | operator=(handle.actuator); 19 | } 20 | 21 | HelioActivationHandle::~HelioActivationHandle() 22 | { 23 | if (actuator) { unset(); } 24 | } 25 | 26 | HelioActivationHandle &HelioActivationHandle::operator=(SharedPtr actuatorIn) 27 | { 28 | if (actuator != actuatorIn && isValid()) { 29 | if (actuator) { unset(); } else { checkTime = 0; } 30 | 31 | actuator = actuatorIn; 32 | 33 | if (actuator) { actuator->_handles.push_back(this); actuator->setNeedsUpdate(); } 34 | } 35 | return *this; 36 | } 37 | 38 | void HelioActivationHandle::unset() 39 | { 40 | if (isActive()) { elapseTo(); } 41 | checkTime = 0; 42 | 43 | if (actuator) { 44 | for (auto handleIter = actuator->_handles.end() - 1; handleIter != actuator->_handles.begin() - 1; --handleIter) { 45 | if ((*handleIter) == this) { 46 | actuator->_handles.erase(handleIter); 47 | break; 48 | } 49 | } 50 | actuator->setNeedsUpdate(); 51 | actuator = nullptr; 52 | } 53 | } 54 | 55 | void HelioActivationHandle::elapseBy(millis_t delta) 56 | { 57 | if (delta && isValid() && isActive()) { 58 | if (!isUntimed()) { 59 | if (delta <= activation.duration) { 60 | activation.duration -= delta; 61 | checkTime += delta; 62 | } else { 63 | delta = activation.duration; 64 | activation.duration = 0; 65 | checkTime = 0; 66 | actuator->setNeedsUpdate(); 67 | } 68 | } 69 | elapsed += delta; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/HelioActivation.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Activation 4 | */ 5 | 6 | #ifndef HelioActivation_H 7 | #define HelioActivation_H 8 | 9 | struct HelioActivation; 10 | struct HelioActivationHandle; 11 | 12 | #include "Helioduino.h" 13 | 14 | // Activation Flags 15 | enum Helio_ActivationFlags : unsigned char { 16 | Helio_ActivationFlags_Forced = 0x01, // Force enable / ignore cursory canEnable checks 17 | Helio_ActivationFlags_None = 0x00 // Placeholder 18 | }; 19 | 20 | // Activation Data 21 | // Activation setup data that is its own object for ease of use. Used to define what 22 | // encapsulates an activation. 23 | struct HelioActivation { 24 | Helio_DirectionMode direction; // Normalized driving direction 25 | float intensity; // Normalized driving intensity ([0.0,1.0]) 26 | millis_t duration; // Duration time remaining, in milliseconds, else -1 for non-diminishing/unlimited or 0 for finished 27 | Helio_ActivationFlags flags; // Activation flags 28 | 29 | inline HelioActivation(Helio_DirectionMode directionIn, float intensityIn, millis_t durationIn, Helio_ActivationFlags flagsIn) : direction(directionIn), intensity(constrain(intensityIn, 0.0f, 1.0f)), duration(durationIn), flags(flagsIn) { ; } 30 | inline HelioActivation() : HelioActivation(Helio_DirectionMode_Undefined, 0.0f, 0, Helio_ActivationFlags_None) { ; } 31 | 32 | inline bool isValid() const { return direction != Helio_DirectionMode_Undefined; } 33 | inline bool isDone() const { return duration == millis_none; } 34 | inline bool isUntimed() const { return duration == -1; } 35 | inline bool isForced() const { return flags & Helio_ActivationFlags_Forced; } 36 | inline float getDriveIntensity() const { return direction == Helio_DirectionMode_Forward ? intensity : 37 | direction == Helio_DirectionMode_Reverse ? -intensity : 0.0f; } 38 | }; 39 | 40 | // Activation Handle 41 | // Since actuators are shared objects, those wishing to enable any actuator must receive 42 | // a valid handle. Actuators may customize how they handle multiple activation handles. 43 | // Handles represent a driving intensity value ranged [0,1] or [-1,1] depending on the 44 | // capabilities of the attached actuator. Handles do not guarantee activation unless their 45 | // forced flag is set (also see Actuator activation signal), but can be set up to ensure 46 | // actuators are enabled for a specified duration, which is able to be async updated. 47 | struct HelioActivationHandle { 48 | SharedPtr actuator; // Actuator owner, set only when activation requested (use operator= to set) 49 | HelioActivation activation; // Activation data 50 | millis_t checkTime; // Last check timestamp, in milliseconds, else 0 for not started 51 | millis_t elapsed; // Elapsed time accumulator, in milliseconds, else 0 52 | 53 | // Handle constructor that specifies a normalized enablement, ranged: [0.0,1.0] for specified direction 54 | HelioActivationHandle(SharedPtr actuator, Helio_DirectionMode direction, float intensity = 1.0f, millis_t duration = -1, bool force = false); 55 | 56 | // Default constructor for empty handles 57 | inline HelioActivationHandle() : HelioActivationHandle(nullptr, Helio_DirectionMode_Undefined, 0.0f, 0, false) { ; } 58 | HelioActivationHandle(const HelioActivationHandle &handle); 59 | ~HelioActivationHandle(); 60 | HelioActivationHandle &operator=(SharedPtr actuator); 61 | inline HelioActivationHandle &operator=(const HelioActivation &activationIn) { activation = activationIn; return *this; } 62 | inline HelioActivationHandle &operator=(const HelioActivationHandle &handle) { activation = handle.activation; return operator=(handle.actuator); } 63 | 64 | // Disconnects activation from an actuator (removes handle reference from actuator) 65 | void unset(); 66 | 67 | // Elapses activation by delta, updating relevant activation values 68 | void elapseBy(millis_t delta); 69 | inline void elapseTo(millis_t time = nzMillis()) { elapseBy(time - checkTime); } 70 | 71 | inline bool isActive() const { return actuator && isValidTime(checkTime); } 72 | inline bool isValid() const { return activation.isValid(); } 73 | inline bool isDone() const { return activation.isDone(); } 74 | inline bool isUntimed() const { return activation.isUntimed(); } 75 | inline bool isForced() const { return activation.isForced(); } 76 | 77 | inline millis_t getTimeLeft() const { return activation.duration; } 78 | inline millis_t getTimeActive(millis_t time = nzMillis()) const { return isActive() ? (time - checkTime) + elapsed : elapsed; } 79 | 80 | // De-normalized driving intensity value [-1.0,1.0] 81 | inline float getDriveIntensity() const { return activation.getDriveIntensity(); } 82 | }; 83 | 84 | #endif // /ifndef HelioActivation_H 85 | -------------------------------------------------------------------------------- /src/HelioAttachments.hpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Attachment Points 4 | */ 5 | 6 | #include "Helioduino.h" 7 | 8 | inline HelioDLinkObject &HelioDLinkObject::operator=(HelioIdentity rhs) 9 | { 10 | _key = rhs.key; 11 | _obj = nullptr; 12 | if (_keyStr) { free((void *)_keyStr); _keyStr = nullptr; } 13 | 14 | auto len = rhs.keyString.length(); 15 | if (len) { 16 | _keyStr = (const char *)malloc(len + 1); 17 | strncpy((char *)_keyStr, rhs.keyString.c_str(), len + 1); 18 | } 19 | return *this; 20 | } 21 | 22 | inline HelioDLinkObject &HelioDLinkObject::operator=(const char *rhs) 23 | { 24 | _key = stringHash(rhs); 25 | _obj = nullptr; 26 | if (_keyStr) { free((void *)_keyStr); _keyStr = nullptr; } 27 | 28 | auto len = strnlen(rhs, HELIO_NAME_MAXSIZE); 29 | if (len) { 30 | _keyStr = (const char *)malloc(len + 1); 31 | strncpy((char *)_keyStr, rhs, len + 1); 32 | } 33 | return *this; 34 | } 35 | 36 | inline HelioDLinkObject &HelioDLinkObject::operator=(const HelioObjInterface *rhs) 37 | { 38 | _key = rhs ? rhs->getKey() : hkey_none; 39 | _obj = rhs ? rhs->getSharedPtr() : nullptr; 40 | if (_keyStr) { free((void *)_keyStr); _keyStr = nullptr; } 41 | 42 | return *this; 43 | } 44 | 45 | inline HelioDLinkObject &HelioDLinkObject::operator=(const HelioAttachment *rhs) 46 | { 47 | _key = rhs ? rhs->getKey() : hkey_none; 48 | _obj = rhs && rhs->isResolved() ? rhs->getSharedPtr() : nullptr; 49 | if (_keyStr) { free((void *)_keyStr); _keyStr = nullptr; } 50 | 51 | if (rhs && !rhs->isResolved()) { 52 | String keyString = rhs->getKeyString(); 53 | auto len = keyString.length(); 54 | if (len) { 55 | _keyStr = (const char *)malloc(len + 1); 56 | strncpy((char *)_keyStr, keyString.c_str(), len + 1); 57 | } 58 | } 59 | return *this; 60 | } 61 | 62 | template 63 | inline HelioDLinkObject &HelioDLinkObject::operator=(SharedPtr &rhs) 64 | { 65 | _key = rhs ? rhs->getKey() : hkey_none; 66 | _obj = rhs ? static_pointer_cast(rhs) : nullptr; 67 | if (_keyStr) { free((void *)_keyStr); _keyStr = nullptr; } 68 | 69 | return *this; 70 | } 71 | 72 | 73 | template 74 | void HelioAttachment::setObject(U obj, bool modify) 75 | { 76 | if (!(_obj == obj)) { 77 | if (_obj.isResolved()) { detachObject(); } 78 | 79 | _obj = obj; // will be replaced by templated operator= inline 80 | 81 | if (_obj.isResolved()) { attachObject(); } 82 | 83 | if (modify && _parent) { 84 | if (_parent->isObject()) { 85 | ((HelioObject *)_parent)->bumpRevisionIfNeeded(); 86 | } else { 87 | ((HelioSubObject *)_parent)->bumpRevisionIfNeeded(); 88 | } 89 | } 90 | } 91 | } 92 | 93 | template 94 | SharedPtr HelioAttachment::getObject() 95 | { 96 | if (_obj) { return _obj.getObject(); } 97 | else if (!_obj.isSet()) { return nullptr; } 98 | else if (_obj.needsResolved() && _obj.resolveObject()) { 99 | attachObject(); 100 | } 101 | return _obj.getObject(); 102 | } 103 | 104 | 105 | template template 106 | HelioSignalAttachment::HelioSignalAttachment(HelioObjInterface *parent, hposi_t subIndex, Signal &(U::*signalGetter)(void)) 107 | : HelioAttachment(parent, subIndex), _signalGetter((SignalGetterPtr)signalGetter), _handleSlot(nullptr) 108 | { ; } 109 | 110 | template 111 | HelioSignalAttachment::HelioSignalAttachment(const HelioSignalAttachment &attachment) 112 | : HelioAttachment(attachment), _signalGetter((SignalGetterPtr)attachment._signalGetter), 113 | _handleSlot(attachment._handleSlot ? attachment._handleSlot->clone() : nullptr) 114 | { ; } 115 | 116 | template 117 | HelioSignalAttachment::~HelioSignalAttachment() 118 | { 119 | if (isResolved() && _handleSlot && _signalGetter) { 120 | (get()->*_signalGetter)().detach(*_handleSlot); 121 | } 122 | if (_handleSlot) { 123 | delete _handleSlot; _handleSlot = nullptr; 124 | } 125 | } 126 | 127 | template 128 | void HelioSignalAttachment::attachObject() 129 | { 130 | HelioAttachment::attachObject(); 131 | 132 | if (isResolved() && _handleSlot && _signalGetter) { 133 | (get()->*_signalGetter)().attach(*_handleSlot); 134 | } 135 | } 136 | 137 | template 138 | void HelioSignalAttachment::detachObject() 139 | { 140 | if (isResolved() && _handleSlot && _signalGetter) { 141 | (get()->*_signalGetter)().detach(*_handleSlot); 142 | } 143 | 144 | HelioAttachment::detachObject(); 145 | } 146 | 147 | template template 148 | void HelioSignalAttachment::setSignalGetter(Signal &(U::*signalGetter)(void)) 149 | { 150 | if (_signalGetter != signalGetter) { 151 | if (isResolved() && _handleSlot && _signalGetter) { (get()->*_signalGetter)().detach(*_handleSlot); } 152 | 153 | _signalGetter = signalGetter; 154 | 155 | if (isResolved() && _handleSlot && _signalGetter) { (get()->*_signalGetter)().attach(*_handleSlot); } 156 | } 157 | } 158 | 159 | template 160 | void HelioSignalAttachment::setHandleSlot(const Slot &handleSlot) 161 | { 162 | if (!_handleSlot || !_handleSlot->operator==(&handleSlot)) { 163 | if (isResolved() && _handleSlot && _signalGetter) { (get()->*_signalGetter)().detach(*_handleSlot); } 164 | 165 | if (_handleSlot) { delete _handleSlot; _handleSlot = nullptr; } 166 | _handleSlot = handleSlot.clone(); 167 | 168 | if (isResolved() && _handleSlot && _signalGetter) { (get()->*_signalGetter)().attach(*_handleSlot); } 169 | } 170 | } 171 | 172 | 173 | inline Helio_UnitsType HelioActuatorAttachment::getActivationUnits() 174 | { 175 | return resolve() && get()->getUserCalibrationData() ? get()->getUserCalibrationData()->calibrationUnits : Helio_UnitsType_Raw_1; 176 | } 177 | 178 | inline float HelioActuatorAttachment::getActiveDriveIntensity() 179 | { 180 | return resolve() ? get()->getDriveIntensity() : 0.0f; 181 | } 182 | 183 | inline float HelioActuatorAttachment::getActiveCalibratedValue() 184 | { 185 | return resolve() ? get()->getCalibratedValue() : 0.0f; 186 | } 187 | 188 | inline float HelioActuatorAttachment::getSetupDriveIntensity() const 189 | { 190 | return _actSetup.intensity; 191 | } 192 | 193 | inline float HelioActuatorAttachment::getSetupCalibratedValue() 194 | { 195 | return resolve() ? get()->calibrationTransform(_actSetup.intensity) : 0.0f; 196 | } 197 | 198 | 199 | inline Helio_TriggerState HelioTriggerAttachment::getTriggerState(bool poll) 200 | { 201 | return resolve() ? get()->getTriggerState(poll) : Helio_TriggerState_Undefined; 202 | } 203 | 204 | 205 | inline Helio_DrivingState HelioDriverAttachment::getDrivingState(bool poll) 206 | { 207 | return resolve() ? get()->getDrivingState(poll) : Helio_DrivingState_Undefined; 208 | } 209 | -------------------------------------------------------------------------------- /src/HelioCallback.hh: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Signal Callback 4 | */ 5 | // Copied and modified from: https://github.com/tomstewart89/Callback 6 | 7 | #ifndef HelioCallback_H 8 | #define HelioCallback_H 9 | 10 | #include "Helioduino.h" 11 | 12 | enum SlotType : signed char { Function, Method }; 13 | 14 | // The Slot base class, its template parameter indicates the datatype of the parameters it expects to receive. Slots can only 15 | // be connected to Signals with identical ParameterTypes. 16 | template class Slot { 17 | protected: 18 | SlotType _slotType; 19 | 20 | Slot(SlotType slotType) : _slotType(slotType) { } 21 | 22 | public: 23 | virtual ~Slot() { } 24 | 25 | // Allows the slot to be called by the signal during firing. 26 | virtual void operator()(ParameterType param) const = 0; 27 | 28 | // Allows the slot to be removed via comparison. 29 | virtual bool operator==(const Slot* slot) const = 0; 30 | 31 | // Allows the signal to take a copy of the slot so that it can maintain an internal reference to it upon connection. 32 | // Essentially a virtual copy consructor. 33 | virtual Slot* clone() const = 0; 34 | 35 | // Provides roughly the same mechanism as RTTI. 36 | SlotType slotType() const { 37 | return _slotType; 38 | } 39 | }; 40 | 41 | // The Signal class, we can implant these into ends and allow means to connect their members to them should they want to 42 | // receive callbacks from their children means. Ofcourse it's possible that these callbacks are made within the context of 43 | // an interrupt so the receipient will want to be fairly quick about how they process it. 44 | template class Signal { 45 | Vector *, Slots> _connections; 46 | 47 | public: 48 | Signal() : _connections() { } 49 | 50 | // Since the signal takes copies of all the input slots via clone() it needs to clean up after itself when being destroyed. 51 | virtual ~Signal() { 52 | for (auto iter = _connections.begin(); iter != _connections.end(); ++iter) { 53 | if (*iter) { delete *iter; *iter = nullptr; } 54 | } 55 | } 56 | 57 | // Adds slot to list of connections. 58 | void attach(const Slot& slot) { 59 | // Connect it up and away we go 60 | _connections.push_back(slot.clone()); 61 | } 62 | 63 | // Removes slot from list of connections. 64 | void detach(const Slot& slot) { 65 | for (auto iter = _connections.begin(); iter != _connections.end(); ++iter) { 66 | if (!(*iter) || slot.operator==(*iter)) { 67 | if (*iter) { delete *iter; *iter = nullptr; } 68 | iter = _connections.erase(iter) - 1; 69 | } 70 | } 71 | } 72 | 73 | // Visits each of its listeners and executes them via operator(). 74 | void fire(ParameterType param) const { 75 | for (auto iter = _connections.begin(); iter != _connections.end(); ++iter) { 76 | if (*iter) { (*(*iter))(param); } 77 | } 78 | } 79 | }; 80 | 81 | // FunctionSlot is a subclass of Slot for use with function pointers. In truth there's not really any need to wrap up free 82 | // standing function pointers into slots since any function in C/C++ is happy to accept a raw function pointer and execute it. 83 | // However this system allows free standing functions to be used alongside member functions or even arbitrary functor objects. 84 | template class FunctionSlot : public Slot { 85 | typedef void (*FunctPtr)(ParameterType); 86 | 87 | // A free standing function pointer. 88 | FunctPtr _funct; 89 | 90 | public: 91 | FunctionSlot() : Slot(Function), _funct(nullptr) { } 92 | FunctionSlot(FunctPtr funct) : Slot(Function), _funct(funct) { } 93 | 94 | // Copy the slot 95 | virtual Slot *clone() const override { 96 | return new FunctionSlot(_funct); 97 | } 98 | 99 | // Execute the slot. 100 | virtual void operator() (ParameterType param) const override { 101 | return (_funct)(param); 102 | } 103 | 104 | // Test the slot. 105 | inline operator bool() const { return _funct; } 106 | 107 | // Function access. 108 | inline FunctPtr getFunct() const { return _funct; } 109 | 110 | // Compares the slot. 111 | virtual bool operator==(const Slot* slot) const override { 112 | if (slot && slot->slotType() == Slot::_slotType) { 113 | const FunctionSlot* functSlot = reinterpret_cast*>(slot); 114 | return functSlot && functSlot->_funct == _funct; 115 | } 116 | return false; 117 | } 118 | }; 119 | 120 | // MethodSlot is a subclass of Slot that allows member function pointers to be used as slots. While free standing 121 | // pointers to functions are relatively intuitive here, Members functions need an additional template parameter, the 122 | // owner object type and they are executed via the ->* operator. 123 | template class MethodSlot : public Slot { 124 | typedef void (ObjectType::*FunctPtr)(ParameterType); 125 | 126 | // The function pointer's owner object. 127 | ObjectType *_obj; 128 | 129 | // A function-pointer-to-method of class ObjectType. 130 | FunctPtr _funct; 131 | 132 | public: 133 | MethodSlot() : Slot(Method), _obj(nullptr), _funct(nullptr) { } 134 | MethodSlot(ObjectType *obj, FunctPtr funct) : Slot(Method), _obj(obj), _funct(funct) { } 135 | template MethodSlot(const MethodSlot &slot) 136 | : Slot(Method), _obj(reinterpret_cast(slot.getObject())), _funct(reinterpret_cast(slot.getFunct())) { } 137 | 138 | // Copy the slot. 139 | virtual Slot *clone() const override { 140 | return new MethodSlot(_obj, _funct); 141 | } 142 | 143 | // Execute the slot. 144 | virtual void operator() (ParameterType param) const override { 145 | return (_obj->*_funct)(param); 146 | } 147 | 148 | // Test the slot. 149 | inline operator bool() const { return _obj && _funct; } 150 | 151 | // Object access. 152 | inline ObjectType *getObject() const { return _obj; } 153 | 154 | // Function access. 155 | inline FunctPtr getFunct() const { return _funct; } 156 | 157 | // Compare the slot. 158 | virtual bool operator==(const Slot* slot) const override { 159 | if (slot && slot->slotType() == Slot::_slotType) { 160 | const MethodSlot* methSlot = reinterpret_cast*>(slot); 161 | return methSlot && methSlot->_obj == _obj && methSlot->_funct == _funct; 162 | } 163 | return false; 164 | } 165 | }; 166 | 167 | #endif // HelioCallback_H 168 | -------------------------------------------------------------------------------- /src/HelioData.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Data 4 | */ 5 | 6 | #include "Helioduino.h" 7 | 8 | size_t serializeDataToBinaryStream(const HelioData *data, Stream *streamOut, size_t skipBytes) 9 | { 10 | return streamOut->write((const uint8_t *)((intptr_t)data + skipBytes), data->_size - skipBytes); 11 | } 12 | 13 | size_t deserializeDataFromBinaryStream(HelioData *data, Stream *streamIn, size_t skipBytes) 14 | { 15 | return streamIn->readBytes((uint8_t *)((intptr_t)data + skipBytes), data->_size - skipBytes); 16 | } 17 | 18 | HelioData *newDataFromBinaryStream(Stream *streamIn) 19 | { 20 | HelioData baseDecode; 21 | size_t readBytes = deserializeDataFromBinaryStream(&baseDecode, streamIn, sizeof(void*)); 22 | HELIO_SOFT_ASSERT(readBytes == baseDecode._size - sizeof(void*), SFP(HStr_Err_ImportFailure)); 23 | 24 | if (readBytes) { 25 | HelioData *data = _allocateDataFromBaseDecode(baseDecode); 26 | HELIO_SOFT_ASSERT(data, SFP(HStr_Err_AllocationFailure)); 27 | 28 | if (data) { 29 | readBytes += deserializeDataFromBinaryStream(data, streamIn, readBytes + sizeof(void*)); 30 | HELIO_SOFT_ASSERT(readBytes == data->_size - sizeof(void*), SFP(HStr_Err_ImportFailure)); 31 | 32 | return data; 33 | } 34 | } 35 | 36 | return nullptr; 37 | } 38 | 39 | HelioData *newDataFromJSONObject(JsonObjectConst &objectIn) 40 | { 41 | HelioData baseDecode; 42 | baseDecode.fromJSONObject(objectIn); 43 | 44 | HelioData *data = _allocateDataFromBaseDecode(baseDecode); 45 | HELIO_SOFT_ASSERT(data, SFP(HStr_Err_AllocationFailure)); 46 | 47 | if (data) { 48 | data->fromJSONObject(objectIn); 49 | return data; 50 | } 51 | 52 | return nullptr; 53 | } 54 | 55 | 56 | HelioData::HelioData() 57 | : id{.chars={'\000','\000','\000','\000'}}, _version(1), _revision(-1) 58 | { 59 | _size = sizeof(*this); 60 | } 61 | 62 | HelioData::HelioData(char id0, char id1, char id2, char id3, uint8_t version, uint8_t revision) 63 | : id{.chars={id0,id1,id2,id3}}, _version(version), _revision(revision) 64 | { 65 | _size = sizeof(*this); 66 | HELIO_HARD_ASSERT(isStandardData(), SFP(HStr_Err_InvalidParameter)); 67 | } 68 | 69 | HelioData::HelioData(hid_t idType, hid_t objType, hposi_t posIndex, hid_t classType, uint8_t version, uint8_t revision) 70 | : id{.object={idType,objType,posIndex,classType}}, _version(version), _revision(revision) 71 | { 72 | _size = sizeof(*this); 73 | } 74 | 75 | HelioData::HelioData(const HelioIdentity &id) 76 | : HelioData(id.type, id.objTypeAs.idType, id.posIndex, -1, 1, 0) 77 | { 78 | _size = sizeof(*this); 79 | } 80 | 81 | void HelioData::toJSONObject(JsonObject &objectOut) const 82 | { 83 | if (isStandardData()) { 84 | objectOut[SFP(HStr_Key_Type)] = charsToString(id.chars, sizeof(id.chars)); 85 | } else { 86 | int8_t typeVals[4] = {id.object.idType, id.object.objType, id.object.posIndex, id.object.classType}; 87 | objectOut[SFP(HStr_Key_Type)] = commaStringFromArray(typeVals, 4); 88 | } 89 | if (_version > 1) { objectOut[SFP(HStr_Key_Version)] = _version; } 90 | if (getRevision() > 1) { objectOut[SFP(HStr_Key_Revision)] = getRevision(); } 91 | } 92 | 93 | void HelioData::fromJSONObject(JsonObjectConst &objectIn) 94 | { 95 | JsonVariantConst idVar = objectIn[SFP(HStr_Key_Type)]; 96 | const char *idStr = idVar.as(); 97 | if (idStr && idStr[0] == 'H') { 98 | strncpy(id.chars, idStr, 4); 99 | } else if (idStr) { 100 | int8_t typeVals[4]; 101 | commaStringToArray(idStr, typeVals, 4); 102 | id.object.idType = typeVals[0]; 103 | id.object.objType = typeVals[1]; 104 | id.object.posIndex = typeVals[2]; 105 | id.object.classType = typeVals[3]; 106 | } 107 | _version = objectIn[SFP(HStr_Key_Version)] | _version; 108 | _revision = objectIn[SFP(HStr_Key_Revision)] | _revision; 109 | _revision = abs(_revision); 110 | } 111 | 112 | 113 | HelioSubData::HelioSubData() 114 | : type(hid_none) 115 | { ; } 116 | 117 | HelioSubData::HelioSubData(hid_t dataType) 118 | : type(dataType) 119 | { ; } 120 | 121 | void HelioSubData::toJSONObject(JsonObject &objectOut) const 122 | { 123 | if (isSet()) { objectOut[SFP(HStr_Key_Type)] = type; } 124 | } 125 | 126 | void HelioSubData::fromJSONObject(JsonObjectConst &objectIn) 127 | { 128 | type = objectIn[SFP(HStr_Key_Type)] | type; 129 | } 130 | -------------------------------------------------------------------------------- /src/HelioData.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Data 4 | */ 5 | 6 | #ifndef HelioData_H 7 | #define HelioData_H 8 | 9 | struct HelioData; 10 | struct HelioSubData; 11 | 12 | #include "Helioduino.h" 13 | 14 | // Serializes Helio data structure to a binary output stream (essentially a memcpy), with optional skipBytes 15 | extern size_t serializeDataToBinaryStream(const HelioData *data, Stream *streamOut, size_t skipBytes = sizeof(void*)); 16 | // Deserializes Helio data structure from a binary input stream (essentially a memcpy), with optional skipBytes 17 | extern size_t deserializeDataFromBinaryStream(HelioData *data, Stream *streamIn, size_t skipBytes = sizeof(void*)); 18 | 19 | // Creates a new Helio data object corresponding to a binary input stream (return ownership transfer - user code *must* delete returned data) 20 | extern HelioData *newDataFromBinaryStream(Stream *streamIn); 21 | // Creates a new Helio data object corresponding to an input JSON element (return ownership transfer - user code *must* delete returned data) 22 | extern HelioData *newDataFromJSONObject(JsonObjectConst &objectIn); 23 | 24 | 25 | // Data Base 26 | // Base class for serializable (JSON+Binary) storage data, used to define the base 27 | // header of all data stored internally. 28 | // NOTE: NON-CONST VALUE TYPES ONLY. All data *MUST* be able to use default operator=, constructor, and destructor. 29 | struct HelioData : public HelioJSONSerializableInterface { 30 | union { 31 | char chars[4]; // Standalone data structure 4-char identifier 32 | struct { 33 | hid_t idType; // Object ID type enum value (e.g. actuator, sensor, etc.) 34 | hid_t objType; // Object type enum value (e.g. actuatorType, sensorType, etc.) 35 | hposi_t posIndex; // Object position index # (zero-ordinal) 36 | hid_t classType; // Object class type enum value (e.g. motor, dht1w, etc.) 37 | } object; 38 | } id; // Identifier union 39 | uint16_t _size; // The size (in bytes) of the data 40 | uint8_t _version; // Version # of data container 41 | int8_t _revision; // Revision # of stored data (uses -vals for modified flag) 42 | 43 | inline bool isStandardData() const { return id.chars[0] == 'H'; } 44 | inline bool isSystemData() const { return isStandardData() && id.chars[1] == 'S' && id.chars[2] == 'Y' && id.chars[3] == 'S'; } 45 | inline bool isCalibrationData() const { return isStandardData() && id.chars[1] == 'C' && id.chars[2] == 'A' && id.chars[3] == 'L'; } 46 | inline bool isUIData() const { return isStandardData() && id.chars[1] == 'U' && id.chars[2] == 'I' && id.chars[3] == 'D'; } 47 | inline bool isObjectData() const { return !isStandardData() && id.object.idType >= 0; } 48 | 49 | HelioData(); // Default constructor 50 | HelioData(char id0, // 4-char identifier, index 0 51 | char id1, // 4-char identifier, index 1 52 | char id2, // 4-char identifier, index 2 53 | char id3, // 4-char identifier, index 3 54 | uint8_t version = 1, // Data structure version # 55 | uint8_t revision = 1); // Stored data revision # 56 | HelioData(hid_t idType, // ID type enum value 57 | hid_t objType, // Object type enum value 58 | hposi_t posIndex, // Object position index # 59 | hid_t classType, // Class type enum value 60 | uint8_t version = 1, // Data structure version # 61 | uint8_t revision = 1); // Stored data revision # 62 | HelioData(const HelioIdentity &id); // Identity constructor 63 | 64 | virtual void toJSONObject(JsonObject &objectOut) const override; 65 | virtual void fromJSONObject(JsonObjectConst &objectIn) override; 66 | 67 | inline uint8_t getRevision() const { return abs(_revision); } 68 | inline bool isModified() const { return _revision < 0; } 69 | inline void bumpRevisionIfNeeded() { if (_revision >= 0) { _revision = -(abs(_revision) + 1); } } // Should be called before modifying data 70 | inline void unsetModified() { _revision = abs(_revision); } // Should be called after save-out 71 | }; 72 | 73 | 74 | // Sub Data Base 75 | // Sub-data exists inside of regular data for smaller objects that don't require the 76 | // entire data object hierarchy, useful for triggers, measurements, etc. 77 | // NOTE: NON-CONST VALUE TYPES ONLY, NO VIRTUALS. All data *MUST* be able to use default operator=. 78 | struct HelioSubData { 79 | hid_t type; // Sub data type, else -1/none 80 | 81 | HelioSubData(); 82 | HelioSubData(hid_t dataType); 83 | void toJSONObject(JsonObject &objectOut) const; 84 | void fromJSONObject(JsonObjectConst &objectIn); 85 | 86 | inline bool isSet() const { return isValidType(type); } 87 | }; 88 | 89 | 90 | // Internal use, but must contain all ways for all data types to be new'ed 91 | extern HelioData *_allocateDataFromBaseDecode(const HelioData &baseDecode); 92 | extern HelioData *_allocateDataForObjType(int8_t idType, int8_t classType); 93 | 94 | #endif // /ifndef HelioData_H 95 | -------------------------------------------------------------------------------- /src/HelioDrivers.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Drivers 4 | */ 5 | 6 | #ifndef HelioDrivers_H 7 | #define HelioDrivers_H 8 | 9 | class HelioDriver; 10 | class HelioAbsoluteDriver; 11 | class HelioIncrementalDriver; 12 | 13 | #include "Helioduino.h" 14 | #include "HelioObject.h" 15 | #include "HelioTriggers.h" 16 | 17 | // Driver Base 18 | // This is the base class for all driver objects, which are used to modify the external 19 | // environment via a set of movement actuators along a specified track. Drivers allow for 20 | // a set-point to be used to drive such tasks, with different drivers specializing the 21 | // manner in which they operate. 22 | class HelioDriver : public HelioSubObject, 23 | public HelioDriverObjectInterface, 24 | public HelioMeasurementUnitsInterfaceStorageSingle { 25 | public: 26 | const enum : signed char { Absolute, Incremental, Unknown = -1 } type; // Driver type (custom RTTI) 27 | inline bool isAbsoluteType() const { return type == Absolute; } 28 | inline bool isIncrementalType() const { return type == Incremental; } 29 | inline bool isUnknownType() const { return type <= Unknown; } 30 | 31 | HelioDriver(float targetSetpoint, 32 | float travelRate, 33 | int type = Unknown); 34 | virtual ~HelioDriver(); 35 | 36 | virtual void update(); 37 | 38 | virtual float getMaxTargetOffset(bool poll = false) override; 39 | virtual Helio_DrivingState getDrivingState(bool poll = false) override; 40 | 41 | void setActuators(const Vector &actuators); 42 | inline const Vector &getActuators() { return _actuators; } 43 | 44 | virtual void setTargetSetpoint(float targetSetpoint) override; 45 | inline float getTargetSetpoint() const { return _targetSetpoint; } 46 | inline void setTravelRate(float travelRate) { _travelRate = travelRate; } 47 | inline float getTravelRate() const { return _travelRate; } 48 | inline bool isInstantaneous() const { return _travelRate == FLT_UNDEF; } 49 | inline Pair getTrackRange() const { return _trackRange; } 50 | 51 | virtual void setEnabled(bool enabled); 52 | inline bool isEnabled() const { return _enabled; } 53 | 54 | virtual void setMeasurementUnits(Helio_UnitsType measurementUnits, uint8_t = 0) override; 55 | virtual Helio_UnitsType getMeasurementUnits(uint8_t = 0) const override; 56 | 57 | Signal &getDrivingSignal(); 58 | 59 | protected: 60 | Pair _trackRange; // Track total range 61 | float _targetSetpoint; // Target set-point value 62 | float _travelRate; // Travel rate (distance units / min) 63 | Helio_DrivingState _drivingState; // Driving state (last handled) 64 | bool _enabled; // Enabled flag 65 | Signal _drivingSignal; // Driving signal 66 | Vector _actuators; // Actuator attachments 67 | 68 | void disableAllActivations(); 69 | 70 | virtual void handleMaxOffset(float maxOffset) = 0; 71 | }; 72 | 73 | 74 | // Absolute Driver 75 | // The absolute driver manages a position-based actuator list driven by an intensity 76 | // value corresponding to a positional offset. A travel rate of FLT_UNDEF is considered 77 | // instantaneous. Suitable for driving simple positional servos. 78 | class HelioAbsoluteDriver : public HelioDriver { 79 | public: 80 | HelioAbsoluteDriver(float travelRate = FLT_UNDEF, 81 | int type = Absolute); 82 | virtual ~HelioAbsoluteDriver(); 83 | 84 | virtual void setEnabled(bool enabled) override; 85 | 86 | protected: 87 | millis_t _lastUpdate; // Last update millis (for delta-time rate application) 88 | 89 | virtual void handleMaxOffset(float maxOffset) override; 90 | }; 91 | 92 | 93 | // Incremental Driver 94 | // The incremental driver manages a direction-based actuator list driven by an intensity 95 | // value corresponding to a speed control. Driver will enter fine driving mode once within 96 | // nearby range, and will consider itself aligned once within aligned range. Travel rate 97 | // only relevant for variable speed motors. Will attempt to maintain a maximum difference 98 | // between leading and trailing actuators. Suitable for driving continuous servos & motors 99 | // that must stay in sync or risk physical breakage. 100 | // All actuators must have position data (be derived from HelioPositionSensorAttachmentInterface). 101 | class HelioIncrementalDriver : public HelioDriver { 102 | public: 103 | HelioIncrementalDriver(float nearbyRange = 0.5f, 104 | float alignedRange = 0.05f, 105 | float maxDifference = 2.5f, 106 | float travelRate = 1.0f, 107 | int type = Incremental); 108 | virtual ~HelioIncrementalDriver(); 109 | 110 | virtual Helio_DrivingState getDrivingState(bool poll = false) override; 111 | 112 | protected: 113 | float _nearbyRange; // Nearby target range (for fine/coarse control) 114 | float _alignedRange; // Aligned to target range 115 | float _maxDifference; // Maximum positional difference 116 | 117 | virtual void handleMaxOffset(float maxOffset) override; 118 | }; 119 | 120 | #endif // /ifndef HelioDrivers_H 121 | -------------------------------------------------------------------------------- /src/HelioLogger.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Logger 4 | */ 5 | 6 | #ifndef HelioLogger_H 7 | #define HelioLogger_H 8 | 9 | class HelioLogger; 10 | struct HelioLoggerSubData; 11 | 12 | #include "Helioduino.h" 13 | 14 | // Logging Level 15 | // Log levels that can be filtered upon if desired. 16 | enum Helio_LogLevel : signed char { 17 | Helio_LogLevel_All, // All (info, warn, err) 18 | Helio_LogLevel_Warnings, // Warnings & errors (warn, err) 19 | Helio_LogLevel_Errors, // Just errors (err) 20 | Helio_LogLevel_None = -1, // None / disabled 21 | Helio_LogLevel_Info = Helio_LogLevel_All // Info alias 22 | }; 23 | 24 | // Logging Events 25 | // Logging event structure that is used in signaling. 26 | struct HelioLogEvent { 27 | Helio_LogLevel level; // Log level 28 | String timestamp; // Timestamp (generated) 29 | String prefix; // Prefix 30 | String msg; // Message 31 | String suffix1; // Suffix1 (optional) 32 | String suffix2; // Suffix2 (optional) 33 | 34 | HelioLogEvent(Helio_LogLevel levelIn, 35 | const String &prefixIn, 36 | const String &msgIn, 37 | const String &suffix1In = String(), 38 | const String &suffix2In = String()); 39 | }; 40 | 41 | // Data Logger 42 | // The Logger acts as the system's event monitor that collects and reports on the various 43 | // processes of interest inside of the system. It allows for different log levels to be 44 | // used that can help filter out unwanted noise, as well as attempts to be more optimized 45 | // for embedded systems by spreading string data out over multiple call parameters to 46 | // avoid large string concatenations that can overstress and crash constrained devices. 47 | // Logging to SD card .txt log files (via SPI card reader) is supported as is logging to 48 | // WiFiStorage .txt log files (via OS/OTA filesystem / WiFiNINA_Generic only). 49 | class HelioLogger { 50 | public: 51 | HelioLogger(); 52 | ~HelioLogger(); 53 | 54 | bool beginLoggingToSDCard(String logFilePrefix); 55 | inline bool isLoggingToSDCard() const; 56 | 57 | #ifdef HELIO_USE_WIFI_STORAGE 58 | bool beginLoggingToWiFiStorage(String logFilePrefix); 59 | inline bool isLoggingToWiFiStorage() const; 60 | #endif 61 | 62 | inline void logActivation(const HelioActuator *actuator); 63 | inline void logDeactivation(const HelioActuator *actuator); 64 | inline void logProcess(const HelioObjInterface *obj, const String &processString = String(), const String &statusString = String()); 65 | inline void logStatus(const HelioObjInterface *obj, const String &statusString = String()); 66 | 67 | void logSystemUptime(); 68 | inline void logSystemSave() { logMessage(SFP(HStr_Log_SystemDataSaved)); } 69 | 70 | void logMessage(const String &msg, const String &suffix1 = String(), const String &suffix2 = String()); 71 | void logWarning(const String &warn, const String &suffix1 = String(), const String &suffix2 = String()); 72 | void logError(const String &err, const String &suffix1 = String(), const String &suffix2 = String()); 73 | void flush(); 74 | 75 | void setLogLevel(Helio_LogLevel logLevel); 76 | inline Helio_LogLevel getLogLevel() const; 77 | 78 | inline bool isLoggingEnabled() const; 79 | inline time_t getSystemUptime() const { return unixNow() - (_initTime ?: SECS_YR_2000); } 80 | 81 | Signal &getLogSignal(); 82 | 83 | void notifyDayChanged(); 84 | 85 | protected: 86 | #if HELIO_SYS_LEAVE_FILES_OPEN 87 | File *_logFileSD; // SD card log file instance (owned) 88 | #ifdef HELIO_USE_WIFI_STORAGE 89 | WiFiStorageFile *_logFileWS; // WiFiStorageFile log file instance (owned) 90 | #endif 91 | #endif 92 | String _logFilename; // Resolved log file name (based on day) 93 | time_t _initTime; // Time of init, for uptime (UTC) 94 | time_t _lastSpaceCheck; // Last time enough space was checked (UTC) 95 | 96 | Signal _logSignal; // Logging signal 97 | 98 | friend class Helioduino; 99 | 100 | inline HelioLoggerSubData *loggerData() const; 101 | inline bool hasLoggerData() const; 102 | 103 | inline void updateInitTracking() { _initTime = unixNow(); } 104 | void log(const HelioLogEvent &event); 105 | void cleanupOldestLogs(bool force = false); 106 | }; 107 | 108 | // Logger Serialization Sub Data 109 | // A part of HSYS system data. 110 | struct HelioLoggerSubData : public HelioSubData { 111 | Helio_LogLevel logLevel; // Log level filter (default: All) 112 | char logFilePrefix[HELIO_PREFIX_MAXSIZE]; // Base log file name prefix / folder (default: "logs/he") 113 | bool logToSDCard; // If system logging to SD card is enabled (default: false) 114 | bool logToWiFiStorage; // If system logging to WiFiStorage is enabled (default: false) 115 | 116 | HelioLoggerSubData(); 117 | void toJSONObject(JsonObject &objectOut) const; 118 | void fromJSONObject(JsonObjectConst &objectIn); 119 | }; 120 | 121 | #endif // /ifndef HelioLogger_H 122 | -------------------------------------------------------------------------------- /src/HelioModules.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Controller Modules 4 | */ 5 | 6 | #ifndef HelioModules_H 7 | #define HelioModules_H 8 | 9 | class HelioCalibrations; 10 | class HelioObjectRegistration; 11 | class HelioPinHandlers; 12 | 13 | #include "Helioduino.h" 14 | #include "HelioPins.h" 15 | 16 | // Calibrations Storage 17 | // Stores user calibration data, which calibrates the various sensors output to 18 | // an usable input value. 19 | class HelioCalibrations { 20 | public: 21 | // Adds/updates user calibration data to storage, returning success flag 22 | bool setUserCalibrationData(const HelioCalibrationData *calibrationData); 23 | 24 | // Drops/removes user calibration data from storage, returning success flag 25 | bool dropUserCalibrationData(const HelioCalibrationData *calibrationData); 26 | 27 | // Returns user calibration data instance in storage 28 | const HelioCalibrationData *getUserCalibrationData(hkey_t key) const; 29 | 30 | // Returns if there are any user calibrations in storage 31 | inline bool hasUserCalibrations() const { return _calibrationData.size(); }; 32 | 33 | protected: 34 | Map _calibrationData; // Loaded user calibration data 35 | }; 36 | 37 | 38 | // Object Registration Storage 39 | // Stores objects in main system store, which is used for SharedPtr<> lookups as well as 40 | // notifying appropriate modules upon entry-to/exit-from the system. 41 | class HelioObjectRegistration { 42 | public: 43 | // Adds object to system, returning success 44 | bool registerObject(SharedPtr obj); 45 | // Removes object from system, returning success 46 | bool unregisterObject(SharedPtr obj); 47 | 48 | // Searches for object by id key (nullptr return = no obj by that id, position index may use HELIO_POS_SEARCH* defines) 49 | SharedPtr objectById(HelioIdentity id) const; 50 | 51 | // Finds first position either open or taken, given the id type 52 | hposi_t firstPosition(HelioIdentity id, bool taken); 53 | // Finds first position taken, given the id type 54 | inline hposi_t firstPositionTaken(HelioIdentity id) { return firstPosition(id, true); } 55 | // Finds first position open, given the id type 56 | inline hposi_t firstPositionOpen(HelioIdentity id) { return firstPosition(id, false); } 57 | 58 | protected: 59 | Map, HELIO_SYS_OBJECTS_MAXSIZE> _objects; // Shared object collection, key'ed by HelioIdentity 60 | 61 | SharedPtr objectById_Col(const HelioIdentity &id) const; 62 | }; 63 | 64 | 65 | // Pin Handlers Storage 66 | // Stores various pin-related system data on a shared pin # basis. Covers: 67 | // - Pin locks: used for async shared resource management 68 | // - Pin muxers: used for i/o pin multiplexing across a shared address bus 69 | // - Pin expanders: used for i/o virtual pin expanding across an i2c interface 70 | // - Pin OneWire: used for digital sensor pin's OneWire owner 71 | class HelioPinHandlers { 72 | public: 73 | // Attempts to get a lock on pin #, to prevent multi-device comm overlap (e.g. for OneWire comms). 74 | bool tryGetPinLock(pintype_t pin, millis_t wait = 150); 75 | // Returns a locked pin lock for the given pin. Only call if pin lock was successfully locked. 76 | inline void returnPinLock(pintype_t pin) { _pinLocks.erase(pin); } 77 | 78 | // Sets pin muxer for pin #. 79 | inline void setPinMuxer(pintype_t pin, SharedPtr pinMuxer) { _pinMuxers[pin] = pinMuxer; } 80 | // Returns pin muxer for pin #. 81 | inline SharedPtr getPinMuxer(pintype_t pin) { return _pinMuxers[pin]; } 82 | // Deactivates all pin muxers. Called before selecting another channel if pin muxers are assumed 83 | // to have a shared address bus (based on HELIO_MUXERS_SHARED_ADDR_BUS setting). 84 | void deactivatePinMuxers(); 85 | 86 | #ifdef HELIO_USE_MULTITASKING 87 | 88 | // Sets pin expander for index. 89 | inline void setPinExpander(hposi_t index, SharedPtr pinExpander) { _pinExpanders[index] = pinExpander; } 90 | // Returns expander for index. 91 | inline SharedPtr getPinExpander(hposi_t index) { return _pinExpanders[index]; } 92 | 93 | #endif // /ifdef HELIO_USE_MULTITASKING 94 | 95 | // OneWire instance for given pin (lazily instantiated) 96 | OneWire *getOneWireForPin(pintype_t pin); 97 | // Drops OneWire instance for given pin (if created) 98 | void dropOneWireForPin(pintype_t pin); 99 | 100 | protected: 101 | Map _pinOneWire; // Pin OneWire mapping 102 | Map _pinLocks; // Pin locks mapping (existence = locked) 103 | Map, HELIO_SYS_PINMUXERS_MAXSIZE> _pinMuxers; // Pin muxers mapping 104 | #ifdef HELIO_USE_MULTITASKING 105 | Map, HELIO_SYS_PINEXPANDERS_MAXSIZE> _pinExpanders; // Pin expanders mapping 106 | #endif 107 | }; 108 | 109 | #endif // /ifndef HelioModules_H 110 | -------------------------------------------------------------------------------- /src/HelioPublisher.h: -------------------------------------------------------------------------------- 1 | 2 | /* Helioduino: Simple automation controller for solar tracking systems. 3 | Copyright (C) 2023 NachtRaveVL 4 | Helioduino Publisher 5 | */ 6 | 7 | #ifndef HelioPublisher_H 8 | #define HelioPublisher_H 9 | 10 | class HelioPublisher; 11 | struct HelioPublisherSubData; 12 | struct HelioDataColumn; 13 | 14 | #include "Helioduino.h" 15 | #include "HelioMeasurements.h" 16 | 17 | // Data Publisher 18 | // The Publisher allows for data collection and publishing capabilities. The data output 19 | // is based on a simple table of time and measured value. Each time segment, called a 20 | // polling frame (and controlled by the polling rate interval), collects data from all 21 | // sensors into a data row, with the appropriate total number of columns. At time of 22 | // either all sensors having reported in for their frame #, or the frame # proceeding 23 | // to advance (in which case the existing value is recycled), the table's row is 24 | // submitted to configured publishing services. 25 | // Publishing to SD card .csv data files (via SPI card reader) is supported as is logging to 26 | // WiFiStorage .csv data files (via OS/OTA filesystem / WiFiNINA_Generic only). MQTT is also 27 | // supported but requires additional setup. 28 | class HelioPublisher { 29 | public: 30 | HelioPublisher(); 31 | ~HelioPublisher(); 32 | 33 | void update(); 34 | 35 | bool beginPublishingToSDCard(String dataFilePrefix); 36 | inline bool isPublishingToSDCard() const; 37 | 38 | #ifdef HELIO_USE_WIFI_STORAGE 39 | bool beginPublishingToWiFiStorage(String dataFilePrefix); 40 | inline bool isPublishingToWiFiStorage() const; 41 | #endif 42 | 43 | #ifdef HELIO_USE_MQTT 44 | bool beginPublishingToMQTTClient(MQTTClient &client); 45 | inline bool isPublishingToMQTTClient() const; 46 | #endif 47 | 48 | void publishData(hposi_t columnIndex, HelioSingleMeasurement measurement); 49 | 50 | inline void setNeedsTabulation(); 51 | inline bool needsTabulation() { return _needsTabulation; } 52 | 53 | inline bool isPublishingEnabled() const; 54 | hposi_t getColumnIndexStart(hkey_t sensorKey); 55 | 56 | Signal, HELIO_PUBLISH_SIGNAL_SLOTS> &getPublishSignal(); 57 | 58 | void notifyDayChanged(); 59 | 60 | protected: 61 | #if HELIO_SYS_LEAVE_FILES_OPEN 62 | File *_dataFileSD; // SD card log file instance (owned) 63 | #ifdef HELIO_USE_WIFI_STORAGE 64 | WiFiStorageFile *_dataFileWS; // WiFiStorageFile log file instance (owned) 65 | #endif 66 | #endif 67 | #ifdef HELIO_USE_MQTT 68 | MQTTClient *_mqttClient; // MQTT client object (strong) 69 | #endif 70 | String _dataFilename; // Resolved data file name (based on day) 71 | hframe_t _pollingFrame; // Polling frame that publishing is caught up to 72 | bool _needsTabulation; // Needs tabulation tracking flag 73 | uint8_t _columnSize; // Number of data columns 74 | HelioDataColumn *_dataColumns; // Data columns array (owned) 75 | 76 | Signal, HELIO_PUBLISH_SIGNAL_SLOTS> _publishSignal; // Data publishing signal 77 | 78 | friend class Helioduino; 79 | 80 | inline HelioPublisherSubData *publisherData() const; 81 | inline bool hasPublisherData() const; 82 | 83 | void advancePollingFrame(); 84 | friend void dataLoop(); 85 | 86 | void publishIfNeeded(); 87 | void publish(time_t timestamp); 88 | 89 | void performTabulation(); 90 | 91 | void resetDataFile(); 92 | void cleanupOldestData(bool force = false); 93 | }; 94 | 95 | // Publisher Data Column 96 | // Data column worth of storage. Intended to be array allocated. 97 | struct HelioDataColumn { 98 | hkey_t sensorKey; // Key to sensor object 99 | HelioSingleMeasurement measurement; // Storage polling frame measurement 100 | }; 101 | 102 | 103 | // Publisher Serialization Sub Data 104 | // A part of HSYS system data. 105 | struct HelioPublisherSubData : public HelioSubData { 106 | char dataFilePrefix[HELIO_PREFIX_MAXSIZE]; // Base data file name prefix / folder (default: "data/he") 107 | bool pubToSDCard; // If publishing sensor data to SD card is enabled (default: false) 108 | bool pubToWiFiStorage; // If publishing sensor data to WiFiStorage is enabled (default: false) 109 | 110 | HelioPublisherSubData(); 111 | void toJSONObject(JsonObject &objectOut) const; 112 | void fromJSONObject(JsonObjectConst &objectIn); 113 | }; 114 | 115 | #endif // /ifndef HelioPublisher_H 116 | -------------------------------------------------------------------------------- /src/HelioRails.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Power Rails 4 | */ 5 | 6 | #ifndef HelioRails_H 7 | #define HelioRails_H 8 | 9 | class HelioRail; 10 | class HelioSimpleRail; 11 | class HelioRegulatedRail; 12 | 13 | struct HelioRailData; 14 | struct HelioSimpleRailData; 15 | struct HelioRegulatedRailData; 16 | 17 | #include "Helioduino.h" 18 | 19 | // Creates rail object from passed rail data (return ownership transfer - user code *must* delete returned object) 20 | extern HelioRail *newRailObjectFromData(const HelioRailData *dataIn); 21 | 22 | 23 | // Power Rail Base 24 | // This is the base class for all power rails, which defines how the rail is identified, 25 | // where it lives, what's attached to it, and who can activate under it. 26 | class HelioRail : public HelioObject, 27 | public HelioRailObjectInterface, 28 | public HelioPowerUnitsInterfaceStorage { 29 | public: 30 | const enum : signed char { Simple, Regulated, Unknown = -1 } classType; // Power rail class (custom RTTI) 31 | inline bool isSimpleClass() const { return classType == Simple; } 32 | inline bool isRegulatedClass() const { return classType == Regulated; } 33 | inline bool isUnknownClass() const { return classType <= Unknown; } 34 | 35 | HelioRail(Helio_RailType railType, 36 | hposi_t railIndex, 37 | int classType = Unknown); 38 | HelioRail(const HelioRailData *dataIn); 39 | virtual ~HelioRail(); 40 | 41 | virtual void update() override; 42 | 43 | virtual bool addLinkage(HelioObject *obj) override; 44 | virtual bool removeLinkage(HelioObject *obj) override; 45 | 46 | inline Helio_RailType getRailType() const { return _id.objTypeAs.railType; } 47 | inline hposi_t getRailIndex() const { return _id.posIndex; } 48 | inline float getRailVoltage() const { return getRailVoltageFromType(getRailType()); } 49 | 50 | Signal &getCapacitySignal(); 51 | 52 | protected: 53 | Helio_TriggerState _limitState; // Limit state (last handled) 54 | 55 | Signal _capacitySignal; // Capacity changed signal 56 | 57 | virtual HelioData *allocateData() const override; 58 | virtual void saveToData(HelioData *dataOut) override; 59 | 60 | void handleLimit(Helio_TriggerState limitState); 61 | friend class HelioRegulatedRail; 62 | }; 63 | 64 | // Simple Power Rail 65 | // Basic power rail that tracks # of devices turned on, with a limit to how many 66 | // can be on at the same time. Crude, but effective, especially when all devices 67 | // along the rail will use about the same amount of power anyways. 68 | class HelioSimpleRail : public HelioRail { 69 | public: 70 | HelioSimpleRail(Helio_RailType railType, 71 | hposi_t railIndex, 72 | int maxActiveAtOnce = 2, 73 | int classType = Simple); 74 | HelioSimpleRail(const HelioSimpleRailData *dataIn); 75 | 76 | virtual bool canActivate(HelioActuator *actuator) override; 77 | virtual float getCapacity(bool poll = false) override; 78 | 79 | virtual void setPowerUnits(Helio_UnitsType powerUnits) override; 80 | 81 | inline int getActiveCount() { return _activeCount; } 82 | 83 | protected: 84 | int _activeCount; // Current active count 85 | int _maxActiveAtOnce; // Max active count 86 | 87 | virtual void saveToData(HelioData *dataOut) override; 88 | 89 | void handleActivation(HelioActuator *actuator); 90 | friend class HelioRail; 91 | }; 92 | 93 | // Regulated Power Rail 94 | // Power rail that has a max power rating and power sensor that can track power 95 | // usage, with limit trigger for over-power state limiting actuator activation. 96 | class HelioRegulatedRail : public HelioRail, 97 | public HelioPowerUsageSensorAttachmentInterface, 98 | public HelioLimitTriggerAttachmentInterface { 99 | public: 100 | HelioRegulatedRail(Helio_RailType railType, 101 | hposi_t railIndex, 102 | float maxPower, 103 | int classType = Regulated); 104 | HelioRegulatedRail(const HelioRegulatedRailData *dataIn); 105 | 106 | virtual void update() override; 107 | virtual SharedPtr getSharedPtrFor(const HelioObjInterface *obj) const override; 108 | 109 | virtual bool canActivate(HelioActuator *actuator) override; 110 | virtual float getCapacity(bool poll = false) override; 111 | 112 | virtual void setPowerUnits(Helio_UnitsType powerUnits) override; 113 | 114 | virtual HelioSensorAttachment &getPowerUsageSensorAttachment() override; 115 | 116 | virtual HelioTriggerAttachment &getLimitTriggerAttachment() override; 117 | 118 | inline float getMaxPower() const { return _maxPower; } 119 | 120 | protected: 121 | float _maxPower; // Maximum power 122 | HelioSensorAttachment _powerUsage; // Power usage sensor attachment 123 | HelioTriggerAttachment _limitTrigger; // Power limit trigger attachment 124 | 125 | virtual void saveToData(HelioData *dataOut) override; 126 | 127 | void handleActivation(HelioActuator *actuator); 128 | friend class HelioRail; 129 | 130 | void handlePower(const HelioMeasurement *measurement); 131 | }; 132 | 133 | 134 | // Rail Serialization Data 135 | struct HelioRailData : public HelioObjectData 136 | { 137 | Helio_UnitsType powerUnits; // Power units 138 | 139 | HelioRailData(); 140 | virtual void toJSONObject(JsonObject &objectOut) const override; 141 | virtual void fromJSONObject(JsonObjectConst &objectIn) override; 142 | }; 143 | 144 | // Simple Rail Serialization Data 145 | struct HelioSimpleRailData : public HelioRailData 146 | { 147 | int maxActiveAtOnce; // Max active count 148 | 149 | HelioSimpleRailData(); 150 | virtual void toJSONObject(JsonObject &objectOut) const override; 151 | virtual void fromJSONObject(JsonObjectConst &objectIn) override; 152 | }; 153 | 154 | // Regulated Rail Serialization Data 155 | struct HelioRegulatedRailData : public HelioRailData 156 | { 157 | float maxPower; // Maximum power 158 | char powerUsageSensor[HELIO_NAME_MAXSIZE]; // Power usage sensor 159 | HelioTriggerSubData limitTrigger; // Power limit trigger 160 | 161 | HelioRegulatedRailData(); 162 | virtual void toJSONObject(JsonObject &objectOut) const override; 163 | virtual void fromJSONObject(JsonObjectConst &objectIn) override; 164 | }; 165 | 166 | #endif // /ifndef HelioRails_H 167 | -------------------------------------------------------------------------------- /src/HelioScheduler.h: -------------------------------------------------------------------------------- 1 | 2 | /* Helioduino: Simple automation controller for solar tracking systems. 3 | Copyright (C) 2023 NachtRaveVL 4 | Helioduino Scheduler 5 | */ 6 | 7 | #ifndef HelioScheduler_H 8 | #define HelioScheduler_H 9 | 10 | class HelioScheduler; 11 | struct HelioSchedulerSubData; 12 | struct HelioProcess; 13 | struct HelioTracking; 14 | 15 | #include "Helioduino.h" 16 | 17 | // Scheduler 18 | // The Scheduler acts as the system's main scheduling attendant, who looks through all 19 | // the various equipment and panels you have programmed in, and figures out the best 20 | // case tracking processes that should occur to support them. It is also responsible 21 | // for setting up and maintaining the drivers that get assigned to panels (such as the 22 | // various mechanical orientation devices in use), as well as determining when 23 | // significant time or event changes have occurred and broadcasting such out. 24 | class HelioScheduler { 25 | public: 26 | HelioScheduler(); 27 | ~HelioScheduler(); 28 | 29 | void update(); 30 | 31 | inline void setNeedsScheduling() { _needsScheduling = hasSchedulerData(); } 32 | inline bool needsScheduling() { return _needsScheduling; } 33 | inline bool inDaytimeMode() const { return _inDaytimeMode; } 34 | 35 | void setCleaningIntervalDays(unsigned int cleaningIntDays); 36 | void setPreDawnCleaningMins(unsigned int cleaningMins); 37 | void setPreDawnHeatingMins(unsigned int heatingMins); 38 | void setReportInterval(TimeSpan reportInterval); 39 | 40 | unsigned int getCleaningIntervalDays() const; 41 | unsigned int getPreDawnCleaningMins() const; 42 | unsigned int getPreDawnHeatingMins() const; 43 | TimeSpan getReportInterval() const; 44 | 45 | inline const Twilight &getDailyTwilight() const { return _dailyTwilight; } 46 | 47 | protected: 48 | Twilight _dailyTwilight; // Daily twilight settings 49 | bool _needsScheduling; // Needs rescheduling tracking flag 50 | bool _inDaytimeMode; // Daytime mode flag 51 | hposi_t _lastDay[3]; // Last day tracking for rescheduling (Y-2k,M,D) 52 | Map _trackings; // Panel tracking processes 53 | 54 | friend class Helioduino; 55 | friend struct HelioProcess; 56 | friend struct HelioTracking; 57 | 58 | inline HelioSchedulerSubData *schedulerData() const; 59 | inline bool hasSchedulerData() const; 60 | 61 | void updateDayTracking(); 62 | void performScheduling(); 63 | void broadcastDayChange(); 64 | }; 65 | 66 | // Scheduler Process Base 67 | // Processes are created and managed by Scheduler to manage the daily control 68 | // sequences necessary for solar panel alignment. 69 | struct HelioProcess { 70 | SharedPtr panel; // Panel 71 | 72 | Vector actuatorReqs; // Actuators required for this stage (keep-enabled list) 73 | 74 | time_t stageStart; // Stage start time 75 | 76 | HelioProcess(SharedPtr panel); 77 | 78 | void clearActuatorReqs(); 79 | void setActuatorReqs(const Vector &actuatorReqsIn); 80 | }; 81 | 82 | // Scheduler Tracking Process 83 | struct HelioTracking : public HelioProcess { 84 | enum : signed char {Init,Warm,Uncover,Clean,Track,Cover} stage; // Current tracking stage 85 | 86 | time_t canProcessAfter; // Time next processing can occur (unix/UTC), else 0/disabled 87 | time_t lastEnvReport; // Last time an environment report was generated (unix/UTC) 88 | bool stormingReported; // Flag for storming reported 89 | bool nightSeqReported; // Flag for night sequence reported 90 | bool coverSeqReported; // Flag for cover sequence reported 91 | 92 | HelioTracking(SharedPtr panel); 93 | ~HelioTracking(); 94 | 95 | void setupStaging(); 96 | void update(); 97 | 98 | private: 99 | void reset(); 100 | }; 101 | 102 | 103 | // Scheduler Serialization Sub Data 104 | // A part of HSYS system data. 105 | struct HelioSchedulerSubData : public HelioSubData { 106 | uint8_t cleaningIntervalDays; // Interval between panel cleanings, in days (default: 14) 107 | uint8_t preDawnCleaningMins; // Time to run panel cleaning sprayers/wipers (if present/needed) before daily tracking starts, in minutes (default: 1) 108 | uint8_t preDawnHeatingMins; // Duration to run panel heaters/de-icers (if present/needed) before daily tracking starts, in minutes (default: 30) 109 | time_t reportInterval; // Interval between environmental sensor reports, in seconds (default: 8hrs) 110 | 111 | HelioSchedulerSubData(); 112 | void toJSONObject(JsonObject &objectOut) const; 113 | void fromJSONObject(JsonObjectConst &objectIn); 114 | }; 115 | 116 | #endif // /ifndef HelioScheduler_H 117 | -------------------------------------------------------------------------------- /src/HelioStreams.h: -------------------------------------------------------------------------------- 1 | 2 | /* Helioduino: Simple automation controller for solar tracking systems. 3 | Copyright (C) 2023 NachtRaveVL 4 | Helioduino Streams 5 | */ 6 | 7 | #ifndef HelioStreams_H 8 | #define HelioStreams_H 9 | 10 | class HelioEEPROMStream; 11 | class HelioPROGMEMStream; 12 | 13 | #include "Helioduino.h" 14 | 15 | #ifdef ARDUINO_ARCH_SAM // Stream doesn't have availableForWrite 16 | #define HELIO_STREAM_AVAIL4WRT_OVERRIDE 17 | #else 18 | #define HELIO_STREAM_AVAIL4WRT_OVERRIDE override 19 | #endif 20 | 21 | // EEPROM Stream 22 | // Stream class for working with I2C_EEPROM data. 23 | class HelioEEPROMStream : public Stream { 24 | public: 25 | HelioEEPROMStream(); 26 | HelioEEPROMStream(uint16_t dataAddress, size_t dataSize); 27 | 28 | virtual int available() override; 29 | virtual int read() override; 30 | size_t readBytes(char *buffer, size_t length); 31 | virtual int peek() override; 32 | virtual void flush() override; 33 | virtual size_t write(const uint8_t *buffer, size_t size) override; 34 | virtual size_t write(uint8_t data) override; 35 | virtual int availableForWrite() HELIO_STREAM_AVAIL4WRT_OVERRIDE; 36 | 37 | protected: 38 | I2C_eeprom *_eeprom; 39 | uint16_t _readAddress, _writeAddress, _endAddress; 40 | }; 41 | 42 | 43 | // PROGMEM Stream 44 | // Stream class for working with PROGMEM data. 45 | class HelioPROGMEMStream : public Stream { 46 | public: 47 | HelioPROGMEMStream(); 48 | HelioPROGMEMStream(uintptr_t dataAddress); 49 | HelioPROGMEMStream(uintptr_t dataAddress, size_t dataSize); 50 | 51 | virtual int available() override; 52 | virtual int read() override; 53 | virtual int peek() override; 54 | virtual void flush() override; 55 | virtual size_t write(const uint8_t *buffer, size_t size) override; 56 | virtual size_t write(uint8_t data) override; 57 | 58 | protected: 59 | uintptr_t _readAddress, _writeAddress, _endAddress; 60 | }; 61 | 62 | #ifdef HELIO_USE_WIFI_STORAGE 63 | 64 | class HelioWiFiStorageFileStream : public Stream { 65 | public: 66 | HelioWiFiStorageFileStream(WiFiStorageFile file, uintptr_t seekPos = 0); 67 | virtual ~HelioWiFiStorageFileStream(); 68 | 69 | virtual int available() override; 70 | virtual int read() override; 71 | size_t readBytes(char *buffer, size_t length); 72 | virtual int peek() override; 73 | virtual void flush() override; 74 | virtual size_t write(const uint8_t *buffer, size_t size) override; 75 | virtual size_t write(uint8_t data) override; 76 | virtual int availableForWrite() HELIO_STREAM_AVAIL4WRT_OVERRIDE; 77 | 78 | protected: 79 | enum WiFiStorageFileDirection : signed char { ReadBuffer, WriteBuffer, None = -1 }; 80 | 81 | WiFiStorageFile _file; 82 | uint8_t _buffer[HELIO_WIFISTREAM_BUFFER_SIZE]; 83 | size_t _bufferOffset; 84 | uintptr_t _bufferFileOffset; 85 | WiFiStorageFileDirection _bufferDirection; 86 | uintptr_t _readOffset, _writeOffset, _endOffset; 87 | 88 | void prepareReadBuffer(); 89 | void prepareWriteBuffer(); 90 | }; 91 | 92 | #endif 93 | 94 | #endif // /ifndef HelioStreams_H 95 | -------------------------------------------------------------------------------- /src/Helioduino.hpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino System 4 | */ 5 | 6 | #include "Helioduino.h" 7 | 8 | inline bool Twilight::isDaytime(time_t unixTime) const { 9 | DateTime time = isUTC ? DateTime((uint32_t)unixTime) : localTime(unixTime); 10 | double hour = time.hour() + (time.minute() / 60.0) + (time.second() / 3600.0); 11 | return sunrise <= sunset ? hour >= sunrise && hour <= sunset 12 | : hour >= sunrise || hour <= sunset; 13 | } 14 | 15 | inline bool Twilight::isDaytime(DateTime localTime) const 16 | { 17 | DateTime time = isUTC ? DateTime((uint32_t)unixTime(localTime)) : localTime; 18 | double hour = time.hour() + (time.minute() / 60.0) + (time.second() / 3600.0); 19 | return sunrise <= sunset ? hour >= sunrise && hour <= sunset 20 | : hour >= sunrise || hour <= sunset; 21 | } 22 | 23 | inline time_t Twilight::hourToUnixTime(double hour, bool isUTC) 24 | { 25 | return isUTC ? unixDayStart() + (time_t)(hour * SECS_PER_HOUR) 26 | : unixTime(localDayStart() + TimeSpan(hour * SECS_PER_HOUR)); 27 | } 28 | 29 | inline DateTime Twilight::hourToLocalTime(double hour, bool isUTC) 30 | { 31 | return isUTC ? localTime(unixDayStart() + (time_t)(hour * SECS_PER_HOUR)) 32 | : localDayStart() + TimeSpan(hour * SECS_PER_HOUR); 33 | } 34 | 35 | 36 | #ifdef HELIO_USE_WIFI 37 | 38 | inline WiFiClass *Helioduino::getWiFi(bool begin) 39 | { 40 | return getWiFi(getWiFiSSID(), getWiFiPassword(), begin); 41 | } 42 | 43 | #endif 44 | #ifdef HELIO_USE_ETHERNET 45 | 46 | inline EthernetClass *Helioduino::getEthernet(bool begin) 47 | { 48 | return getEthernet(getMACAddress(), begin); 49 | } 50 | 51 | #endif 52 | 53 | 54 | inline HelioLoggerSubData *HelioLogger::loggerData() const 55 | { 56 | return &Helioduino::_activeInstance->_systemData->logger; 57 | } 58 | 59 | inline bool HelioLogger::hasLoggerData() const 60 | { 61 | return Helioduino::_activeInstance && Helioduino::_activeInstance->_systemData; 62 | } 63 | 64 | inline bool HelioLogger::isLoggingToSDCard() const 65 | { 66 | return hasLoggerData() && loggerData()->logLevel != Helio_LogLevel_None && loggerData()->logToSDCard; 67 | } 68 | 69 | #ifdef HELIO_USE_WIFI_STORAGE 70 | 71 | inline bool HelioLogger::isLoggingToWiFiStorage() const 72 | { 73 | return hasLoggerData() && loggerData()->logLevel != Helio_LogLevel_None && loggerData()->logToWiFiStorage; 74 | } 75 | 76 | #endif 77 | 78 | inline void HelioLogger::logActivation(const HelioActuator *actuator) 79 | { 80 | if (actuator) { logMessage(actuator->getId().getDisplayString(), SFP(HStr_Log_HasEnabled)); } 81 | } 82 | 83 | inline void HelioLogger::logDeactivation(const HelioActuator *actuator) 84 | { 85 | if (actuator) { logMessage(actuator->getId().getDisplayString(), SFP(HStr_Log_HasDisabled)); } 86 | } 87 | 88 | inline void HelioLogger::logProcess(const HelioObjInterface *obj, const String &processString, const String &statusString) 89 | { 90 | if (obj) { logMessage(obj->getId().getDisplayString(), processString, statusString); } 91 | } 92 | 93 | inline void HelioLogger::logStatus(const HelioObjInterface *obj, const String &statusString) 94 | { 95 | if (obj) { logMessage(obj->getId().getDisplayString(), statusString); } 96 | } 97 | 98 | inline Helio_LogLevel HelioLogger::getLogLevel() const 99 | { 100 | return hasLoggerData() ? loggerData()->logLevel : Helio_LogLevel_None; 101 | } 102 | 103 | inline bool HelioLogger::isLoggingEnabled() const 104 | { 105 | return hasLoggerData() && loggerData()->logLevel != Helio_LogLevel_None && (loggerData()->logToSDCard || loggerData()->logToWiFiStorage); 106 | } 107 | 108 | 109 | inline HelioPublisherSubData *HelioPublisher::publisherData() const 110 | { 111 | return &Helioduino::_activeInstance->_systemData->publisher; 112 | } 113 | 114 | inline bool HelioPublisher::hasPublisherData() const 115 | { 116 | return Helioduino::_activeInstance && Helioduino::_activeInstance->_systemData; 117 | } 118 | 119 | inline bool HelioPublisher::isPublishingToSDCard() const 120 | { 121 | return hasPublisherData() && publisherData()->pubToSDCard; 122 | } 123 | 124 | #ifdef HELIO_USE_WIFI_STORAGE 125 | 126 | inline bool HelioPublisher::isPublishingToWiFiStorage() const 127 | { 128 | return hasPublisherData() && publisherData()->pubToWiFiStorage; 129 | } 130 | 131 | #endif 132 | #ifdef HELIO_USE_MQTT 133 | 134 | inline bool HelioPublisher::isPublishingToMQTTClient() const 135 | { 136 | return hasPublisherData() && _mqttClient; 137 | } 138 | 139 | #endif 140 | 141 | inline bool HelioPublisher::isPublishingEnabled() const 142 | { 143 | return hasPublisherData() && (publisherData()->pubToSDCard || publisherData()->pubToWiFiStorage 144 | #ifdef HELIO_USE_MQTT 145 | || _mqttClient 146 | #endif 147 | ); 148 | } 149 | 150 | inline void HelioPublisher::setNeedsTabulation() 151 | { 152 | _needsTabulation = hasPublisherData(); 153 | } 154 | 155 | 156 | inline HelioSchedulerSubData *HelioScheduler::schedulerData() const 157 | { 158 | return &Helioduino::_activeInstance->_systemData->scheduler; 159 | } 160 | 161 | inline bool HelioScheduler::hasSchedulerData() const 162 | { 163 | return Helioduino::_activeInstance && Helioduino::_activeInstance->_systemData; 164 | } 165 | -------------------------------------------------------------------------------- /src/full/HelioduinoUI.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Full/RW UI 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioUI_H 9 | #define HelioUI_H 10 | 11 | class HelioduinoFullUI; 12 | typedef HelioduinoFullUI HelioduinoUI; 13 | 14 | #include "../shared/HelioduinoUI.h" 15 | 16 | class HelioduinoFullUI : public HelioduinoBaseUI { 17 | public: 18 | HelioduinoFullUI(String deviceUUID, // Device UUID hex string for remote controllability 19 | UIControlSetup uiControlSetup = UIControlSetup(), // UI control input setup, from controller initialization 20 | UIDisplaySetup uiDisplaySetup = UIDisplaySetup(), // UI display output setup, from controller initialization 21 | bool isActiveLowIO = true, // Signaling logic level usage for I/O control/display devices 22 | bool allowInterruptableIO = true, // Allows interruptable pins to interrupt, else forces polling 23 | bool enableTcUnicodeFonts = false, // Enables tcUnicode fonts usage instead of gfx-lib specific fonts 24 | bool enableBufferedVRAM = false); // Enables sprite-sized buffered video RAM for smooth animations 25 | virtual ~HelioduinoFullUI(); 26 | 27 | void addRemote(Helio_RemoteControl rcType, // Type of remote control 28 | UARTDeviceSetup rcSetup = UARTDeviceSetup(), // Remote control serial setup (if serial based), else ignored 29 | uint16_t rcServerPort = HELIO_UI_REMOTESERVER_PORT); // Remote control server listening port (if networking based), else ignored 30 | 31 | virtual bool isFullUI() override; 32 | 33 | protected: 34 | }; 35 | 36 | #endif // /ifndef HelioUI_H 37 | #endif 38 | -------------------------------------------------------------------------------- /src/min/HelioduinoUI.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Minimal/RO UI 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioUI_H 9 | #define HelioUI_H 10 | 11 | class HelioduinoMinUI; 12 | typedef HelioduinoMinUI HelioduinoUI; 13 | 14 | #include "../shared/HelioduinoUI.h" 15 | 16 | class HelioduinoMinUI : public HelioduinoBaseUI { 17 | public: 18 | HelioduinoMinUI(String deviceUUID, // Device UUID hex string for remote controllability 19 | UIControlSetup uiControlSetup = UIControlSetup(), // UI control input setup, from controller initialization 20 | UIDisplaySetup uiDisplaySetup = UIDisplaySetup(), // UI display output setup, from controller initialization 21 | bool isActiveLowIO = true, // Signaling logic level usage for I/O control/display devices 22 | bool allowInterruptableIO = true, // Allows interruptable pins to interrupt, else forces polling 23 | bool enableTcUnicodeFonts = false, // Enables tcUnicode fonts usage instead of gfx-lib specific fonts 24 | bool enableBufferedVRAM = false); // Enables sprite-sized buffered video RAM for smooth animations 25 | virtual ~HelioduinoMinUI(); 26 | 27 | void allocateStandardControls(); // Allocates/pulls-into-build any standard tcMenu controls, from encoders to matrices 28 | void allocateESP32TouchControl(); // Allocates/pulls-into-build an ESP32 Touch key control (only for ESP32) 29 | void allocateResistiveTouchControl(); // Allocates/pulls-into-build a resistive touchscreen control, must be called after display allocation 30 | void allocateTouchscreenControl(); // Allocates/pulls-into-build a Touchscreen control (using FT6206/XPT2046), must be called after display allocation 31 | void allocateTFTTouchControl(); // Allocates/pulls-into-build a TFTTouch control (using TFT_eSPI), must be called after TFT display allocation 32 | 33 | void allocateLCDDisplay(); // Allocates/pulls-into-build a LCD display (using LiquidCrystalIO) 34 | 35 | void allocateSSD1305Display(); // Allocates/pulls-into-build a SSD1305 OLED pixel display (using U8g2) 36 | void allocateSSD1305x32AdaDisplay(); // Allocates/pulls-into-build a SSD1305 (ADAFRUIT_128X32) OLED pixel display (using U8g2) 37 | void allocateSSD1305x64AdaDisplay(); // Allocates/pulls-into-build a SSD1305 (ADAFRUIT_128x64) OLED pixel display (using U8g2) 38 | void allocateSSD1306Display(); // Allocates/pulls-into-build a SSD1306 OLED pixel display (using U8g2) 39 | void allocateSH1106Display(); // Allocates/pulls-into-build a SH1106 OLED pixel display (using U8g2) 40 | void allocateCustomOLEDDisplay(); // Allocates/pulls-into-build a custom OLED pixel display as statically defined (using U8g2) 41 | void allocateSSD1607Display(); // Allocates/pulls-into-build a SSD1607 OLED pixel display (using U8g2) 42 | void allocateIL3820Display(); // Allocates/pulls-into-build an IL3820 OLED pixel display (using U8g2) 43 | void allocateIL3820V2Display(); // Allocates/pulls-into-build an IL3820 V2 OLED pixel display (using U8g2) 44 | 45 | void allocateST7735Display(); // Allocates/pulls-into-build a ST7735 color pixel display (using AdafruitGFX) 46 | void allocateST7789Display(); // Allocates/pulls-into-build a ST7789 color pixel display (using AdafruitGFX) 47 | void allocateILI9341Display(); // Allocates/pulls-into-build an ILI9341 pixel display (using AdafruitGFX) 48 | void allocateTFTDisplay(); // Allocates/pulls-into-build a TFT_eSPI color pixel display (using TFT_eSPI) 49 | 50 | void addSerialRemote(UARTDeviceSetup rcSetup = UARTDeviceSetup()); // Adds/pulls-into-build a remote control by Serial or Bluetooth AT 51 | void addSimhubRemote(UARTDeviceSetup rcSetup = UARTDeviceSetup()); // Adds/pulls-into-build a remote control by Simhub serial connector, requires UART setup 52 | void addWiFiRemote(uint16_t rcServerPort = HELIO_UI_REMOTESERVER_PORT); // Adds/pulls-into-build a remote control by WiFi, requires enabled WiFi 53 | void addEthernetRemote(uint16_t rcServerPort = HELIO_UI_REMOTESERVER_PORT); // Adds/pulls-into-build a remote control by Ethernet, requires enabled Ethernet 54 | 55 | virtual bool isFullUI() override; 56 | 57 | protected: 58 | }; 59 | 60 | #endif // /ifndef HelioUI_H 61 | #endif 62 | -------------------------------------------------------------------------------- /src/shared/HelioMenus.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Menu Screens 4 | */ 5 | 6 | #include "HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/shared/HelioMenus.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Menu Screens 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenus_H 9 | #define HelioMenus_H 10 | 11 | class HelioMenu; 12 | 13 | #include "HelioduinoUI.h" 14 | #include "RemoteMenuItem.h" 15 | #include "EditableLargeNumberMenuItem.h" 16 | 17 | // Menu Screen Base 18 | class HelioMenu 19 | { 20 | public: 21 | inline HelioMenu() : _loaded(false) { ; } 22 | virtual ~HelioMenu() = default; 23 | 24 | virtual void loadMenu(MenuItem *addFrom = nullptr) = 0; // should call menuMgr.addMenuAfter() 25 | virtual MenuItem *getRootItem() = 0; 26 | 27 | inline bool isLoaded() const { return _loaded; } 28 | 29 | protected: 30 | bool _loaded; 31 | }; 32 | 33 | // Initializes an AnyMenuInfo structure 34 | #define InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback)\ 35 | safeProgCpy(varName.name, CFP(strNum), NAME_SIZE_T);\ 36 | varName.id = itemId;\ 37 | varName.eepromAddr = eepromPosition;\ 38 | varName.maxValue = valMaximum;\ 39 | varName.callback = fnCallback 40 | 41 | // Initializes a BooleanMenuInfo structure 42 | #define InitBooleanMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback,boolNaming)\ 43 | InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback);\ 44 | varName.naming = boolNaming 45 | 46 | // Initializes a SubMenuInfo structure 47 | #define InitSubMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback)\ 48 | InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback) 49 | 50 | // Initializes an EnumMenuInfo structure 51 | #define InitEnumMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback,enumItems)\ 52 | InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback);\ 53 | varName.menuItems = enumItems 54 | 55 | // Initializes an AnalogMenuInfo structure, with units from CFP() 56 | #define InitAnalogMenuInfoUnits(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback,valOffset,valDivisor,unitsStrNum)\ 57 | InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback);\ 58 | varName.offset = valOffset;\ 59 | varName.divisor = valDivisor;\ 60 | safeProgCpy(varName.unitName, CFP(unitsStrNum), UNIT_SIZE_T) 61 | 62 | // Initializes an AnalogMenuInfo structure, with blank units 63 | #define InitAnalogMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback,valOffset,valDivisor)\ 64 | InitAnyMenuInfo(varName,strNum,itemId,eepromPosition,valMaximum,fnCallback);\ 65 | varName.offset = valOffset;\ 66 | varName.divisor = valDivisor;\ 67 | varName.unitName[0] = '\000' 68 | 69 | // Altered rendering callback that uses CFP() 70 | #define H_RENDERING_CALLBACK_NAME_INVOKE(fnName, parent, strNum, eepromPosition, invoke) \ 71 | int fnName(RuntimeMenuItem* item, uint8_t row, RenderFnMode mode, char* buffer, int buffSize) { \ 72 | switch(mode) { \ 73 | case RENDERFN_NAME: \ 74 | safeProgCpy(buffer, CFP(strNum), buffSize); \ 75 | return true; \ 76 | case RENDERFN_INVOKE: \ 77 | invokeIfSafe(invoke, item); \ 78 | return true; \ 79 | case RENDERFN_EEPROM_POS: \ 80 | return eepromPosition; \ 81 | default: \ 82 | return parent(item, row, mode, buffer, buffSize); \ 83 | } \ 84 | } 85 | 86 | #ifdef HELIO_DISABLE_BUILTIN_DATA 87 | #define InfoPtrForItem(itemName,castType) (&init.minfo##itemName) 88 | #define InfoLocation INFO_LOCATION_RAM 89 | #else 90 | #define InfoPtrForItem(itemName,castType) ((const castType *)CFP(HUIStr_Item_##itemName)) 91 | #define InfoLocation INFO_LOCATION_PGM 92 | #endif 93 | 94 | #include "screens/HelioMenuHome.h" 95 | #include "screens/HelioMenuAlerts.h" 96 | #include "screens/HelioMenuActuators.h" 97 | #include "screens/HelioMenuSensors.h" 98 | #include "screens/HelioMenuPanels.h" 99 | #include "screens/HelioMenuPowerRails.h" 100 | #include "screens/HelioMenuScheduling.h" 101 | #include "screens/HelioMenuSettings.h" 102 | #include "screens/HelioMenuCalibrations.h" 103 | #include "screens/HelioMenuInformation.h" 104 | 105 | #endif // /ifndef HelioMenus_H 106 | #endif 107 | -------------------------------------------------------------------------------- /src/shared/HelioOverviews.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Overview Screens 4 | */ 5 | 6 | #include "HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/shared/HelioOverviews.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Overview Screens 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioOverviews_H 9 | #define HelioOverviews_H 10 | 11 | class HelioOverview; 12 | class HelioOverviewLCD; 13 | class HelioOverviewOLED; 14 | template class HelioOverviewGFX; 15 | class HelioOverviewTFT; 16 | 17 | #include "HelioduinoUI.h" 18 | 19 | // Overview Screen Base 20 | // Overview screen class that manages the default at-a-glance system overview. 21 | // Meant to be able to be deleted on a moments notice to transition back into menu. 22 | class HelioOverview { 23 | public: 24 | inline HelioOverview(HelioDisplayDriver *display) : _display(display), _needsFullRedraw(true) { ; } 25 | virtual ~HelioOverview() = default; 26 | 27 | // Renders overview screen given current display orientation. 28 | virtual void renderOverview(bool isLandscape, Pair screenSize) = 0; 29 | 30 | inline void setNeedsFullRedraw() { _needsFullRedraw = true; } 31 | 32 | protected: 33 | HelioDisplayDriver *_display; // Display (strong) 34 | bool _needsFullRedraw; // Needs full redraw flag 35 | }; 36 | 37 | #include "screens/HelioOverviewGFX.h" 38 | #include "screens/HelioOverviewLCD.h" 39 | #include "screens/HelioOverviewOLED.h" 40 | #include "screens/HelioOverviewTFT.h" 41 | 42 | #endif // /ifndef HelioOverviews_H 43 | #endif 44 | -------------------------------------------------------------------------------- /src/shared/HelioOverviews.hpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Overview Screens 4 | */ 5 | 6 | #include "HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | #include "screens/HelioOverviewGFX.hpp" 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/HelioRemoteControls.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Remote Controls 4 | */ 5 | 6 | #include "HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | HelioRemoteSerialControl::HelioRemoteSerialControl(UARTDeviceSetup serialSetup) 10 | : _serialTransport(serialSetup.serial), _serialInitializer(), _serialConnection(_serialTransport, _serialInitializer) 11 | { ; } 12 | 13 | BaseRemoteServerConnection *HelioRemoteSerialControl::getConnection() 14 | { 15 | return &_serialConnection; 16 | } 17 | 18 | 19 | HelioRemoteSimhubControl::HelioRemoteSimhubControl(UARTDeviceSetup serialSetup, menuid_t statusMenuId) 20 | : _simhubConnection(serialSetup.serial, statusMenuId) 21 | { ; } 22 | 23 | BaseRemoteServerConnection *HelioRemoteSimhubControl::getConnection() 24 | { 25 | return &_simhubConnection; 26 | } 27 | 28 | 29 | #ifdef HELIO_USE_WIFI 30 | 31 | HelioRemoteWiFiControl::HelioRemoteWiFiControl(uint16_t listeningPort) 32 | : _rcServer(listeningPort), _netInitialisation(&_rcServer), _netTransport(), _netConnection(_netTransport, _netInitialisation) 33 | { ; } 34 | 35 | BaseRemoteServerConnection *HelioRemoteWiFiControl::getConnection() 36 | { 37 | return &_netConnection; 38 | } 39 | 40 | #endif // /ifdef HELIO_USE_WIFI 41 | 42 | 43 | #ifdef HELIO_USE_ETHERNET 44 | 45 | HelioRemoteEthernetControl::HelioRemoteEthernetControl(uint16_t listeningPort) 46 | : _rcServer(listeningPort), _netInitialisation(&_rcServer), _netTransport(), _netConnection(_netTransport, _netInitialisation) 47 | { ; } 48 | 49 | BaseRemoteServerConnection *HelioRemoteEthernetControl::getConnection() 50 | { 51 | return &_netConnection; 52 | } 53 | 54 | #endif // /ifdef HELIO_USE_ETHERNET 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/shared/HelioRemoteControls.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Remote Controls 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioRemoteControls_H 9 | #define HelioRemoteControls_H 10 | 11 | class HelioRemoteControl; 12 | class HelioRemoteSerialControl; 13 | class HelioRemoteSimhubControl; 14 | #ifdef HELIO_USE_WIFI 15 | class HelioRemoteWiFiControl; 16 | #endif 17 | #ifdef HELIO_USE_ETHERNET 18 | class HelioRemoteEthernetControl; 19 | #endif 20 | 21 | #include "HelioduinoUI.h" 22 | 23 | // Remote Control Base 24 | // Base remote control class. 25 | class HelioRemoteControl { 26 | public: 27 | virtual ~HelioRemoteControl() = default; 28 | 29 | // Connection accessor 30 | virtual BaseRemoteServerConnection *getConnection() = 0; 31 | }; 32 | 33 | 34 | // Serial UART Remote Control 35 | // Manages remote control over serial UART. 36 | class HelioRemoteSerialControl : public HelioRemoteControl { 37 | public: 38 | HelioRemoteSerialControl(UARTDeviceSetup serialSetup); 39 | virtual ~HelioRemoteSerialControl() = default; 40 | 41 | virtual BaseRemoteServerConnection *getConnection() override; 42 | 43 | protected: 44 | SerialTagValueTransport _serialTransport; 45 | NoInitialisationNeeded _serialInitializer; 46 | TagValueRemoteServerConnection _serialConnection; 47 | }; 48 | 49 | 50 | // Simhub Connector Remote Control 51 | // Manages remote control over simhub connector. 52 | class HelioRemoteSimhubControl : public HelioRemoteControl { 53 | public: 54 | HelioRemoteSimhubControl(UARTDeviceSetup serialSetup, menuid_t statusMenuId); 55 | virtual ~HelioRemoteSimhubControl() = default; 56 | 57 | virtual BaseRemoteServerConnection *getConnection() override; 58 | 59 | protected: 60 | SimHubRemoteConnection _simhubConnection; 61 | }; 62 | 63 | 64 | #ifdef HELIO_USE_WIFI 65 | // WiFi Remote Control 66 | // Manages remote control over a WiFi connection. 67 | class HelioRemoteWiFiControl : public HelioRemoteControl { 68 | public: 69 | HelioRemoteWiFiControl(uint16_t listeningPort = HELIO_UI_REMOTESERVER_PORT); 70 | virtual ~HelioRemoteWiFiControl() = default; 71 | 72 | virtual BaseRemoteServerConnection *getConnection() override; 73 | 74 | inline WiFiServer &getRCServer() { return _rcServer; } 75 | 76 | protected: 77 | WiFiServer _rcServer; 78 | WiFiInitialisation _netInitialisation; 79 | WiFiTagValTransport _netTransport; 80 | TagValueRemoteServerConnection _netConnection; 81 | }; 82 | #endif 83 | 84 | 85 | #ifdef HELIO_USE_ETHERNET 86 | // Ethernet Remote Control 87 | // Manages remote control over an Ethernet connection. 88 | class HelioRemoteEthernetControl : public HelioRemoteControl { 89 | public: 90 | HelioRemoteEthernetControl(uint16_t listeningPort = HELIO_UI_REMOTESERVER_PORT); 91 | virtual ~HelioRemoteEthernetControl() = default; 92 | 93 | virtual BaseRemoteServerConnection *getConnection() override; 94 | 95 | inline EthernetServer &getRCServer() { return _rcServer; } 96 | 97 | protected: 98 | EthernetServer _rcServer; 99 | EthernetInitialisation _netInitialisation; 100 | EthernetTagValTransport _netTransport; 101 | TagValueRemoteServerConnection _netConnection; 102 | }; 103 | #endif 104 | 105 | #endif // /ifndef HelioRemoteControls_H 106 | #endif 107 | -------------------------------------------------------------------------------- /src/shared/HelioUIData.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino UI Data 4 | */ 5 | 6 | #include 7 | #include "HelioUIData.h" 8 | 9 | HelioUIData::HelioUIData() 10 | : HelioData('H','U','I','D', 1), 11 | updatesPerSec(HELIO_UI_UPDATE_SPEED), 12 | displayTheme(Helio_DisplayTheme_Undefined), 13 | titleMode(Helio_TitleMode_Undefined), 14 | analogSlider(false), editingIcons(false), 15 | joystickCalib{0.5f,0.5f,0.05f}, touchscreenCalib{0} 16 | { 17 | _size = sizeof(*this); 18 | } 19 | 20 | void HelioUIData::toJSONObject(JsonObject &objectOut) const 21 | { 22 | HelioData::toJSONObject(objectOut); 23 | 24 | if (updatesPerSec != HELIO_UI_UPDATE_SPEED) { objectOut[SFP(HStr_Key_UpdatesPerSec)] = updatesPerSec; } 25 | if (displayTheme != Helio_DisplayTheme_Undefined) { objectOut[SFP(HStr_Key_DisplayTheme)] = displayTheme; } 26 | if (!isFPEqual(joystickCalib[0], 0.5f) || !isFPEqual(joystickCalib[1], 0.5f) || !isFPEqual(joystickCalib[2], 0.05f)) { objectOut[SFP(HStr_Key_JoystickCalib)] = commaStringFromArray(joystickCalib, 3); } 27 | } 28 | 29 | void HelioUIData::fromJSONObject(JsonObjectConst &objectIn) 30 | { 31 | HelioData::fromJSONObject(objectIn); 32 | 33 | updatesPerSec = objectIn[SFP(HStr_Key_UpdatesPerSec)] | updatesPerSec; 34 | displayTheme = objectIn[SFP(HStr_Key_DisplayTheme)] | displayTheme; 35 | JsonVariantConst joystickCalibVar = objectIn[SFP(HStr_Key_JoystickCalib)]; 36 | commaStringToArray(joystickCalibVar, joystickCalib, 3); 37 | } 38 | -------------------------------------------------------------------------------- /src/shared/HelioUIData.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino UI Data 4 | */ 5 | 6 | #ifndef HelioUIData_H 7 | #define HelioUIData_H 8 | 9 | struct HelioUIData; 10 | 11 | #include 12 | #include "HelioUIDefines.h" 13 | 14 | // UI Serialization Data 15 | // id: HUID. Helioduino UI data. 16 | struct HelioUIData : public HelioData { 17 | uint8_t updatesPerSec; // Updates per second (1-10, default: HELIO_UI_UPDATE_SPEED) 18 | Helio_DisplayTheme displayTheme; // Display theme (if supported) 19 | Helio_TitleMode titleMode; // Title mode 20 | bool analogSlider; // Use analog slider 21 | bool editingIcons; // Use editing icons 22 | float joystickCalib[3]; // Joystick calibration ({midX,midY,zeroTol}, default: {0.5,0.5,0.05}) 23 | uint16_t touchscreenCalib[4]; // Touchscreen calibration ({x0,y0,x1,y1}), default: {0,0,0,0}) 24 | 25 | HelioUIData(); 26 | virtual void toJSONObject(JsonObject &objectOut) const override; 27 | virtual void fromJSONObject(JsonObjectConst &objectIn) override; 28 | }; 29 | 30 | #endif // /ifndef HelioUIData_H 31 | -------------------------------------------------------------------------------- /src/shared/HelioUIStrings.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino UI Strings/Prototypes 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioUIStrings_H 9 | #define HelioUIStrings_H 10 | 11 | // UI Strings Enumeration Table 12 | enum HelioUI_String : unsigned short { 13 | HUIStr_Keys_MatrixActions, 14 | 15 | HUIStr_Item_Actuators, 16 | HUIStr_Item_AddNew, 17 | HUIStr_Item_Alerts, 18 | HUIStr_Item_AllowRemoteCtrl, 19 | HUIStr_Item_Altitude, 20 | HUIStr_Item_AssignByDHCP, 21 | HUIStr_Item_AssignByHostname, 22 | HUIStr_Item_AutosavePrimary, 23 | HUIStr_Item_AutosaveSecondary, 24 | HUIStr_Item_BackToOverview, 25 | HUIStr_Item_BatteryFailure, 26 | HUIStr_Item_Board, 27 | HUIStr_Item_BrokerPort, 28 | HUIStr_Item_Browse, 29 | HUIStr_Item_Calibrations, 30 | HUIStr_Item_ControlMode, 31 | HUIStr_Item_ControllerIP, 32 | HUIStr_Item_Controls, 33 | HUIStr_Item_DSTAddHour, 34 | HUIStr_Item_DataPolling, 35 | HUIStr_Item_Date, 36 | HUIStr_Item_Debug, 37 | HUIStr_Item_DisplayMode, 38 | HUIStr_Item_EEPROM, 39 | HUIStr_Item_Firmware, 40 | HUIStr_Item_FreeMemory, 41 | HUIStr_Item_GPSPolling, 42 | HUIStr_Item_General, 43 | HUIStr_Item_Information, 44 | HUIStr_Item_JoystickXMid, 45 | HUIStr_Item_JoystickXTol, 46 | HUIStr_Item_JoystickYMid, 47 | HUIStr_Item_JoystickYTol, 48 | HUIStr_Item_LatDegrees, 49 | HUIStr_Item_Library, 50 | HUIStr_Item_LocalTime, 51 | HUIStr_Item_Location, 52 | HUIStr_Item_LongMinutes, 53 | HUIStr_Item_MACAddr0x, 54 | HUIStr_Item_MQTTBroker, 55 | HUIStr_Item_Measurements, 56 | HUIStr_Item_Name, 57 | HUIStr_Item_Networking, 58 | HUIStr_Item_Panels, 59 | HUIStr_Item_PowerRails, 60 | HUIStr_Item_RTC, 61 | HUIStr_Item_RemoteCtrlPort, 62 | HUIStr_Item_SDCard, 63 | HUIStr_Item_Scheduling, 64 | HUIStr_Item_Sensors, 65 | HUIStr_Item_Settings, 66 | HUIStr_Item_Size, 67 | HUIStr_Item_System, 68 | HUIStr_Item_SystemMode, 69 | HUIStr_Item_SystemName, 70 | HUIStr_Item_Time, 71 | HUIStr_Item_TimeZone, 72 | HUIStr_Item_ToggleBadConn, 73 | HUIStr_Item_ToggleFastTime, 74 | HUIStr_Item_TriggerAutosave, 75 | HUIStr_Item_TriggerLowMem, 76 | HUIStr_Item_TriggerSDCleanup, 77 | HUIStr_Item_TriggerSigTime, 78 | HUIStr_Item_Uptime, 79 | HUIStr_Item_WiFiPass, 80 | HUIStr_Item_WiFiSSID, 81 | 82 | HUIStr_Enum_Autosave, 83 | HUIStr_Enum_DataPolling, 84 | HUIStr_Enum_GPSPolling, 85 | HUIStr_Enum_Measurements, 86 | HUIStr_Enum_SystemMode, 87 | HUIStr_Enum_TimeZone, 88 | 89 | HUIStr_Unit_MSL, 90 | HUIStr_Unit_Percent, 91 | 92 | HUIStr_Count 93 | }; 94 | 95 | // Returns memory resident string from PROGMEM (Flash) UI string enumeration. 96 | extern String stringFromPGM(HelioUI_String strNum); 97 | 98 | // Makes UI Strings lookup go through EEPROM, with specified data begin address. 99 | extern void beginUIStringsFromEEPROM(uint16_t uiDataAddress); 100 | 101 | // Makes UI Strings lookup go through SD card strings file at file prefix. 102 | extern void beginUIStringsFromSDCard(String uiDataFilePrefix); 103 | 104 | #ifndef HELIO_DISABLE_BUILTIN_DATA 105 | // Returns PROGMEM (Flash) address pointer given UI string number. 106 | const char *pgmAddrForStr(HelioUI_String strNum); 107 | #endif 108 | 109 | // Returns the pitch byte size for entries in a compressed enum list by parsing the initial item. 110 | extern size_t enumListPitch(const char *enumData); 111 | inline size_t enumListPitch(HelioUI_String strNum) { return enumListPitch(CFP(strNum)); } 112 | 113 | #endif // /ifndef HelioUIStrings_H 114 | #endif 115 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuActuators.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Actuators Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuActuators.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Actuators Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuActuators_H 9 | #define HelioMenuActuators_H 10 | 11 | class HelioActuatorsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioActuatorsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuActuators_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuAlerts.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Alerts Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuAlerts.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Alerts Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuAlerts_H 9 | #define HelioMenuAlerts_H 10 | 11 | class HelioAlertsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioAlertsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuAlerts_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuCalibrations.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Calibrations Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuCalibrations.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Calibrations Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuCalibrations_H 9 | #define HelioMenuCalibrations_H 10 | 11 | class HelioCalibrationsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioCalibrationsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuCalibrations_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuHome.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Home Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuHome_H 9 | #define HelioMenuHome_H 10 | 11 | class HelioHomeMenu; 12 | #ifdef HELIO_DISABLE_BUILTIN_DATA 13 | struct HelioHomeMenuInfo; 14 | #endif 15 | struct HelioHomeMenuItems; 16 | 17 | #include "../HelioduinoUI.h" 18 | 19 | class HelioHomeMenu : public HelioMenu 20 | { 21 | public: 22 | HelioHomeMenu(); 23 | virtual ~HelioHomeMenu(); 24 | 25 | virtual void loadMenu(MenuItem *addFrom = nullptr) override; 26 | virtual MenuItem *getRootItem() override; 27 | 28 | inline HelioHomeMenuItems &getItems() { return *_items; } 29 | 30 | protected: 31 | HelioHomeMenuItems *_items; 32 | }; 33 | 34 | #ifdef HELIO_DISABLE_BUILTIN_DATA 35 | struct HelioHomeMenuInfo { 36 | HelioHomeMenuInfo(); 37 | 38 | AnyMenuInfo minfoBackToOverview; 39 | #ifdef HELIO_UI_ENABLE_DEBUG_MENU 40 | BooleanMenuInfo minfoToggleBadConn; 41 | BooleanMenuInfo minfoToggleFastTime; 42 | AnyMenuInfo minfoTriggerSigTime; 43 | AnyMenuInfo minfoTriggerSDCleanup; 44 | AnyMenuInfo minfoTriggerLowMem; 45 | AnyMenuInfo minfoTriggerAutosave; 46 | SubMenuInfo minfoDebug; 47 | #endif // /ifdef HELIO_UI_ENABLE_DEBUG_MENU 48 | AnyMenuInfo minfoInformation; 49 | AnyMenuInfo minfoCalibrations; 50 | SubMenuInfo minfoLibrary; 51 | AnyMenuInfo minfoSettings; 52 | AnyMenuInfo minfoScheduling; 53 | AnyMenuInfo minfoPowerRails; 54 | AnyMenuInfo minfoPanels; 55 | AnyMenuInfo minfoSensors; 56 | AnyMenuInfo minfoActuators; 57 | SubMenuInfo minfoSystem; 58 | AnyMenuInfo minfoAlerts; 59 | }; 60 | #endif // /ifdef HELIO_DISABLE_BUILTIN_DATA 61 | 62 | struct HelioHomeMenuItems { 63 | HelioHomeMenuItems(); 64 | 65 | #ifdef HELIO_DISABLE_BUILTIN_DATA 66 | HelioHomeMenuInfo init; 67 | #endif 68 | 69 | ActionMenuItem menuBackToOverview; 70 | #ifdef HELIO_UI_ENABLE_DEBUG_MENU 71 | BooleanMenuItem menuToggleBadConn; 72 | BooleanMenuItem menuToggleFastTime; 73 | ActionMenuItem menuTriggerSigTime; 74 | ActionMenuItem menuTriggerSDCleanup; 75 | ActionMenuItem menuTriggerLowMem; 76 | ActionMenuItem menuTriggerAutosave; 77 | BackMenuItem menuBackDebug; 78 | SubMenuItem menuDebug; 79 | #endif // /ifdef HELIO_UI_ENABLE_DEBUG_MENU 80 | ActionMenuItem menuInformation; 81 | ActionMenuItem menuCalibrations; 82 | BackMenuItem menuBackLibrary; 83 | SubMenuItem menuLibrary; 84 | ActionMenuItem menuSettings; 85 | ActionMenuItem menuScheduling; 86 | ActionMenuItem menuPowerRails; 87 | ActionMenuItem menuPanels; 88 | ActionMenuItem menuSensors; 89 | ActionMenuItem menuActuators; 90 | BackMenuItem menuBackSystem; 91 | SubMenuItem menuSystem; 92 | ActionMenuItem menuAlerts; 93 | }; 94 | 95 | #endif // /ifndef HelioMenuHome_H 96 | #endif 97 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuInformation.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Information Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuInformation.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Information Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuInformation_H 9 | #define HelioMenuInformation_H 10 | 11 | class HelioInformationMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioInformationMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuInformation_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuPanels.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Panels Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuPanels.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Panels Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuPanels_H 9 | #define HelioMenuPanels_H 10 | 11 | class HelioPanelsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioPanelsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuPanels_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuPowerRails.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino PowerRails Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuPowerRails.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino PowerRails Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuPowerRails_H 9 | #define HelioMenuPowerRails_H 10 | 11 | class HelioPowerRailsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioPowerRailsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuPowerRails_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuScheduling.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Scheduling Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuScheduling.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Scheduling Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuScheduling_H 9 | #define HelioMenuScheduling_H 10 | 11 | class HelioSchedulingMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioSchedulingMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuScheduling_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuSensors.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Sensors Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuSensors.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Sensors Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuSensors_H 9 | #define HelioMenuSensors_H 10 | 11 | class HelioSensorsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioSensorsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuSensors_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuSettings.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Settings Menu Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | // todo 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/shared/screens/HelioMenuSettings.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino Settings Menu Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioMenuSettings_H 9 | #define HelioMenuSettings_H 10 | 11 | class HelioSettingsMenu; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | class HelioSettingsMenu : public HelioMenu 16 | { }; // todo 17 | 18 | #endif // /ifndef HelioMenuSettings_H 19 | #endif 20 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewGFX.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino AdafruitGFX Overview Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | float skyEaseInOut(float x) { 10 | return x < 0.5f ? 2.0f * x * x : 1.0f - ((-2.0f * x + 2.0f) * (-2.0f * x + 2.0f) * 0.5f); 11 | } 12 | 13 | void randomStarColor(uint8_t* r, uint8_t* g, uint8_t* b) { 14 | switch(random(20)) { 15 | case 0: 16 | *r = 155; *g = 176; *b = 255; 17 | break; 18 | case 1: 19 | *r = 170; *g = 191; *b = 255; 20 | break; 21 | case 2: 22 | *r = 202; *g = 215; *b = 255; 23 | break; 24 | case 3: case 4: 25 | *r = 248; *g = 247; *b = 255; 26 | break; 27 | case 5: case 6: case 7: 28 | *r = 255; *g = 244; *b = 234; 29 | break; 30 | case 8: case 9: case 10: case 11: 31 | *r = 255; *g = 210; *b = 161; 32 | break; 33 | default: 34 | *r = 255; *g = 204; *b = 111; 35 | break; 36 | } 37 | int randVals[3] = {(int)random(20),(int)random(25),(int)random(20)}; 38 | *r = constrain((int)(*r) + (-10 + randVals[0]), 0, 255); 39 | *g = constrain((int)(*g) + (-15 + randVals[1]), 0, 255); 40 | *b = constrain((int)(*b) + (-10 + randVals[2]), 0, 255); 41 | } 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewGFX.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino AdafruitGFX Overview Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioOverviewGFX_H 9 | #define HelioOverviewGFX_H 10 | 11 | template class HelioOverviewGFX; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | // AdafruitGFX Overview Screen 16 | // Overview screen built for AdafruitGFX displays. 17 | template 18 | class HelioOverviewGFX : public HelioOverview { 19 | public: 20 | HelioOverviewGFX(HelioDisplayAdafruitGFX *display, const void *clockFont = nullptr, const void *detailFont = nullptr); 21 | virtual ~HelioOverviewGFX(); 22 | 23 | virtual void renderOverview(bool isLandscape, Pair screenSize) override; 24 | 25 | protected: 26 | T &_gfx; // Graphics (strong) 27 | AdafruitDrawable &_drawable; // Drawable (strong) 28 | const void *_clockFont; // Overview clock font (strong) 29 | const void *_detailFont; // Overview detail font (strong) 30 | 31 | uint8_t _skyBlue, _skyRed; // Sky color 32 | Map,HELIO_UI_STARFIELD_MAXSIZE> _stars; // Starfield 33 | int _timeMag, _dateMag; // Time/date mag level 34 | DateTime _lastTime; // Last time (local) 35 | uint16_t _timeHeight, _dateHeight; // Pixel height 36 | 37 | void drawBackground(Coord pt, Coord sz, Pair &screenSize); 38 | }; 39 | 40 | #endif // /ifndef HelioOverviewGFX_H 41 | #endif 42 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewLCD.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino LCD Overview Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | HelioOverviewLCD::HelioOverviewLCD(HelioDisplayLiquidCrystal *display) 10 | : HelioOverview(display), _lcd(display->getLCD()) 11 | { ; } 12 | 13 | HelioOverviewLCD::~HelioOverviewLCD() 14 | { ; } 15 | 16 | void HelioOverviewLCD::renderOverview(bool isLandscape, Pair screenSize) 17 | { 18 | // todo 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewLCD.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino LCD Overview Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioOverviewLCD_H 9 | #define HelioOverviewLCD_H 10 | 11 | class HelioOverviewLCD; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | // LCD Overview Screen 16 | // Overview screen built for LCD displays. 17 | class HelioOverviewLCD : public HelioOverview { 18 | public: 19 | HelioOverviewLCD(HelioDisplayLiquidCrystal *display); 20 | virtual ~HelioOverviewLCD(); 21 | 22 | virtual void renderOverview(bool isLandscape, Pair screenSize) override; 23 | 24 | protected: 25 | LiquidCrystal &_lcd; // LCD (strong) 26 | }; 27 | 28 | #endif // /ifndef HelioOverviewLCD_H 29 | #endif 30 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewOLED.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino U8g2 OLED Overview Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | HelioOverviewOLED::HelioOverviewOLED(HelioDisplayU8g2OLED *display, const void *clockFont, const void *detailFont) 10 | : HelioOverview(display), _gfx(display->getGfx()), _drawable(display->getDrawable()), _clockFont(clockFont), _detailFont(detailFont) 11 | { ; } 12 | 13 | HelioOverviewOLED::~HelioOverviewOLED() 14 | { ; } 15 | 16 | void HelioOverviewOLED::renderOverview(bool isLandscape, Pair screenSize) 17 | { 18 | // todo 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewOLED.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino U8g2 OLED Overview Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioOverviewOLED_H 9 | #define HelioOverviewOLED_H 10 | 11 | class HelioOverviewOLED; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | // OLED Overview Screen 16 | // Overview screen built for OLED displays. 17 | class HelioOverviewOLED : public HelioOverview { 18 | public: 19 | HelioOverviewOLED(HelioDisplayU8g2OLED *display, const void *clockFont, const void *detailFont); 20 | virtual ~HelioOverviewOLED(); 21 | 22 | virtual void renderOverview(bool isLandscape, Pair screenSize) override; 23 | 24 | protected: 25 | U8G2 &_gfx; // Graphics (strong) 26 | #ifdef HELIO_UI_ENABLE_STCHROMA_LDTC 27 | StChromaArtDrawable &_drawable; // Drawable (strong) 28 | #else 29 | U8g2Drawable &_drawable; // Drawable (strong) 30 | #endif 31 | const void *_clockFont; // Overview clock font (strong) 32 | const void *_detailFont; // Overview detail font (strong) 33 | }; 34 | 35 | #endif // /ifndef HelioOverviewOLED_H 36 | #endif 37 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewTFT.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino TFT_eSPI Overview Screen 4 | */ 5 | 6 | #include "../HelioduinoUI.h" 7 | #ifdef HELIO_USE_GUI 8 | 9 | extern float skyEaseInOut(float x); 10 | extern void randomStarColor(uint8_t* r, uint8_t* g, uint8_t* b); 11 | 12 | HelioOverviewTFT::HelioOverviewTFT(HelioDisplayTFTeSPI *display, const void *clockFont, const void *detailFont) 13 | : HelioOverview(display), _gfx(display->getGfx()), _drawable(display->getDrawable()), _clockFont(clockFont), _detailFont(detailFont) 14 | { ; } 15 | 16 | HelioOverviewTFT::~HelioOverviewTFT() 17 | { ; } 18 | 19 | void HelioOverviewTFT::renderOverview(bool isLandscape, Pair screenSize) 20 | { 21 | // todo 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/shared/screens/HelioOverviewTFT.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | Helioduino TFT_eSPI Overview Screen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #ifndef HelioOverviewTFT_H 9 | #define HelioOverviewTFT_H 10 | 11 | class HelioOverviewTFT; 12 | 13 | #include "../HelioduinoUI.h" 14 | 15 | // TFT_eSPI Overview Screen 16 | // Overview screen built for TFT_eSPI displays. 17 | class HelioOverviewTFT : public HelioOverview { 18 | public: 19 | HelioOverviewTFT(HelioDisplayTFTeSPI *display, const void *clockFont, const void *detailFont); 20 | virtual ~HelioOverviewTFT(); 21 | 22 | virtual void renderOverview(bool isLandscape, Pair screenSize) override; 23 | 24 | protected: 25 | TFT_eSPI &_gfx; // Graphics (strong) 26 | TfteSpiDrawable &_drawable; // Drawable (strong) 27 | const void *_clockFont; // Overview clock font (strong) 28 | const void *_detailFont; // Overview detail font (strong) 29 | }; 30 | 31 | #endif // /ifndef HelioOverviewTFT_H 32 | #endif 33 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Display_LiquidCrystal.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Liquid Crystal Display 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #include "HelioduinoUI.h" 9 | 10 | /* 11 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 12 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 13 | */ 14 | 15 | /* Changelist: 16 | * - Changed from application.name to constructed appTitle parameter 17 | * - Put length limits into renderTitle & now using internal appTitle 18 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 19 | */ 20 | 21 | /** 22 | * @file tcMenu_Display_LiquidCrystal.h 23 | * 24 | * LiquidCrystalIO renderer that renders menus onto this type of display. This file is a plugin file and should not 25 | * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, 26 | * make sure to rename it first. 27 | * 28 | * LIBRARY REQUIREMENT 29 | * This renderer is designed for use with this library: https://github.com/davetcc/LiquidCrystalIO 30 | */ 31 | 32 | #ifndef _TCMENU_LIQUID_CRYSTAL_H 33 | #define _TCMENU_LIQUID_CRYSTAL_H 34 | 35 | #include 36 | 37 | #include "tcMenu.h" 38 | #include "BaseRenderers.h" 39 | #include 40 | 41 | /** 42 | * A renderer that can renderer onto a LiquidCrystal display and supports the concept of single level 43 | * sub menus, active items and editing. 44 | */ 45 | class LiquidCrystalRenderer : public BaseMenuRenderer { 46 | private: 47 | LiquidCrystal* lcd; 48 | uint8_t dimY; 49 | const char *appTitle; 50 | uint8_t backChar; 51 | uint8_t forwardChar; 52 | uint8_t editChar; 53 | bool drewTitleThisTime; 54 | bool titleRequired; 55 | uint8_t lcdEditorCursorX = 0xFF; 56 | uint8_t lcdEditorCursorY = 0xFF; 57 | public: 58 | 59 | LiquidCrystalRenderer(LiquidCrystal& lcd, uint8_t dimX, uint8_t dimY, const char *appTitle); 60 | virtual ~LiquidCrystalRenderer(); 61 | void render() override; 62 | void initialise() override; 63 | void setTitleRequired(bool titleRequired) { this->titleRequired = titleRequired; } 64 | 65 | void setEditorChars(char back, char forward, char edit); 66 | 67 | uint8_t getRows() {return dimY;} 68 | LiquidCrystal* getLCD() {return lcd;} 69 | BaseDialog* getDialog() override; 70 | private: 71 | void renderTitle(bool forceDraw); 72 | void renderMenuItem(uint8_t row, MenuItem* item); 73 | void renderActionItem(uint8_t row, MenuItem* item); 74 | void renderBackItem(uint8_t row, MenuItem* item); 75 | void renderList(); 76 | void setupEditorPlacement(int32_t x, int32_t y); 77 | }; 78 | 79 | class LiquidCrystalDialog : public BaseDialog { 80 | public: 81 | LiquidCrystalDialog(LiquidCrystalRenderer* renderer) { 82 | bitWrite(flags, DLG_FLAG_SMALLDISPLAY, (renderer->getRows() <= 2)); 83 | } 84 | protected: 85 | void internalRender(int currentValue) override; 86 | }; 87 | 88 | /** 89 | * This method constructs an instance of a liquid crystal renderer. 90 | */ 91 | inline MenuRenderer* liquidCrystalRenderer(LiquidCrystal& lcd, uint8_t dimX, uint8_t dimY, const char *appTitle) { 92 | return new LiquidCrystalRenderer(lcd, dimX, dimY, appTitle); 93 | } 94 | 95 | #endif // _TCMENU_LIQUID_CRYSTAL_H 96 | #endif 97 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Display_TfteSpi.h: -------------------------------------------------------------------------------- 1 | 2 | /* Helioduino: Simple automation controller for solar tracking systems. 3 | Copyright (C) 2023 NachtRaveVL 4 | tcMenu TFT_eSPI Display 5 | */ 6 | 7 | // SETUP NOTICE 8 | // Users should edit TFT_eSPI/User_Setup.h to match the setup used for TFTeSPI display, 9 | // via TFT_DC, TFT_CS, TFT_RST, and optionally TOUCH_CS for TFTTouch input support. 10 | 11 | #include 12 | #ifdef HELIO_USE_GUI 13 | #include "HelioduinoUI.h" 14 | 15 | /* 16 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 17 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 18 | */ 19 | 20 | /* Changelist: 21 | * - Refactored TFTTouch to have screen size given in init 22 | * - Refactored TFTTouch code to avoid define switches/build errors 23 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 24 | */ 25 | 26 | /** 27 | * @file tcMenu_Display_TfteSpi.h 28 | * 29 | * TFT_eSPI renderer that renders menus onto this type of display. This file is a plugin file and should not 30 | * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, 31 | * make sure to rename it first. 32 | */ 33 | 34 | #ifndef TCMENU_PLUGIN_TCMENUTFTESPI_H 35 | #define TCMENU_PLUGIN_TCMENUTFTESPI_H 36 | 37 | #include 38 | #include 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #define TFT_SPRITE_BITS 4 45 | #define SPRITE_PALETTE_SIZE (1 << TFT_SPRITE_BITS) 46 | 47 | using namespace tcgfx; 48 | 49 | class TftSpriteAndConfig; 50 | 51 | class TfteSpiDrawable : public DeviceDrawable { 52 | private: 53 | TFT_eSPI* tft; 54 | TftSpriteAndConfig* spriteWithConfig; 55 | uint16_t spriteHeight; 56 | public: 57 | TfteSpiDrawable(TFT_eSPI *tft, int maxSpriteHeight = 0); 58 | 59 | DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override; 60 | 61 | void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; 62 | 63 | void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; 64 | 65 | void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; 66 | 67 | void drawBox(const Coord &where, const Coord &size, bool filled) override; 68 | 69 | void drawCircle(const Coord &where, int radius, bool filled) override; 70 | 71 | void drawPolygon(const Coord *points, int numPoints, bool filled) override; 72 | 73 | void drawPixel(uint16_t x, uint16_t y) override; 74 | 75 | void transaction(bool isStarting, bool redrawNeeded) override; 76 | 77 | Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; 78 | Coord getDisplayDimensions() override { return Coord(tft->width(), tft->height());} 79 | TFT_eSPI* getTFT() { return tft; } 80 | protected: 81 | UnicodeFontHandler* createFontHandler() override; 82 | private: 83 | void fontPtrToNum(const void* font, int mag); 84 | }; 85 | 86 | class TftSpriteAndConfig : public TfteSpiDrawable { 87 | private: 88 | TfteSpiDrawable* root; 89 | TFT_eSprite sprite; 90 | Coord where; 91 | Coord currentSize; 92 | const Coord size; 93 | uint8_t currentColorsDefined; 94 | public: 95 | TftSpriteAndConfig(TfteSpiDrawable *root, int width, int height); 96 | 97 | bool initSprite(const Coord& spriteWhere, const Coord& spriteSize, const color_t* palette, int paletteEntries); 98 | DeviceDrawable *getSubDeviceFor(const Coord &where, const Coord& size, const color_t *palette, int paletteSize) override { return nullptr; } 99 | void transaction(bool isStarting, bool redrawNeeded) override; 100 | color_t getUnderlyingColor(color_t col) override; 101 | }; 102 | 103 | namespace iotouch { 104 | 105 | /** 106 | * Implements the touch interrogator class, this purely gets the current reading from the device when requested. This 107 | * implementation works with the TFT_eSPI touch functions providing tcMenu support for it. It is your responsibility 108 | * to have run whatever calibration is needed before calling this function. The X and Y values to the constructor 109 | * are the maximum values that can be returned by calling getTouch. 110 | */ 111 | class TftSpiTouchInterrogator : public iotouch::TouchInterrogator { 112 | private: 113 | TFT_eSPI* tft; 114 | uint16_t maxWidthDim; 115 | uint16_t maxHeightDim; 116 | bool usingRawTouch; 117 | public: 118 | TftSpiTouchInterrogator(TFT_eSPI* tft, bool rawTouch) 119 | : tft(tft), maxWidthDim(0), maxHeightDim(0), usingRawTouch(rawTouch) { } 120 | 121 | inline void init(uint16_t xMax, uint16_t yMax) { maxWidthDim = xMax; maxHeightDim = yMax; } 122 | iotouch::TouchState internalProcessTouch(float *ptrX, float *ptrY, const TouchOrientationSettings& touchOrientationSettings, 123 | const iotouch::CalibrationHandler& calib) override; 124 | }; 125 | 126 | } 127 | 128 | #endif //TCMENU_PLUGIN_TCMENUTFTESPI_H 129 | #endif 130 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Display_U8g2.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu U8G2 Display 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /** 15 | * @file tcMenu_Display_U8g2.h 16 | * 17 | * U8G2 renderer that renders menus onto this type of display. This file is a plugin file and should not 18 | * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, 19 | * make sure to rename it first. 20 | * 21 | * LIBRARY REQUIREMENT 22 | * This library requires the u8g2 library available for download from your IDE library manager. 23 | */ 24 | 25 | #include "tcMenu_Display_U8g2.h" 26 | 27 | const uint8_t* safeGetFont(const void* fnt) { 28 | if(fnt) return static_cast(fnt); 29 | return u8g2_font_6x10_tf; 30 | } 31 | 32 | #if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1 33 | static uint8_t bytesSent = 0; 34 | TwoWire* U8g2Drawable::pWire = nullptr; 35 | uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { 36 | if(!U8g2Drawable::pWire) return 0; 37 | switch(msg) 38 | { 39 | case U8X8_MSG_BYTE_SEND: 40 | bytesSent+= arg_int; 41 | U8g2Drawable::pWire->write((uint8_t *)arg_ptr, (int)arg_int); 42 | if(bytesSent > 16) { 43 | taskManager.yieldForMicros(0); 44 | bytesSent = 0; 45 | } 46 | break; 47 | case U8X8_MSG_BYTE_START_TRANSFER: 48 | U8g2Drawable::pWire->beginTransmission(u8x8_GetI2CAddress(u8x8)>>1); 49 | break; 50 | case U8X8_MSG_BYTE_END_TRANSFER: 51 | U8g2Drawable::pWire->endTransmission(); 52 | break; 53 | case U8X8_MSG_BYTE_INIT: 54 | case U8X8_MSG_BYTE_SET_DC: 55 | break; 56 | default: 57 | return 0; 58 | } 59 | return 1; 60 | } 61 | #endif // WANT_TASK_MANAGER_FRIENDLY_YIELD 62 | 63 | U8g2Drawable::U8g2Drawable(U8G2 *u8g2, TwoWire* wireImpl, bool tcUnicode) : u8g2(u8g2), tcUtf8(tcUnicode) { 64 | #if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1 65 | pWire = wireImpl; 66 | if(wireImpl) { 67 | u8g2->getU8x8()->byte_cb = u8g2_byte_with_yield; 68 | } 69 | #endif 70 | } 71 | 72 | void U8g2Drawable::internalDrawText(const Coord &where, const void *font, int mag, const char *text) { 73 | u8g2->setFont(safeGetFont(font)); 74 | u8g2->setFontMode(drawColor == 2); 75 | auto extraHeight = u8g2->getMaxCharHeight(); 76 | u8g2->setDrawColor(drawColor); 77 | if (tcUtf8) { 78 | u8g2->drawUTF8(where.x, where.y + extraHeight, text); 79 | } else { 80 | u8g2->setCursor(where.x, where.y + extraHeight); 81 | u8g2->print(text); 82 | } 83 | } 84 | 85 | void U8g2Drawable::drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) { 86 | u8g2->setDrawColor(backgroundColor); 87 | u8g2->drawBox(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y); 88 | u8g2->setDrawColor(drawColor); 89 | if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) { 90 | #if defined(__AVR__) || defined(ESP8266) 91 | u8g2->drawXBMP(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, icon->getIcon(selected)); 92 | #else 93 | u8g2->drawXBM(where.x, where.y, icon->getDimensions().x, icon->getDimensions().y, icon->getIcon(selected)); 94 | #endif 95 | } 96 | } 97 | 98 | void U8g2Drawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) { 99 | u8g2->setDrawColor(backgroundColor); 100 | u8g2->drawBox(where.x, where.y, size.x, size.y); 101 | u8g2->setDrawColor(drawColor); 102 | #if defined(__AVR__) || defined(ESP8266) 103 | u8g2->drawXBMP(where.x, where.y, size.x, size.y, data); 104 | #else 105 | u8g2->drawXBM(where.x, where.y, size.x, size.y, data); 106 | #endif 107 | } 108 | 109 | void U8g2Drawable::drawBox(const Coord &where, const Coord &size, bool filled) { 110 | u8g2->setDrawColor(drawColor); 111 | if(filled) { 112 | u8g2->drawBox(where.x, where.y, size.x, size.y); 113 | } 114 | else { 115 | u8g2->drawFrame(where.x, where.y, size.x, size.y); 116 | } 117 | } 118 | 119 | void U8g2Drawable::drawCircle(const Coord &where, int radius, bool filled) { 120 | u8g2->setDrawColor(drawColor); 121 | u8g2->drawCircle(where.x, where.y, radius); 122 | } 123 | 124 | void U8g2Drawable::drawPolygon(const Coord *points, int numPoints, bool filled) { 125 | if(numPoints == 2) { 126 | u8g2->drawLine(points[0].x, points[0].y, points[1].x, points[1].y); 127 | } 128 | else if(numPoints == 3) { 129 | u8g2->drawTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y); 130 | } 131 | } 132 | 133 | 134 | void U8g2Drawable::transaction(bool isStarting, bool redrawNeeded) { 135 | if(isStarting) { 136 | u8g2->setFontPosBottom(); 137 | u8g2->setFontRefHeightExtendedText(); 138 | } 139 | else if(redrawNeeded) { 140 | u8g2->sendBuffer(); 141 | } 142 | } 143 | 144 | Coord U8g2Drawable::internalTextExtents(const void *font, int mag, const char *text, int *baseline) { 145 | u8g2->setFont(safeGetFont(font)); 146 | if(baseline) *baseline = (int)u8g2->getFontDescent(); 147 | if (tcUtf8) { 148 | return Coord(u8g2->getUTF8Width(text), u8g2->getMaxCharHeight()); 149 | } else { 150 | return Coord(u8g2->getStrWidth(text), u8g2->getMaxCharHeight()); 151 | } 152 | } 153 | 154 | void U8g2Drawable::drawPixel(uint16_t x, uint16_t y) { 155 | u8g2->drawPixel(x, y); 156 | } 157 | 158 | UnicodeFontHandler* U8g2Drawable::createFontHandler() { 159 | return new UnicodeFontHandler(u8g2, ENCMODE_UTF8); 160 | } 161 | 162 | #endif 163 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Display_U8g2.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu U8G2 Display 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #include "HelioduinoUI.h" 9 | 10 | /* 11 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 12 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 13 | */ 14 | 15 | /* Changelist: 16 | * - Refactored UTF8 usage to dyanmic 17 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 18 | */ 19 | 20 | /** 21 | * @file tcMenu_Display_U8g2.h 22 | * 23 | * U8G2 renderer that renders menus onto this type of display. This file is a plugin file and should not 24 | * be directly edited, it will be replaced each time the project is built. If you want to edit this file in place, 25 | * make sure to rename it first. 26 | * 27 | * LIBRARY REQUIREMENT 28 | * This library requires the u8g2 library available for download from your IDE library manager. 29 | */ 30 | 31 | #ifndef _TCMENU_U8G2_H_ 32 | #define _TCMENU_U8G2_H_ 33 | 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | // If you DONT want task manager yield code in I2C set to 0 45 | #ifndef WANT_TASK_MANAGER_FRIENDLY_YIELD 46 | #define WANT_TASK_MANAGER_FRIENDLY_YIELD 0 47 | #endif // WANT_TASK_MANAGER_FRIENDLY_YIELD 48 | 49 | using namespace tcgfx; 50 | 51 | /** 52 | * A standard menu render configuration that describes how to renderer each item and the title. 53 | * Specialised for u8g2 fonts. 54 | */ 55 | typedef struct ColorGfxMenuConfig U8G2GfxMenuConfig; 56 | 57 | // some colour displays don't create this value 58 | #ifndef BLACK 59 | #define BLACK 0 60 | #endif 61 | 62 | // some colour displays don't create this value 63 | #ifndef WHITE 64 | #define WHITE 1 65 | #endif 66 | 67 | /** 68 | * This is used to draw to I2C including a task manager yield to improve performance on slower I2C devices. 69 | * Not really needed for SPI as we are talking in low order millis for a full refresh. 70 | */ 71 | uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); 72 | 73 | /** 74 | * A basic renderer that can use the AdaFruit_GFX library to render information onto a suitable 75 | * display. It is your responsibility to fully initialise and prepare the display before passing 76 | * it to this renderer. The usual procedure is to create a display variable globally in your 77 | * sketch and then provide that as the parameter to setGraphicsDevice. If you are using the 78 | * designer you provide the display variable name in the code generation parameters. 79 | * 80 | * You can also override many elements of the display using AdaColorGfxMenuConfig, to use the defaults 81 | * just call prepareAdaColorDefaultGfxConfig(..) passing it a pointer to your config object. Again the 82 | * designer UI takes care of this. 83 | */ 84 | class U8g2Drawable : public DeviceDrawable { 85 | private: 86 | U8G2* u8g2; 87 | bool tcUtf8; 88 | #if WANT_TASK_MANAGER_FRIENDLY_YIELD == 1 89 | static TwoWire* pWire; 90 | friend uint8_t u8g2_byte_with_yield(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); 91 | #endif // WANT_TASK_MANAGER_FRIENDLY_YIELD 92 | public: 93 | explicit U8g2Drawable(U8G2* u8g2, TwoWire* wire = nullptr, bool tcUnicode = false); 94 | ~U8g2Drawable() override = default; 95 | 96 | DeviceDrawable* getSubDeviceFor(const Coord &where, const Coord &size, const color_t *palette, int paletteSize) override {return nullptr; } 97 | 98 | void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; 99 | void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; 100 | void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; 101 | void drawBox(const Coord &where, const Coord &size, bool filled) override; 102 | void drawCircle(const Coord &where, int radius, bool filled) override; 103 | void drawPolygon(const Coord *points, int numPoints, bool filled) override; 104 | 105 | Coord getDisplayDimensions() override { return Coord(u8g2->getWidth(), u8g2->getHeight()); } 106 | void transaction(bool isStarting, bool redrawNeeded) override; 107 | Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; 108 | color_t getUnderlyingColor(color_t col) override { return (col<4) ? col : 1; } 109 | protected: 110 | void drawPixel(uint16_t x, uint16_t y) override; 111 | UnicodeFontHandler *createFontHandler() override; 112 | }; 113 | 114 | #endif // _TCMENU_U8G2_H_ 115 | #endif 116 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Extra_BspUserSettings.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu STM32 LDTC Frame Buffer & BSP Touch 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_GUI) && (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_STM32)) && defined(HELIO_UI_ENABLE_BSP_TOUCH) 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 16 | */ 17 | 18 | #ifndef TCMENU_BSP_INCLUDES 19 | #define TCMENU_BSP_INCLUDES 20 | 21 | // 22 | // In this file you provide all the includes needed for your BSP driver. It may even be that you need to provide 23 | // mappings between any incompatible functions and the ones you have available. In most cases this should be minimal. 24 | // 25 | 26 | // These are the includes needed to access the display and touch BSP functions 27 | // This path works for platformio, change as needed for your arrangements. 28 | 29 | #include "Drivers/BSP/STM32F429I-Discovery/stm32f429i_discovery_ts.h" 30 | #include "Drivers/BSP/STM32F429I-Discovery/stm32f429i_discovery_lcd.h" 31 | 32 | // Here's the functions we expect to be present, if you don't have these in your setup, you will need to provide them. 33 | 34 | // Touch screen 35 | 36 | // LCD 37 | // structure TS_StateTypeDef must be defined 38 | // BSP_TS_Init(xSize, ySize) 39 | // BSP_TS_GetState(TS_StateTypeDef*) 40 | 41 | // structure sFONT must be defined 42 | // BSP_LCD_Init() 43 | // BSP_LCD_LayerDefaultInit(layer, address) 44 | // BSP_LCD_DrawBitmap(x, y, data) 45 | // BSP_LCD_DrawPixel(x, y, color) 46 | // BSP_LCD_FillRect(x, y, w, h) 47 | // BSP_LCD_DrawRect(x, y, w, h) 48 | // BSP_LCD_FillCircle(x, y, r) 49 | // BSP_LCD_DrawCircle(x, y, r) 50 | // BSP_LCD_DrawLine(x, y, x1, y1) 51 | // BSP_LCD_FillTriangle(x, y, x1, y1, x2, y2) 52 | // BSP_LCD_SetFont(sFONT*) 53 | // BSP_LCD_SetTextColor(uint32_t) 54 | // BSP_LCD_SetBackColor(uint32_t) 55 | // BSP_LCD_DisplayStringAt(x, y, text, justification) 56 | 57 | #endif 58 | #endif 59 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Extra_StChromaArt.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu STM32 LDTC Frame Buffer & BSP Touch 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_GUI) && (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_STM32)) 8 | #include "HelioduinoUI.h" 9 | #if (defined(HELIO_UI_ENABLE_STCHROMA_LDTC) || defined(HELIO_UI_ENABLE_BSP_TOUCH)) 10 | 11 | /* 12 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 13 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 14 | */ 15 | 16 | #include "tcMenu_Extra_StChromaArt.h" 17 | 18 | StChromaArtDrawable::StChromaArtDrawable() { 19 | BSP_LCD_Init(); 20 | BSP_LCD_LayerDefaultInit(0, SDRAM_DEVICE_ADDR); 21 | } 22 | 23 | Coord StChromaArtDrawable::internalTextExtents(const void *maybeFont, int mag, const char *text, int *baseline) { 24 | auto fontHandler = getUnicodeHandler(true); 25 | setTcFontAccordingToMag(fontHandler, maybeFont, mag); 26 | return fontHandler->textExtents(text, baseline, false); 27 | } 28 | 29 | void StChromaArtDrawable::internalDrawText(const Coord &where, const void *font, int mag, const char *text) { 30 | if(font == nullptr) return; // font must be defined 31 | 32 | auto handler = getUnicodeHandler(true); 33 | setTcFontAccordingToMag(handler, font, mag); 34 | handler->setCursor(where.x, where.y + handler->getYAdvance()); 35 | handler->print(text); 36 | } 37 | 38 | Coord StChromaArtDrawable::getDisplayDimensions() { 39 | return Coord(BSP_LCD_GetXSize(), BSP_LCD_GetYSize()); 40 | } 41 | 42 | void StChromaArtDrawable::drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) { 43 | if(icon->getIconType() == DrawableIcon::ICON_NATIVE) { 44 | BSP_LCD_DrawBitmap(where.x, where.y, (uint8_t*)icon->getIcon(selected)); 45 | } 46 | else if(icon->getIconType() == DrawableIcon::ICON_XBITMAP) { 47 | drawXBitmap(where, icon->getDimensions(), icon->getIcon(selected)); 48 | } 49 | } 50 | 51 | void StChromaArtDrawable::drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) { 52 | int16_t w = size.x; 53 | int16_t h = size.y; 54 | int16_t y = where.y; 55 | 56 | int16_t byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte 57 | uint8_t byte = 0; 58 | 59 | for (int16_t j = 0; j < h; j++, y++) { 60 | for (int16_t i = 0; i < w; i++) { 61 | if (i & 7) { 62 | byte >>= 1; 63 | } else { 64 | byte = data[j * byteWidth + i / 8]; 65 | } 66 | // Nearly identical to drawBitmap(), only the bit order 67 | // is reversed here (left-to-right = LSB to MSB): 68 | BSP_LCD_DrawPixel(where.x + i , where.y + j, (byte & 0x01) ? drawColor : backgroundColor); 69 | } 70 | } 71 | } 72 | 73 | void StChromaArtDrawable::drawBox(const Coord &where, const Coord &size, bool filled) { 74 | BSP_LCD_SetTextColor(drawColor); 75 | if(filled) { 76 | BSP_LCD_FillRect(where.x, where.y, size.x, size.y); 77 | } 78 | else { 79 | BSP_LCD_DrawRect(where.x, where.y, size.x, size.y); 80 | } 81 | } 82 | 83 | void StChromaArtDrawable::drawCircle(const Coord &where, int radius, bool filled) { 84 | // make sure the circle is within bounds, otherwise it crashes BSP. 85 | if(where.x < radius || where.y < radius || where.x + radius > BSP_LCD_GetXSize() || where.y + radius > BSP_LCD_GetYSize()) return; 86 | 87 | BSP_LCD_SetTextColor(drawColor); 88 | if(filled) { 89 | BSP_LCD_FillCircle(where.x, where.y, radius); 90 | } 91 | else { 92 | BSP_LCD_DrawCircle(where.x, where.y, radius); 93 | } 94 | } 95 | 96 | void StChromaArtDrawable::drawPolygon(const Coord *points, int numPoints, bool filled) { 97 | BSP_LCD_SetTextColor(drawColor); 98 | if(numPoints == 2) { 99 | BSP_LCD_DrawLine(points[0].x, points[0].y, points[1].x, points[1].y); 100 | } 101 | else if(numPoints == 3) { 102 | BSP_LCD_FillTriangle(points[0].x, points[0].y, points[1].x, points[1].y, points[2].x, points[2].y); 103 | } 104 | } 105 | 106 | void StChromaArtDrawable::transaction(bool isStarting, bool redrawNeeded) { 107 | } 108 | 109 | 110 | StBspTouchInterrogator::StBspTouchInterrogator() 111 | : width(0), height(0) {} 112 | 113 | void StBspTouchInterrogator::init(int wid, int hei) { 114 | width = wid; 115 | height = hei; 116 | BSP_TS_Init(width, height); 117 | } 118 | 119 | iotouch::TouchState StBspTouchInterrogator::internalProcessTouch(float *ptrX, float *ptrY, const iotouch::TouchOrientationSettings& rotation, 120 | const iotouch::CalibrationHandler& calibrationHandler) { 121 | TS_StateTypeDef tsState; 122 | BSP_TS_GetState(&tsState); 123 | if(!tsState.TouchDetected) return iotouch::NOT_TOUCHED; 124 | 125 | *ptrX = calibrationHandler.calibrateX((float)tsState.X / float(width), rotation.isXInverted()); 126 | *ptrY = calibrationHandler.calibrateY(float(height - tsState.Y) / float(height), rotation.isYInverted()); 127 | return iotouch::TOUCHED; 128 | } 129 | 130 | #endif 131 | #endif 132 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Extra_StChromaArt.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu STM32 LDTC Frame Buffer & BSP Touch 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_GUI) && (defined(ARDUINO_ARCH_MBED) || defined(ARDUINO_ARCH_STM32)) 8 | #include "HelioduinoUI.h" 9 | #if (defined(HELIO_UI_ENABLE_STCHROMA_LDTC) || defined(HELIO_UI_ENABLE_BSP_TOUCH)) 10 | 11 | /* 12 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 13 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 14 | */ 15 | 16 | /* Changelist: 17 | * - Refactored to have screen size given in init 18 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 19 | */ 20 | 21 | /** 22 | * @file tcMenu_Extra_StChromaArt.h 23 | * 24 | * This renderer works with the ChromaART classes provided on many ST boards, it assumes you have a object that 25 | * represents the frame buffer. 26 | * 27 | * LIBRARY REQUIREMENT 28 | * This library requires the u8g2 library available for download from your IDE library manager. 29 | */ 30 | 31 | #ifndef TCMENU_ST_CHROMA_ART_H 32 | #define TCMENU_ST_CHROMA_ART_H 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "tcMenu_Extra_BspUserSettings.h" 42 | 43 | using namespace tcgfx; 44 | 45 | // some colour displays don't create this value 46 | #ifndef BLACK 47 | #define BLACK 0 48 | #endif 49 | 50 | // some colour displays don't create this value 51 | #ifndef WHITE 52 | #define WHITE 0xffff 53 | #endif 54 | 55 | /** 56 | * A renderer that can work with BSP_LCD displays for mbed such as the STM32F429 discovery display prototype. You 57 | * can use this as a starting point for a chroma art based display renderer. It provides some extended support 58 | * by providing font capabilities from the Adafruit Graphics libraries. 59 | */ 60 | class StChromaArtDrawable : public DeviceDrawable { 61 | public: 62 | explicit StChromaArtDrawable(); 63 | ~StChromaArtDrawable() override = default; 64 | 65 | DeviceDrawable* getSubDeviceFor(const Coord &where, const Coord &size, const color_t *palette, int paletteSize) override {return nullptr; } 66 | 67 | void internalDrawText(const Coord &where, const void *font, int mag, const char *text) override; 68 | void drawBitmap(const Coord &where, const DrawableIcon *icon, bool selected) override; 69 | void drawXBitmap(const Coord &where, const Coord &size, const uint8_t *data) override; 70 | void drawBox(const Coord &where, const Coord &size, bool filled) override; 71 | void drawCircle(const Coord &where, int radius, bool filled) override; 72 | void drawPolygon(const Coord *points, int numPoints, bool filled) override; 73 | 74 | Coord getDisplayDimensions() override; 75 | void transaction(bool isStarting, bool redrawNeeded) override; 76 | Coord internalTextExtents(const void *font, int mag, const char *text, int *baseline) override; 77 | void drawPixel(uint16_t x, uint16_t y) override { BSP_LCD_DrawPixel(x, y, drawColor); } 78 | }; 79 | 80 | class StBspTouchInterrogator : public iotouch::TouchInterrogator { 81 | private: 82 | int width, height; 83 | public: 84 | StBspTouchInterrogator(); 85 | 86 | void init(int wid, int hei); 87 | iotouch::TouchState internalProcessTouch(float *ptrX, float *ptrY, const iotouch::TouchOrientationSettings& rotation, 88 | const iotouch::CalibrationHandler& calib) override; 89 | }; 90 | 91 | #endif // TCMENU_ST_CHROMA_ART_H 92 | #endif 93 | #endif 94 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Input_AdaTouchDriver.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Adafruit FT2606 & XPT2046 Touchscreen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | #include "tcMenu_Input_AdaTouchDriver.h" 15 | 16 | #ifndef HELIO_UI_ENABLE_XPT2046TS 17 | iotouch::AdaLibTouchInterrogator::AdaLibTouchInterrogator(Adafruit_FT6206& touchLibRef) 18 | : theTouchDevice(touchLibRef), maxWidthDim(0), maxHeightDim(0) {} 19 | #else 20 | iotouch::AdaLibTouchInterrogator::AdaLibTouchInterrogator(XPT2046_Touchscreen& touchLibRef) 21 | : theTouchDevice(touchLibRef) {} 22 | #endif 23 | 24 | iotouch::TouchState iotouch::AdaLibTouchInterrogator::internalProcessTouch(float *ptrX, float *ptrY, const iotouch::TouchOrientationSettings& rotation, const iotouch::CalibrationHandler& calib) { 25 | if(theTouchDevice.touched() == 0) return iotouch::NOT_TOUCHED; 26 | 27 | TS_Point pt = theTouchDevice.getPoint(); 28 | //serdebugF3("point at ", pt.x, pt.y); 29 | 30 | #ifndef HELIO_UI_ENABLE_XPT2046TS 31 | *ptrX = calib.calibrateX(float(pt.x) / maxWidthDim, rotation.isXInverted()); 32 | *ptrY = calib.calibrateY(float(pt.y) / maxHeightDim, rotation.isYInverted()); 33 | #else 34 | *ptrX = calib.calibrateX(float(pt.x) / XPT2046_RAW_MAX, rotation.isXInverted()); 35 | *ptrY = calib.calibrateY(float(pt.y) / XPT2046_RAW_MAX, rotation.isYInverted()); 36 | #endif 37 | return iotouch::TOUCHED; 38 | } 39 | 40 | #endif -------------------------------------------------------------------------------- /src/shared/tcMenu_Input_AdaTouchDriver.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Adafruit FT2606 & XPT2046 Touchscreen 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | #include "HelioduinoUI.h" 9 | 10 | /* 11 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 12 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 13 | */ 14 | 15 | /* Changelist: 16 | * - Refactored to have screen size/SPI given in init 17 | * - Split into proper header/source file 18 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 19 | */ 20 | 21 | /** 22 | * @file tcMenu_Input_AdaTouchDriver.h 23 | * 24 | * Touch integration for libraries that are compatible with the Adafruit_FT2606 library interface. It has been tested 25 | * with both the XPT_2046 and FT_6206 libraries. 26 | * This file is a plugin file and should not be directly edited, it will be replaced each time the project 27 | * is built. If you want to edit this file in place, make sure to rename it first. 28 | */ 29 | 30 | #ifndef TCMENU_TOUCH_PLUGIN_H 31 | #define TCMENU_TOUCH_PLUGIN_H 32 | 33 | #ifndef HELIO_UI_ENABLE_XPT2046TS 34 | #include 35 | #else 36 | #include 37 | #endif 38 | #include 39 | 40 | namespace iotouch { 41 | 42 | /** 43 | * Implements the touch interrogator class, this purely gets the current reading from the device when requested. 44 | */ 45 | class AdaLibTouchInterrogator : public iotouch::TouchInterrogator { 46 | private: 47 | #ifndef HELIO_UI_ENABLE_XPT2046TS 48 | Adafruit_FT6206& theTouchDevice; 49 | uint16_t maxWidthDim; 50 | uint16_t maxHeightDim; 51 | #else 52 | XPT2046_Touchscreen& theTouchDevice; 53 | #endif 54 | public: 55 | #ifndef HELIO_UI_ENABLE_XPT2046TS 56 | AdaLibTouchInterrogator(Adafruit_FT6206& touchLibRef); 57 | #else 58 | AdaLibTouchInterrogator(XPT2046_Touchscreen& touchLibRef); 59 | #endif 60 | 61 | #ifndef HELIO_UI_ENABLE_XPT2046TS 62 | inline void init(uint16_t xMax, uint16_t yMax) { maxWidthDim = xMax; maxHeightDim = yMax; theTouchDevice.begin(); } 63 | #else 64 | inline void init(SPIClass *spi = nullptr) { if (spi) { theTouchDevice.begin(*spi); } else { theTouchDevice.begin(); } } 65 | #endif 66 | iotouch::TouchState internalProcessTouch(float *ptrX, float *ptrY, const iotouch::TouchOrientationSettings& rotation, const iotouch::CalibrationHandler& calib); 67 | }; 68 | 69 | } 70 | 71 | #endif // TCMENU_TOUCH_PLUGIN_H 72 | #endif 73 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Input_ESP32TouchKeysAbstraction.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu ESP32 Touch Keys 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_GUI) && defined(ESP32) 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | #include "tcMenu_Input_ESP32TouchKeysAbstraction.h" 15 | 16 | volatile int intCount = 0; 17 | 18 | void esp32TouchKeyInterruptHandler(void* touchAbsAsVoid) { 19 | TaskManager::markInterrupted(0); 20 | intCount++; 21 | } 22 | 23 | bool ESP32TouchKeysAbstraction::runLoop() { 24 | return allOk; 25 | } 26 | 27 | void ESP32TouchKeysAbstraction::attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) { 28 | interruptCodeNeeded = true; 29 | } 30 | 31 | uint8_t ESP32TouchKeysAbstraction::readValue(pinid_t pin) { 32 | if(!allOk) return 0; 33 | 34 | ensureInterruptRegistered(); 35 | 36 | uint16_t val; 37 | touch_pad_read_filtered((touch_pad_t)pin, &val); 38 | return val <= pinThreshold; 39 | } 40 | 41 | void ESP32TouchKeysAbstraction::pinDirection(pinid_t pin, uint8_t mode) { 42 | if(!allOk) return; 43 | serdebugF2("Pin Direction ", pin); 44 | touch_pad_config((touch_pad_t) pin, pinThreshold); 45 | touch_pad_set_trigger_mode(TOUCH_TRIGGER_BELOW); 46 | } 47 | 48 | ESP32TouchKeysAbstraction::ESP32TouchKeysAbstraction(int defThreshold, touch_high_volt_t highVoltage, 49 | touch_low_volt_t lowVoltage, touch_volt_atten_t attenuation) { 50 | allOk = touch_pad_init() == ESP_OK; 51 | serdebugF2("touch_pad_init ", allOk); 52 | touch_pad_set_voltage(highVoltage, lowVoltage, attenuation); 53 | serdebugF2("touch_pad set voltage ", allOk); 54 | interruptCodeNeeded = false; 55 | startedUp = false; 56 | pinThreshold = defThreshold; 57 | enabledPinMask = 0; 58 | taskManager.scheduleFixedRate(5, [] {serdebugF2("intCount=", intCount);}, TIME_SECONDS); 59 | } 60 | 61 | void ESP32TouchKeysAbstraction::ensureInterruptRegistered() { 62 | if(!startedUp) { 63 | startedUp = true; 64 | touch_pad_filter_start(DEFAULT_TOUCHKEY_FILTER_FREQ); 65 | } 66 | 67 | if(interruptCodeNeeded) { 68 | interruptCodeNeeded = false; 69 | touch_pad_isr_register(esp32TouchKeyInterruptHandler, this); 70 | allOk = touch_pad_intr_enable() == ESP_OK; 71 | serdebugF2("Enabled interrupts for touch sensor ok=", allOk); 72 | } 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Input_ESP32TouchKeysAbstraction.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu ESP32 Touch Keys 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_GUI) && defined(ESP32) 8 | #include "HelioduinoUI.h" 9 | 10 | /* 11 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 12 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 13 | */ 14 | 15 | /* Changelist: 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | /** 20 | * @file ESP32TouchKeysAbstraction.h 21 | * 22 | * Contains an ESP32 specific touch key implementation 23 | */ 24 | 25 | #ifndef IOABSTRACTION_ESP32TOUCHKEYSABSTRACTION_H 26 | #define IOABSTRACTION_ESP32TOUCHKEYSABSTRACTION_H 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #ifndef DEFAULT_TOUCHKEY_FILTER_FREQ 33 | #define DEFAULT_TOUCHKEY_FILTER_FREQ 10 34 | #endif 35 | 36 | /** 37 | * An IoAbstraction that can work with the touch key sensors on ESP32 boards using the underlying functions. 38 | */ 39 | class ESP32TouchKeysAbstraction : public BasicIoAbstraction { 40 | private: 41 | uint16_t pinThreshold; 42 | uint16_t enabledPinMask; 43 | bool allOk; 44 | bool interruptCodeNeeded; 45 | bool startedUp; 46 | public: 47 | ESP32TouchKeysAbstraction(int defThreshold, touch_high_volt_t highVoltage = TOUCH_HVOLT_2V7, touch_low_volt_t lowVoltage = TOUCH_LVOLT_0V5, 48 | touch_volt_atten_t attenuation = TOUCH_HVOLT_ATTEN_1V); 49 | ~ESP32TouchKeysAbstraction() override = default; 50 | 51 | void ensureInterruptRegistered(); 52 | 53 | /** 54 | * You can call this method to check if any errors occurred during initialisation 55 | * @return true if correctly created, otherwise false. 56 | */ 57 | bool isCorrectlyCreated() const { return allOk; } 58 | 59 | /** 60 | * Sets the direction, but direction is always input for this abstraction. Must still be called to initialise the 61 | * touch interface for that pin. 62 | * @param pin the touch pin number 0..9 63 | * @param mode always input, ignored 64 | */ 65 | void pinDirection(pinid_t pin, uint8_t mode) override; 66 | 67 | uint8_t readValue(pinid_t pin) override; 68 | void attachInterrupt(pinid_t pin, RawIntHandler interruptHandler, uint8_t mode) override; 69 | bool runLoop() override; 70 | 71 | // 72 | // Unimplemented functions 73 | // 74 | void writePort(pinid_t pin, uint8_t portVal) override { } 75 | void writeValue(pinid_t pin, uint8_t value) override { } 76 | uint8_t readPort(pinid_t pin) override { return 0; } 77 | }; 78 | 79 | #endif //IOABSTRACTION_ESP32TOUCHKEYSABSTRACTION_H 80 | #endif 81 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_EthernetTransport.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Ethernet Remote Control 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_ETHERNET) && defined(HELIO_USE_GUI) 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /** 15 | * Ethernet remote capability plugin. This file is a plugin file and should not be directly edited, 16 | * it will be replaced each time the project is built. If you want to edit this file in place, 17 | * make sure to rename it first. 18 | */ 19 | 20 | #include "tcMenu_Remote_EthernetTransport.h" 21 | 22 | using namespace tcremote; 23 | 24 | #if ETHERNET_BUFFER_SIZE > 0 // we need buffering when dealing with Ethernet2 25 | 26 | bool EthernetTagValTransport::available() { 27 | return client && client.connected(); 28 | } 29 | 30 | bool EthernetTagValTransport::connected() { 31 | return client && client.connected(); 32 | } 33 | 34 | void EthernetTagValTransport::flush() { 35 | if(!client || writeBufferPos == 0) return; 36 | 37 | if((int)client.write(writeBuffer, writeBufferPos) == writeBufferPos) { 38 | serdebugF2("Buffer written ", writeBufferPos); 39 | writeBufferPos = 0; 40 | client.flush(); 41 | } 42 | else { 43 | writeBufferPos = 0; 44 | close(); 45 | } 46 | } 47 | 48 | int EthernetTagValTransport::fillReadBuffer(uint8_t* dataBuffer, int maxData) { 49 | if(client && client.connected() && client.available()) { 50 | auto amt = client.read(dataBuffer, maxData); 51 | if(amt <= 0) { 52 | close(); 53 | return 0; 54 | } 55 | serdebugF2("read to buffer ", amt); 56 | return amt; 57 | } 58 | return 0; 59 | } 60 | 61 | void EthernetTagValTransport::close() { 62 | serdebugF("socket close"); 63 | BaseBufferedRemoteTransport::close(); 64 | client.stop(); 65 | } 66 | 67 | #else // unbuffed client - requires library to support Nagle algorythm. 68 | 69 | bool EthernetTagValTransport::available() { 70 | return client && client.connected(); 71 | } 72 | 73 | bool EthernetTagValTransport::connected() { 74 | return client && client.connected(); 75 | } 76 | 77 | int EthernetTagValTransport::writeChar(char data) { 78 | // only uncomment below for worst case debugging.. 79 | // serdebug2("writing ", data); 80 | return client.write(data); 81 | } 82 | 83 | int EthernetTagValTransport::writeStr(const char* data) { 84 | // only uncomment below for worst case debugging.. 85 | // serdebug2("writing ", data); 86 | return client.write(data); 87 | } 88 | 89 | void EthernetTagValTransport::flush() { 90 | if(client) client.flush(); 91 | } 92 | 93 | uint8_t EthernetTagValTransport::readByte() { 94 | return client.read(); 95 | } 96 | 97 | bool EthernetTagValTransport::readAvailable() { 98 | return client && client.connected() && client.available(); 99 | } 100 | 101 | void EthernetTagValTransport::close() { 102 | serdebugF("socket close"); 103 | client.stop(); 104 | currentField.msgType = UNKNOWN_MSG_TYPE; 105 | currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG; 106 | } 107 | 108 | #endif 109 | 110 | bool EthernetInitialisation::attemptInitialisation() { 111 | #ifdef ARDUINO_ARCH_STM32 112 | // we'll keep checking if the link is up before trying to initialise further 113 | if(Ethernet.linkStatus() == LinkOFF) return false; 114 | #endif 115 | serdebugF("Initialising server "); 116 | this->server->begin(); 117 | initialised = true; 118 | return initialised; 119 | } 120 | 121 | bool EthernetInitialisation::attemptNewConnection(BaseRemoteServerConnection *remoteServerConnection) { 122 | auto client = server->available(); 123 | if(client) { 124 | serdebugF("Client found"); 125 | auto* tvCon = reinterpret_cast(remoteServerConnection); 126 | reinterpret_cast(tvCon->transport())->setClient(client); 127 | return true; 128 | } 129 | return false; 130 | } 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_EthernetTransport.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Ethernet Remote Control 4 | */ 5 | 6 | #include 7 | #if defined(HELIO_USE_ETHERNET) && defined(HELIO_USE_GUI) 8 | #include "HelioduinoUI.h" 9 | 10 | /* 11 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 12 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 13 | */ 14 | 15 | /* Changelist: 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | /** 20 | * @file tcMenu_Remote_EthernetTransport.h 21 | * 22 | * Ethernet remote capability plugin. This file is a plugin file and should not be directly edited, 23 | * it will be replaced each time the project is built. If you want to edit this file in place, 24 | * make sure to rename it first. 25 | */ 26 | 27 | #ifndef TCMENU_ETHERNETTRANSPORT_H_ 28 | #define TCMENU_ETHERNETTRANSPORT_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef ETHERNET_BUFFER_SIZE 36 | #define ETHERNET_BUFFER_SIZE 64 37 | #endif 38 | 39 | #if ETHERNET_BUFFER_SIZE > 0 40 | #include 41 | #endif 42 | 43 | namespace tcremote { 44 | 45 | #if ETHERNET_BUFFER_SIZE > 0 46 | 47 | /** 48 | * An implementation of TagValueTransport that is able to read and write via a buffer to sockets. 49 | */ 50 | class EthernetTagValTransport : public tcremote::BaseBufferedRemoteTransport { 51 | private: 52 | EthernetClient client; 53 | public: 54 | EthernetTagValTransport() : BaseBufferedRemoteTransport(BUFFER_MESSAGES_TILL_FULL, ETHERNET_BUFFER_SIZE, MAX_VALUE_LEN) { } 55 | ~EthernetTagValTransport() override = default; 56 | void setClient(EthernetClient cl) { this->client = cl; } 57 | 58 | int fillReadBuffer(uint8_t* data, int maxSize) override; 59 | void flush() override; 60 | bool available() override; 61 | bool connected() override; 62 | void close() override; 63 | }; 64 | 65 | #else // ethernet buffering not needed 66 | 67 | /** 68 | * An implementation of TagValueTransport that is able to read and write using sockets. 69 | */ 70 | class EthernetTagValTransport : public TagValueTransport { 71 | private: 72 | EthernetClient client; 73 | public: 74 | EthernetTagValTransport() : TagValueTransport(TagValueTransportType::TVAL_UNBUFFERED) {}; 75 | ~EthernetTagValTransport() override = default; 76 | void setClient(EthernetClient client) { this->client = client; } 77 | 78 | int writeChar(char data) override ; 79 | int writeStr(const char* data) override; 80 | void flush() override; 81 | bool available() override; 82 | bool connected() override; 83 | uint8_t readByte() override; 84 | bool readAvailable() override; 85 | void close() override; 86 | }; 87 | 88 | #endif // ethernet buffering check 89 | 90 | /** 91 | * This class provides the initialisation and connection generation logic for ethernet connections. 92 | */ 93 | class EthernetInitialisation : public DeviceInitialisation { 94 | private: 95 | EthernetServer *server; 96 | public: 97 | explicit EthernetInitialisation(EthernetServer* server) : server(server) {} 98 | 99 | bool attemptInitialisation() override; 100 | 101 | bool attemptNewConnection(BaseRemoteServerConnection *transport) override; 102 | }; 103 | 104 | /** 105 | * This function converts from a RSSI (Radio Strength indicator) 106 | * measurement into a series of icons (of the ones we have defined 107 | * in the stock icons. The input is the RSSI figure in dB as an 108 | * integer. 109 | * @param strength the signal strength (usually negative) as an int 110 | * @return a state that can be used with the standard wifi TitleWidget 111 | */ 112 | int fromWiFiRSSITo4StateIndicator(int strength); 113 | 114 | } // namespace tcremote 115 | 116 | #ifndef TC_MANUAL_NAMESPACING 117 | using namespace tcremote; 118 | #endif // TC_MANUAL_NAMESPACING 119 | 120 | #endif /* TCMENU_ETHERNETTRANSPORT_H_ */ 121 | #endif 122 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_SerialTransport.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Serial Remote Control 4 | */ 5 | #include 6 | #ifdef HELIO_USE_GUI 7 | 8 | /* 9 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 10 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 11 | */ 12 | 13 | /** 14 | * Serial remote capability plugin. This file is a plugin file and should not be directly edited, 15 | * it will be replaced each time the project is built. If you want to edit this file in place, 16 | * make sure to rename it first. 17 | */ 18 | 19 | #include "tcMenu_Remote_SerialTransport.h" 20 | 21 | SerialTagValueTransport::SerialTagValueTransport(Stream* thePort) : TagValueTransport(TVAL_UNBUFFERED) { 22 | this->serialPort = thePort; 23 | } 24 | 25 | void SerialTagValueTransport::close() { 26 | currentField.msgType = UNKNOWN_MSG_TYPE; 27 | currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG; 28 | } 29 | 30 | // DO NOT replace this with the standard char* write method on serial. 31 | // It cannot handle large volumes of data going through at once and often 32 | // overflows the buffer causing data errors. 33 | int SerialTagValueTransport::writeChar(char ch) { 34 | if(available()) { 35 | serialPort->write(ch); 36 | } 37 | else { 38 | int tries = 30; 39 | while(tries && !available()) { 40 | --tries; 41 | serialPort->flush(); 42 | taskManager.yieldForMicros(100); 43 | } 44 | 45 | // if it's not available now, it probably will timeout anyway. 46 | if(!available()) { 47 | return 0; 48 | } 49 | 50 | serialPort->write(ch); 51 | } 52 | return 1; 53 | } 54 | 55 | int SerialTagValueTransport::writeStr(const char* str) { 56 | int i=0; 57 | bool lastWriteOk = true; 58 | while(str[i] && lastWriteOk) { 59 | lastWriteOk = writeChar(str[i]); 60 | i++; 61 | } 62 | return i; 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_SerialTransport.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Serial Remote Control 4 | */ 5 | #include 6 | #ifdef HELIO_USE_GUI 7 | #include "HelioduinoUI.h" 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 16 | */ 17 | 18 | /** 19 | * @file tcMenu_Remote_SerialTransport.h 20 | * 21 | * Serial remote capability plugin. This file is a plugin file and should not be directly edited, 22 | * it will be replaced each time the project is built. If you want to edit this file in place, 23 | * make sure to rename it first. 24 | */ 25 | 26 | #ifndef TCMENU_SERIALTRANSPORT_H_ 27 | #define TCMENU_SERIALTRANSPORT_H_ 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | namespace tcremote { 36 | 37 | /** 38 | * Serial transport is an implementation of TagValueTransport that works over a serial port 39 | */ 40 | class SerialTagValueTransport : public TagValueTransport { 41 | private: 42 | Stream* serialPort; 43 | public: 44 | explicit SerialTagValueTransport(Stream* thePort); 45 | ~SerialTagValueTransport() override = default; 46 | 47 | void flush() override {serialPort->flush();} 48 | int writeChar(char data) override; 49 | int writeStr(const char* data) override; 50 | 51 | uint8_t readByte() override { return serialPort->read(); } 52 | bool readAvailable() override { return serialPort->available(); } 53 | bool available() override { return serialPort->availableForWrite() != 0;} 54 | bool connected() override { return true;} 55 | 56 | void close() override; 57 | }; 58 | } 59 | 60 | #ifndef TC_MANUAL_NAMESPACING 61 | using namespace tcremote; 62 | #endif // TC_MANUAL_NAMESPACING 63 | 64 | #endif /* TCMENU_SERIALTRANSPORT_H_ */ 65 | #endif 66 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_SimhubConnector.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Simhub Remote Control 4 | */ 5 | #include 6 | #ifdef HELIO_USE_GUI 7 | 8 | /* 9 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 10 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 11 | */ 12 | 13 | /** 14 | * SimHub Connector that connects to simhub using the serial port and changes menu items based on simhub update. 15 | * This class should not be directly edited, it will be replaced each time the project is built. 16 | * If you want to edit this file in place, make sure to rename it first. 17 | */ 18 | 19 | #include "tcMenu_Remote_SimhubConnector.h" 20 | #include 21 | #include 22 | #include 23 | 24 | SimhubConnector::SimhubConnector(SerPortName* serialPort, uint16_t statusMenuId) : lineBuffer {} { 25 | this->serialPort = serialPort; 26 | statusMenuItem = (statusMenuId != INVALID_MENU_ID) ? reinterpret_cast(getMenuItemById(statusMenuId)) : nullptr; 27 | this->linePosition = 0; 28 | changeStatus(false); 29 | } 30 | 31 | void SimhubConnector::tick() { 32 | while(serialPort && serialPort->available()) { 33 | if(linePosition >= MAX_LINE_WIDTH) { 34 | lineBuffer[MAX_LINE_WIDTH - 1] = 0; 35 | serdebugF2("Error occurred during Rx ", lineBuffer); 36 | linePosition = 0; 37 | } 38 | 39 | lineBuffer[linePosition] = (char)serialPort->read(); 40 | 41 | if(lineBuffer[linePosition] == '\n') { 42 | lineBuffer[linePosition] = 0; 43 | serdebugF2("RX ", lineBuffer); 44 | // we have received a command from simhub 45 | processCommandFromSimhub(); 46 | linePosition=0; 47 | } 48 | else linePosition++; 49 | } 50 | 51 | } 52 | 53 | void SimhubConnector::processCommandFromSimhub() { 54 | if(isDigit(lineBuffer[0])) { 55 | processTcMenuCommand(); 56 | } 57 | else if(strcmp(lineBuffer, "simhubStart") == 0) { 58 | changeStatus(true); 59 | 60 | } 61 | else if(strcmp(lineBuffer, "simhubEnd") == 0) { 62 | changeStatus(false); 63 | } 64 | } 65 | 66 | void SimhubConnector::changeStatus(bool connected) { 67 | this->connected = connected; 68 | if(statusMenuItem != nullptr) { 69 | statusMenuItem->setBoolean(connected); 70 | } 71 | } 72 | 73 | void SimhubConnector::processTcMenuCommand() { 74 | int i = 0; 75 | char sz[6]; 76 | while(isDigit(lineBuffer[i]) && i < 5) { 77 | sz[i] = lineBuffer[i]; 78 | i++; 79 | }; 80 | sz[i] = 0; 81 | int menuId = atoi(sz); 82 | while(lineBuffer[i] != '=') i++; 83 | char* value = &lineBuffer[i + 1]; 84 | 85 | serdebugF4("updch, item, value", sz, menuId, value); 86 | 87 | MenuItem* menuItem = getMenuItemById(menuId); 88 | if(menuItem->getMenuType() == MENUTYPE_INT_VALUE || menuItem->getMenuType() == MENUTYPE_ENUM_VALUE || menuItem->getMenuType() == MENUTYPE_BOOLEAN_VALUE) { 89 | auto* valItem = reinterpret_cast(menuItem); 90 | valItem->setCurrentValue(atoi(value)); 91 | } 92 | else if(menuItem->getMenuType() == MENUTYPE_TEXT_VALUE) { 93 | auto* txtItem = reinterpret_cast(menuItem); 94 | txtItem->setTextValue(value); 95 | } 96 | } 97 | 98 | void SimHubRemoteConnection::init(int remoteNumber, const ConnectorLocalInfo &info) { 99 | /* currently does nothing, simhub connector presently only receives information */ 100 | } 101 | 102 | void SimHubRemoteConnection::tick() { 103 | connector.tick(); 104 | } 105 | 106 | bool SimHubRemoteConnection::connected() { 107 | return connector.getStatus(); 108 | } 109 | 110 | const char pgmSimHubConnectionText[] PROGMEM = "SimHub: "; 111 | 112 | void SimHubRemoteConnection::copyConnectionStatus(char *buffer, int bufferSize) { 113 | if(bufferSize < 11) { 114 | buffer[0] = 'S'; buffer[1] = 'H'; 115 | buffer[2] = ':'; buffer[3] = connector.getStatus() ? 'Y' : 'N'; 116 | buffer[4] = 0; 117 | } else { 118 | safeProgCpy(buffer, pgmSimHubConnectionText, bufferSize); 119 | appendChar(buffer, connector.getStatus() ? 'Y' : 'N', bufferSize); 120 | } 121 | } 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_SimhubConnector.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Simhub Remote Control 4 | */ 5 | #include 6 | #ifdef HELIO_USE_GUI 7 | #include "HelioduinoUI.h" 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 16 | */ 17 | 18 | /** 19 | * @file tcMenu_Remote_SimhubConnector.h 20 | * 21 | * SimHub Connector that connects to simhub using the serial port and changes menu items based on simhub update. 22 | * This class should not be directly edited, it will be replaced each time the project is built. 23 | * If you want to edit this file in place, make sure to rename it first. 24 | */ 25 | 26 | #ifndef TCLIBRARYDEV_SIMHUBCONNECTOR_H 27 | #define TCLIBRARYDEV_SIMHUBCONNECTOR_H 28 | 29 | /** 30 | * this is the maximum number of chars on a line 31 | */ 32 | #define MAX_LINE_WIDTH 32 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #if defined(ESP8266) || defined(ESP32) 40 | # define SerPortName HardwareSerial 41 | #else 42 | # define SerPortName Stream 43 | #endif 44 | 45 | namespace tcremote { 46 | 47 | class SimhubConnector { 48 | private: 49 | SerPortName* serialPort; 50 | BooleanMenuItem* statusMenuItem; 51 | char lineBuffer[MAX_LINE_WIDTH]; 52 | int linePosition; 53 | bool connected; 54 | public: 55 | SimhubConnector(SerPortName* serialPort, menuid_t statusMenuId); 56 | void tick(); 57 | bool getStatus() { return connected; } 58 | private: 59 | void processCommandFromSimhub(); 60 | void processTcMenuCommand(); 61 | void changeStatus(bool b); 62 | }; 63 | 64 | 65 | class SimHubRemoteConnection : public BaseRemoteServerConnection { 66 | private: 67 | SimhubConnector connector; 68 | NoInitialisationNeeded noInitialisation; 69 | public: 70 | SimHubRemoteConnection(SerPortName* serialPort, menuid_t statusMenuId) 71 | : BaseRemoteServerConnection(noInitialisation, SIMHUB_CONNECTOR), connector(serialPort, statusMenuId) { 72 | } 73 | 74 | void init(int remoteNumber, const ConnectorLocalInfo &info) override; 75 | 76 | void tick() override; 77 | 78 | bool connected() override; 79 | 80 | void copyConnectionStatus(char *buffer, int bufferSize) override; 81 | }; 82 | } 83 | 84 | #ifndef TC_MANUAL_NAMESPACING 85 | using namespace tcremote; 86 | #endif // TC_MANUAL_NAMESPACING 87 | 88 | #endif //TCLIBRARYDEV_SIMHUBCONNECTOR_H 89 | #endif 90 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_WiFiTransport.cpp: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu WiFi Remote Control 4 | */ 5 | #include 6 | #if defined(HELIO_USE_WIFI) && defined(HELIO_USE_GUI) 7 | 8 | /* 9 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 10 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 11 | */ 12 | 13 | /** 14 | * WiFi remote capability plugin. This file is a plugin file and should not be directly edited, 15 | * it will be replaced each time the project is built. If you want to edit this file in place, 16 | * make sure to rename it first. 17 | */ 18 | 19 | #include "tcMenu_Remote_WiFiTransport.h" 20 | 21 | using namespace tcremote; 22 | 23 | #if WIFI_BUFFER_SIZE > 0 // we need buffering when dealing with WiFi2 24 | 25 | bool WiFiTagValTransport::available() { 26 | return client && client.connected(); 27 | } 28 | 29 | bool WiFiTagValTransport::connected() { 30 | return client && client.connected(); 31 | } 32 | 33 | void WiFiTagValTransport::flush() { 34 | if(!client || writeBufferPos == 0) return; 35 | 36 | if((int)client.write(writeBuffer, writeBufferPos) == writeBufferPos) { 37 | serdebugF2("Buffer written ", writeBufferPos); 38 | writeBufferPos = 0; 39 | client.flush(); 40 | } 41 | else { 42 | writeBufferPos = 0; 43 | close(); 44 | } 45 | } 46 | 47 | int WiFiTagValTransport::fillReadBuffer(uint8_t* dataBuffer, int maxData) { 48 | if(client && client.connected() && client.available()) { 49 | auto amt = client.read(dataBuffer, maxData); 50 | if(amt <= 0) { 51 | close(); 52 | return 0; 53 | } 54 | serdebugF2("read to buffer ", amt); 55 | return amt; 56 | } 57 | return 0; 58 | } 59 | 60 | void WiFiTagValTransport::close() { 61 | serdebugF("socket close"); 62 | BaseBufferedRemoteTransport::close(); 63 | client.stop(); 64 | } 65 | 66 | #else // unbuffed client - requires library to support Nagle algorythm. 67 | 68 | bool WiFiTagValTransport::available() { 69 | return client && client.connected(); 70 | } 71 | 72 | bool WiFiTagValTransport::connected() { 73 | return client && client.connected(); 74 | } 75 | 76 | int WiFiTagValTransport::writeChar(char data) { 77 | // only uncomment below for worst case debugging.. 78 | // serdebug2("writing ", data); 79 | return client.write(data); 80 | } 81 | 82 | int WiFiTagValTransport::writeStr(const char* data) { 83 | // only uncomment below for worst case debugging.. 84 | // serdebug2("writing ", data); 85 | return client.write(data); 86 | } 87 | 88 | void WiFiTagValTransport::flush() { 89 | if(client) client.flush(); 90 | } 91 | 92 | uint8_t WiFiTagValTransport::readByte() { 93 | return client.read(); 94 | } 95 | 96 | bool WiFiTagValTransport::readAvailable() { 97 | return client && client.connected() && client.available(); 98 | } 99 | 100 | void WiFiTagValTransport::close() { 101 | serdebugF("socket close"); 102 | client.stop(); 103 | currentField.msgType = UNKNOWN_MSG_TYPE; 104 | currentField.fieldType = FVAL_PROCESSING_AWAITINGMSG; 105 | } 106 | 107 | #endif 108 | 109 | bool WiFiInitialisation::attemptInitialisation() { 110 | #ifdef ARDUINO_ARCH_STM32 111 | // we'll keep checking if the link is up before trying to initialise further 112 | if(WiFi.status() != WL_CONNECTED) return false; 113 | #endif 114 | serdebugF("Initialising server "); 115 | this->server->begin(); 116 | initialised = true; 117 | return initialised; 118 | } 119 | 120 | bool WiFiInitialisation::attemptNewConnection(BaseRemoteServerConnection *remoteServerConnection) { 121 | auto client = server->available(); 122 | if(client) { 123 | serdebugF("Client found"); 124 | auto* tvCon = reinterpret_cast(remoteServerConnection); 125 | reinterpret_cast(tvCon->transport())->setClient(client); 126 | return true; 127 | } 128 | return false; 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Remote_WiFiTransport.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu WiFi Remote Control 4 | */ 5 | #include 6 | #if defined(HELIO_USE_WIFI) && defined(HELIO_USE_GUI) 7 | #include "HelioduinoUI.h" 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 16 | * - Derived from EthernetTransport 17 | */ 18 | 19 | /** 20 | * @file tcMenu_Remote_WiFiTransport.h 21 | * 22 | * WiFi remote capability plugin. This file is a plugin file and should not be directly edited, 23 | * it will be replaced each time the project is built. If you want to edit this file in place, 24 | * make sure to rename it first. 25 | */ 26 | 27 | #ifndef TCMENU_WIFITRANSPORT_H_ 28 | #define TCMENU_WIFITRANSPORT_H_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifndef WIFI_BUFFER_SIZE 36 | #define WIFI_BUFFER_SIZE 64 37 | #endif 38 | 39 | #if WIFI_BUFFER_SIZE > 0 40 | #include 41 | #endif 42 | 43 | namespace tcremote { 44 | 45 | #if WIFI_BUFFER_SIZE > 0 46 | 47 | /** 48 | * An implementation of TagValueTransport that is able to read and write via a buffer to sockets. 49 | */ 50 | class WiFiTagValTransport : public tcremote::BaseBufferedRemoteTransport { 51 | private: 52 | WiFiClient client; 53 | public: 54 | WiFiTagValTransport() : BaseBufferedRemoteTransport(BUFFER_MESSAGES_TILL_FULL, WIFI_BUFFER_SIZE, MAX_VALUE_LEN) { } 55 | ~WiFiTagValTransport() override = default; 56 | void setClient(WiFiClient cl) { this->client = cl; } 57 | 58 | int fillReadBuffer(uint8_t* data, int maxSize) override; 59 | void flush() override; 60 | bool available() override; 61 | bool connected() override; 62 | void close() override; 63 | }; 64 | 65 | #else // wifi buffering not needed 66 | 67 | /** 68 | * An implementation of TagValueTransport that is able to read and write using sockets. 69 | */ 70 | class WiFiTagValTransport : public TagValueTransport { 71 | private: 72 | WiFiClient client; 73 | public: 74 | WiFiTagValTransport() : TagValueTransport(TagValueTransportType::TVAL_UNBUFFERED) {}; 75 | ~WiFiTagValTransport() override = default; 76 | void setClient(WiFiClient client) { this->client = client; } 77 | 78 | int writeChar(char data) override ; 79 | int writeStr(const char* data) override; 80 | void flush() override; 81 | bool available() override; 82 | bool connected() override; 83 | uint8_t readByte() override; 84 | bool readAvailable() override; 85 | void close() override; 86 | }; 87 | 88 | #endif // wifi buffering check 89 | 90 | /** 91 | * This class provides the initialisation and connection generation logic for wifi connections. 92 | */ 93 | class WiFiInitialisation : public DeviceInitialisation { 94 | private: 95 | WiFiServer *server; 96 | public: 97 | explicit WiFiInitialisation(WiFiServer* server) : server(server) {} 98 | 99 | bool attemptInitialisation() override; 100 | 101 | bool attemptNewConnection(BaseRemoteServerConnection *transport) override; 102 | }; 103 | 104 | /** 105 | * This function converts from a RSSI (Radio Strength indicator) 106 | * measurement into a series of icons (of the ones we have defined 107 | * in the stock icons. The input is the RSSI figure in dB as an 108 | * integer. 109 | * @param strength the signal strength (usually negative) as an int 110 | * @return a state that can be used with the standard wifi TitleWidget 111 | */ 112 | int fromWiFiRSSITo4StateIndicator(int strength); 113 | 114 | } // namespace tcremote 115 | 116 | #ifndef TC_MANUAL_NAMESPACING 117 | using namespace tcremote; 118 | #endif // TC_MANUAL_NAMESPACING 119 | 120 | #endif /* TCMENU_WIFITRANSPORT_H_ */ 121 | #endif 122 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_CoolBlueModern.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Cool Blue Modern/ML Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | /** 20 | * Cool blue modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. 21 | * This file will not be updated by the designer, you can edit. 22 | */ 23 | #ifndef COOL_BLUE_MODERN_THEME 24 | #define COOL_BLUE_MODERN_THEME 25 | 26 | #include 27 | 28 | #define ACTION_BORDER_WIDTH 0 29 | 30 | inline void installCoolBlueModernTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 31 | const color_t coolBlueMdrnTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; 32 | const color_t coolBlueMdrnItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; 33 | const color_t coolBlueMdrnActionPalette[] = {RGB(255, 255, 255), RGB(0,45,120), RGB(20,133,255), RGB(31,100,178)}; 34 | 35 | // here we get a refrerence to the drawable and then set the dimensions. 36 | auto* rootDrawable = bgr.getDeviceDrawable(); 37 | bgr.setDisplayDimensions(rootDrawable->getDisplayDimensions().x, rootDrawable->getDisplayDimensions().y); 38 | 39 | // we need a reference to the factory object that we will use to configure the drawing. 40 | auto& factory = bgr.getGraphicsPropertiesFactory(); 41 | 42 | // change the selected colours. 43 | factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); 44 | 45 | // for this theme we use the same size padding for each case, we need touchable items. We calculate the height too 46 | MenuPadding allPadding(4, 3, 4, 3); 47 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, allPadding); 48 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, allPadding); 49 | 50 | // now we configure the drawing for each item type 51 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueMdrnTitlePalette, allPadding, titleFont.fontData, titleFont.fontMag, 3, titleHeight, 52 | GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(0)); 53 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueMdrnItemPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, 54 | GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); 55 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueMdrnActionPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, 56 | GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(ACTION_BORDER_WIDTH)); 57 | 58 | // and lastly, whenever changing the configuration, we must refresh. 59 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 60 | } 61 | 62 | #endif //COOL_BLUE_MODERN_THEME 63 | #endif 64 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_CoolBlueTraditional.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Cool Blue Traditional/SM Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | #ifndef COOL_BLUE_TRADITIONAL_THEME 20 | #define COOL_BLUE_TRADITIONAL_THEME 21 | 22 | inline void installCoolBlueTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 23 | // tcMenu drawing properties take a 4 color palette for items, titles and actions. 24 | // this renderer shares the color configuration for items and actions. 25 | const color_t coolBlueTitlePalette[] = {RGB(0,0,0), RGB(20,132,255), RGB(192,192,192), RGB(64, 64, 64)}; 26 | const color_t coolBlueItemPalette[] = {RGB(255, 255, 255), RGB(0,64,135), RGB(20,133,255), RGB(31,100,178)}; 27 | 28 | // first we keep a reference to the screen size, and set the dimensions on the renderer. 29 | auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; 30 | auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; 31 | bgr.setDisplayDimensions(width, height); 32 | 33 | // get hold of the item display factory that holds the drawing configuration. 34 | auto& factory = bgr.getGraphicsPropertiesFactory(); 35 | 36 | // when an item is active, it will show in these colours instead of the default. 37 | factory.setSelectedColors(RGB(31, 88, 100), RGB(255, 255, 255)); 38 | 39 | // here we calculate the item padding and row heights based on the resolution of the display 40 | bool medResOrBetter = width > 160; 41 | MenuPadding titlePadding(medResOrBetter ? 4 : 2); 42 | MenuPadding itemPadding(medResOrBetter ? 2 : 1); 43 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); 44 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); 45 | 46 | // we set the editing and selected icons here based on the row height. 47 | if(needEditingIcons && itemHeight > 12) { 48 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); 49 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); 50 | } 51 | else if(needEditingIcons) { 52 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); 53 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); 54 | } 55 | 56 | // we tell the library how to draw titles, items and actions by default. 57 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, coolBlueTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, 58 | medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); 59 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, 60 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); 61 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, coolBlueItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, 62 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); 63 | 64 | // after adjusting the drawing configuration, we must always refresh the cache. 65 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 66 | } 67 | 68 | #endif //COOL_BLUE_TRADITIONAL_THEME 69 | #endif 70 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_DarkModeModern.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Dark Mode Modern/ML Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | /** 20 | * Dark mode modern theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. 21 | * This file will not be updated by the designer, you can edit. 22 | */ 23 | #ifndef DARK_MODE_MODERN_THEME 24 | #define DARK_MODE_MODERN_THEME 25 | 26 | #include 27 | 28 | #define ACTION_BORDER_WIDTH 0 29 | 30 | inline void installDarkModeModernTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 31 | const color_t darkModeMdrnTitlePalette[] = {RGB(255,255,255), RGB(43,43,43), RGB(192,192,192), RGB(0,133,255)}; 32 | const color_t darkModeMdrnItemPalette[] = {RGB(255, 255, 255), RGB(0,0,0), RGB(43,43,43), RGB(65,65,65)}; 33 | const color_t darkModeMdrnActionPalette[] = {RGB(255, 255, 255), RGB(35,35,35), RGB(20,45,110), RGB(192,192,192)}; 34 | 35 | // here we get a reference to the drawable and then set the dimensions. 36 | auto* rootDrawable = bgr.getDeviceDrawable(); 37 | bgr.setDisplayDimensions(rootDrawable->getDisplayDimensions().x, rootDrawable->getDisplayDimensions().y); 38 | 39 | // we need a reference to the factory object that we will use to configure the drawing. 40 | auto& factory = bgr.getGraphicsPropertiesFactory(); 41 | 42 | // change the selected colours. 43 | factory.setSelectedColors(RGB(46, 66, 161), RGB(255, 255, 255)); 44 | 45 | // for this theme we use the same size padding for each case, we need touchable items. We calculate the height too 46 | MenuPadding allPadding(4, 3, 4, 3); 47 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, allPadding); 48 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, allPadding); 49 | 50 | // now we configure the drawing for each item type 51 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, darkModeMdrnTitlePalette, allPadding, titleFont.fontData, titleFont.fontMag, 3, titleHeight, 52 | GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(0)); 53 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, darkModeMdrnItemPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, 54 | GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); 55 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, darkModeMdrnActionPalette, allPadding, itemFont.fontData, itemFont.fontMag, 2, itemHeight, 56 | GridPosition::JUSTIFY_CENTER_WITH_VALUE, MenuBorder(ACTION_BORDER_WIDTH)); 57 | 58 | // and lastly, whenever changing the configuration, we must refresh. 59 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 60 | } 61 | 62 | #endif //DARK_MODE_MODERN_THEME 63 | #endif 64 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_DarkModeTraditional.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Dark Mode Traditional/SM Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | /** 20 | * Dark mode traditional theme by TheCodersCorner.com. This is part of the standard themes shipped with TcMenu. 21 | * This file will not be updated by the designer, you can edit. 22 | */ 23 | 24 | #ifndef DARK_MODE_TRADITIONAL_THEME 25 | #define DARK_MODE_TRADITIONAL_THEME 26 | 27 | inline void installDarkModeTraditionalTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 28 | // tcMenu drawing properties take a 4 color palette for items, titles and actions. 29 | // this renderer shares the color configuration for items and actions. 30 | const color_t darkModeTitlePalette[] = {RGB(255,255,255), RGB(43,43,43), RGB(192,192,192), RGB(0,133,255)}; 31 | const color_t darkModeItemPalette[] = {RGB(255, 255, 255), RGB(0,0,0), RGB(43,43,43), RGB(65,65,65)}; 32 | const color_t darkModeActionPalette[] = {RGB(255, 255, 255), RGB(35,35,35), RGB(20,45,110), RGB(192,192,192)}; 33 | 34 | // first we keep a reference to the screen size, and set the dimensions on the renderer. 35 | auto width = bgr.getDeviceDrawable()->getDisplayDimensions().x; 36 | auto height = bgr.getDeviceDrawable()->getDisplayDimensions().y; 37 | bgr.setDisplayDimensions(width, height); 38 | 39 | // get hold of the item display factory that holds the drawing configuration. 40 | auto& factory = bgr.getGraphicsPropertiesFactory(); 41 | 42 | // when an item is active, it will show in these colours instead of the default. 43 | factory.setSelectedColors(RGB(46, 66, 161), RGB(255, 255, 255)); 44 | 45 | // here we calculate the item padding and row heights based on the resolution of the display 46 | bool medResOrBetter = width > 160; 47 | MenuPadding titlePadding(medResOrBetter ? 4 : 2); 48 | MenuPadding itemPadding(medResOrBetter ? 2 : 1); 49 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); 50 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); 51 | 52 | // we set the editing and selected icons here based on the row height. 53 | if(needEditingIcons && itemHeight > 12) { 54 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defEditingIcon)); 55 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(16, 12),DrawableIcon::ICON_XBITMAP, defActiveIcon)); 56 | } 57 | else if(needEditingIcons) { 58 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); 59 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); 60 | } 61 | 62 | // we tell the library how to draw titles, items and actions by default. 63 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, darkModeTitlePalette, titlePadding, titleFont.fontData, titleFont.fontMag, 64 | medResOrBetter ? 3 : 1, titleHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder()); 65 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, darkModeItemPalette, itemPadding, itemFont.fontData, itemFont.fontMag, 66 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); 67 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, darkModeActionPalette, itemPadding, itemFont.fontData, itemFont.fontMag, 68 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT, MenuBorder()); 69 | 70 | // after adjusting the drawing configuration, we must always refresh the cache. 71 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 72 | } 73 | 74 | #endif //DARK_MODE_TRADITIONAL_THEME 75 | #endif 76 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_MonoBordered.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Mono Bordered Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | #ifndef TCMENU_THEME_MONO_BORDER 20 | #define TCMENU_THEME_MONO_BORDER 21 | 22 | #define TITLE_BORDER_THICKNESS 2 23 | #define TITLE_SPACING 2 24 | 25 | inline void installMonoBorderedTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 26 | color_t defaultItemPaletteMono[] = {WHITE, BLACK, WHITE, WHITE}; 27 | 28 | bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); 29 | auto& factory = bgr.getGraphicsPropertiesFactory(); 30 | 31 | factory.setSelectedColors(0, 1); 32 | 33 | MenuPadding titlePadding(1); 34 | MenuPadding itemPadding(1); 35 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); 36 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); 37 | 38 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); 39 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); 40 | 41 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultItemPaletteMono, titlePadding, titleFont.fontData, titleFont.fontMag, 42 | TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, 43 | MenuBorder(0, 0, TITLE_BORDER_THICKNESS, 0)); 44 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, 45 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); 46 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMono, itemPadding, itemFont.fontData, itemFont.fontMag, 47 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); 48 | 49 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 50 | } 51 | 52 | #endif //TCMENU_THEME_MONO_BORDER 53 | #endif 54 | -------------------------------------------------------------------------------- /src/shared/tcMenu_Theme_MonoInverse.h: -------------------------------------------------------------------------------- 1 | /* Helioduino: Simple automation controller for solar tracking systems. 2 | Copyright (C) 2023 NachtRaveVL 3 | tcMenu Mono Inverse Theme 4 | */ 5 | 6 | #include 7 | #ifdef HELIO_USE_GUI 8 | 9 | /* 10 | * Copyright (c) 2018 https://www.thecoderscorner.com (Dave Cherry). 11 | * This product is licensed under an Apache license, see the LICENSE file in the top-level directory. 12 | */ 13 | 14 | /* Changelist: 15 | * - Variable name standardizations and keeping things in function scope. 16 | * - Enclosed inside of #ifdef & reorg'ed for general inclusion 17 | */ 18 | 19 | #ifndef TCMENU_THEME_MONO_INVERSE 20 | #define TCMENU_THEME_MONO_INVERSE 21 | 22 | #define TITLE_PADDING 2 23 | #define TITLE_SPACING 2 24 | 25 | inline void installMonoInverseTitleTheme(GraphicsDeviceRenderer& bgr, const MenuFontDef& itemFont, const MenuFontDef& titleFont, bool needEditingIcons) { 26 | color_t defaultItemPaletteMonoInv[] = {1, 0, 1, 1}; 27 | color_t defaultTitlePaletteMonoInv[] = {0, 1, 0, 0}; 28 | 29 | bgr.setDisplayDimensions(bgr.getDeviceDrawable()->getDisplayDimensions().x, bgr.getDeviceDrawable()->getDisplayDimensions().y); 30 | auto& factory = bgr.getGraphicsPropertiesFactory(); 31 | 32 | factory.setSelectedColors(0, 2); 33 | 34 | MenuPadding titlePadding(TITLE_PADDING); 35 | MenuPadding itemPadding(1); 36 | int titleHeight = bgr.heightForFontPadding(titleFont.fontData, titleFont.fontMag, titlePadding); 37 | int itemHeight = bgr.heightForFontPadding(itemFont.fontData, itemFont.fontMag, itemPadding); 38 | 39 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_EDIT_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResEditingIcon)); 40 | factory.addImageToCache(DrawableIcon(SPECIAL_ID_ACTIVE_ICON, Coord(8, 6),DrawableIcon::ICON_XBITMAP, loResActiveIcon)); 41 | 42 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_TITLE, defaultTitlePaletteMonoInv, titlePadding, titleFont.fontData, titleFont.fontMag, 43 | TITLE_SPACING, titleHeight + 1, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); 44 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ITEM, defaultItemPaletteMonoInv, itemPadding, itemFont.fontData, itemFont.fontMag, 45 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_VALUE_RIGHT , MenuBorder(0)); 46 | factory.setDrawingPropertiesDefault(ItemDisplayProperties::COMPTYPE_ACTION, defaultItemPaletteMonoInv, itemPadding, itemFont.fontData, itemFont.fontMag, 47 | 1, itemHeight, GridPosition::JUSTIFY_TITLE_LEFT_WITH_VALUE, MenuBorder(0)); 48 | 49 | tcgfx::ConfigurableItemDisplayPropertiesFactory::refreshCache(); 50 | } 51 | 52 | #endif //TCMENU_THEME_MONO_INVERSE 53 | #endif 54 | --------------------------------------------------------------------------------