* Optimize Sun data calculation * Remove not required enum * Split config struct into different sub structs * Feature: Allow configuration of LWT QoS * Made resetreason methods static * Feature: Implement offset cache for "YieldDay" Thanks to @broth-itk for the idea! Fix: #1258 #1397 * Add Esp32-Stick-PoE-A * remove broken LilyGO_T_ETH_POE config, use device profile instead * Feature: High resolution Icon and PWA (Progressive Web App) functionality Fix: #1289 * webapp: Update dependencies * Initialize TaskScheduler * Migrate SunPosition to TaskScheduler * Migrate Datastore to TaskScheduler * Migrate MqttHandleInverterTotal to TaskSchedule * Migrate MqttHandleHass to TaskScheduler * Migrate MqttHandleDtu to TaskScheduler * Migrate MqttHandleInverter to TaskScheduler * Migrate LedSingle to TaskScheduler * Migrate NetworkSettings to TaskScheduler * Migrate InverterSettings to TaskScheduler * Migrate MessageOutput to TaskScheduler * Migrate Display_Graphic to TaskScheduler * Migrate WebApi to TaskScheduler * Split InverterSettings into multiple tasks * Calculate SunPosition only every 5 seconds * Split LedSingle into multiple tasks * Upgrade espMqttClient from 1.4.5 to 1.5.0 * Doc: Correct amount of MPP-Tracker * Added HMT-1600-4T and HMT-1800-4T to DevInfoParser Fix #1524 * Adjusted inverter names for HMS-1600/1800/2000-4T * Add channel count to description of detected inverter type (DevInfoParser) * Adjust device web api endpoint for dynamic led count * Feature: Added ability to change the brightness of the LEDs Based on the idea of @moritzlerch with several modifications like pwmTable and structure * webapp: Update dependencies * Update olikraus/U8g2 from 2.35.7 to 2.35.8 * Remove not required onWebsocketEvent * Remove code nesting * Introduce several const statements * Remove not required AsyncEventSource * Doc: Added byte specification to each command * Feature: Added basic Grid Profile parser which shows the used profile and version Other values are still outstanding. * Optimize AlarmLogParser to save memory * Add libfrozen to project to create constexpr maps * Feature: First version of GridProfile Parser which shows all values contained in the profile. * webapp: Update dependencies * Apply better variable names * Remove not required casts * Add additional compiler flags to prevent errors * Add const statement to several variables * Replace NULL by nullptr * Update bblanchon/ArduinoJson from 6.21.3 to 6.21.4 * Add const keyword to method parameters * Add const keyword to methods * Use references instead of pointers whenver possible * Adjust member variable names in MqttSettings * Adjust member variable names in NetworkSettings * webapp: Update timezone database to latest version * webapp: Beautify and unify form footers * Feature: Allow setting of an inverter limit of 0% and 0W Thanks to @madmartin in #1270 * Feature: Allow links in device profiles These links will be shown on the hardware settings page. * Doc: Added hint regarding HMS-xxxx-xT-NA inverters * Feature: Added DeviceProfile for CASmo-DTU Based on #1565 * Upgrade actions/upload-artifact from v3 to v4 * Upgrade actions/download-artifact from v3 to v4 * webapp: add app.js.gz * Gridprofileparser: Added latest known values Thanks to @stefan123t and @noone2k * webapp: Fix lint errors * Feature: Add DTU to Home Assistant Auto Discovery This is based on PR 1365 from @CFenner with several fixes and optimizations * Fix: Remove debug output as it floods the console * Fix: Gridprofileparser: Add additional error handling if profile is unknown * webapp: add app.js.gz * Fix: Offset cache for "YieldDay" did not work correctly * webapp: update dependencies * webapp: add app.js.gz * Fix: yarn.lock was outdated * Fix: yarn build error * Fix: Reset Yield day correction in combination with Zero Yield Day on Midnight lead to wrong values. * Fix: Allow negative values in GridProfileParser * Correct variable name * Fix #1579: Static IP in Ethernet mode did not work correctly * Feature: Added diagram to display This is based on the idea of @Henrik-Ingenieur and was discussed in #1504 * webapp: update dependencies * webapp: add app.js.gz --------- Co-authored-by: Thomas Basler <thomas@familie-basler.net> Co-authored-by: Pierre Kancir <pierre.kancir.emn@gmail.com>
161 lines
4.2 KiB
C++
161 lines
4.2 KiB
C++
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2023 Thomas Basler and others
|
|
*/
|
|
#include "Led_Single.h"
|
|
#include "Configuration.h"
|
|
#include "Datastore.h"
|
|
#include "MqttSettings.h"
|
|
#include "NetworkSettings.h"
|
|
#include "PinMapping.h"
|
|
#include <Hoymiles.h>
|
|
|
|
LedSingleClass LedSingle;
|
|
|
|
/*
|
|
The table is calculated using the following formula
|
|
(See https://www.mikrocontroller.net/articles/LED-Fading)
|
|
a = Step count: 101 --> 0 - 100
|
|
b = PWM resolution: 256: 0 - 255
|
|
y = Calculated value of index x:
|
|
y = 0 if x = 0
|
|
y = pow(2, log2(b-1) * (x+1) / a) if x > 0
|
|
*/
|
|
const uint8_t pwmTable[] = {
|
|
0,
|
|
1, 1, 1, 1, 1, 1, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
|
|
3, 4, 4, 4, 4, 4, 5, 5, 5, 5,
|
|
6, 6, 6, 7, 7, 8, 8, 8, 9, 9,
|
|
10, 11, 11, 12, 12, 13, 14, 15, 16, 16,
|
|
17, 18, 19, 20, 22, 23, 24, 25, 27, 28,
|
|
30, 32, 33, 35, 37, 39, 42, 44, 47, 49,
|
|
52, 55, 58, 61, 65, 68, 72, 76, 81, 85,
|
|
90, 95, 100, 106, 112, 118, 125, 132, 139, 147,
|
|
156, 164, 174, 183, 194, 205, 216, 228, 241, 255
|
|
};
|
|
|
|
#define LED_OFF 0
|
|
|
|
LedSingleClass::LedSingleClass()
|
|
{
|
|
}
|
|
|
|
void LedSingleClass::init(Scheduler& scheduler)
|
|
{
|
|
bool ledActive = false;
|
|
|
|
_blinkTimeout.set(500);
|
|
turnAllOn();
|
|
|
|
const auto& pin = PinMapping.get();
|
|
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
|
|
|
if (pin.led[i] >= 0) {
|
|
pinMode(pin.led[i], OUTPUT);
|
|
setLed(i, false);
|
|
ledActive = true;
|
|
}
|
|
|
|
_ledMode[i] = LedState_t::Off;
|
|
}
|
|
|
|
if (ledActive) {
|
|
scheduler.addTask(_outputTask);
|
|
_outputTask.setCallback(std::bind(&LedSingleClass::outputLoop, this));
|
|
_outputTask.setIterations(TASK_FOREVER);
|
|
_outputTask.enable();
|
|
|
|
scheduler.addTask(_setTask);
|
|
_setTask.setCallback(std::bind(&LedSingleClass::setLoop, this));
|
|
_setTask.setInterval(LEDSINGLE_UPDATE_INTERVAL * TASK_MILLISECOND);
|
|
_setTask.setIterations(TASK_FOREVER);
|
|
_setTask.enable();
|
|
}
|
|
}
|
|
|
|
void LedSingleClass::setLoop()
|
|
{
|
|
if (_allMode == LedState_t::On) {
|
|
const CONFIG_T& config = Configuration.get();
|
|
|
|
// Update network status
|
|
_ledMode[0] = LedState_t::Off;
|
|
|
|
if (NetworkSettings.isConnected()) {
|
|
_ledMode[0] = LedState_t::Blink;
|
|
}
|
|
|
|
struct tm timeinfo;
|
|
if (getLocalTime(&timeinfo, 5) && (!config.Mqtt.Enabled || (config.Mqtt.Enabled && MqttSettings.getConnected()))) {
|
|
_ledMode[0] = LedState_t::On;
|
|
}
|
|
|
|
// Update inverter status
|
|
_ledMode[1] = LedState_t::Off;
|
|
if (Hoymiles.getNumInverters() && Datastore.getIsAtLeastOnePollEnabled()) {
|
|
// set LED status
|
|
if (Datastore.getIsAllEnabledReachable() && Datastore.getIsAllEnabledProducing()) {
|
|
_ledMode[1] = LedState_t::On;
|
|
}
|
|
if (Datastore.getIsAllEnabledReachable() && !Datastore.getIsAllEnabledProducing()) {
|
|
_ledMode[1] = LedState_t::Blink;
|
|
}
|
|
}
|
|
|
|
} else if (_allMode == LedState_t::Off) {
|
|
_ledMode[0] = LedState_t::Off;
|
|
_ledMode[1] = LedState_t::Off;
|
|
}
|
|
}
|
|
|
|
void LedSingleClass::outputLoop()
|
|
{
|
|
for (uint8_t i = 0; i < PINMAPPING_LED_COUNT; i++) {
|
|
switch (_ledMode[i]) {
|
|
case LedState_t::Off:
|
|
setLed(i, false);
|
|
break;
|
|
case LedState_t::On:
|
|
setLed(i, true);
|
|
break;
|
|
case LedState_t::Blink:
|
|
if (_blinkTimeout.occured()) {
|
|
setLed(i, !_ledStateCurrent[i]);
|
|
_blinkTimeout.reset();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LedSingleClass::setLed(const uint8_t ledNo, const bool ledState)
|
|
{
|
|
const auto& pin = PinMapping.get();
|
|
const auto& config = Configuration.get();
|
|
|
|
if (pin.led[ledNo] < 0) {
|
|
return;
|
|
}
|
|
|
|
const uint32_t currentPWM = ledcRead(analogGetChannel(pin.led[ledNo]));
|
|
const uint32_t targetPWM = ledState ? pwmTable[config.Led_Single[ledNo].Brightness] : LED_OFF;
|
|
|
|
if (currentPWM == targetPWM) {
|
|
return;
|
|
}
|
|
|
|
analogWrite(pin.led[ledNo], targetPWM);
|
|
_ledStateCurrent[ledNo] = ledState;
|
|
}
|
|
|
|
void LedSingleClass::turnAllOff()
|
|
{
|
|
_allMode = LedState_t::Off;
|
|
}
|
|
|
|
void LedSingleClass::turnAllOn()
|
|
{
|
|
_allMode = LedState_t::On;
|
|
}
|