committed by
Torsten Stauder
59 changed files with 7261 additions and 5580 deletions
-
2Hardware-Plaforms/ESP32-A1S-Audiokit/README.md
-
1platformio.ini
-
1141src/AudioPlayer.cpp
-
44src/AudioPlayer.h
-
113src/Battery.cpp
-
10src/Battery.h
-
46src/Bluetooth.cpp
-
4src/Bluetooth.h
-
360src/Button.cpp
-
15src/Button.h
-
381src/Cmd.cpp
-
3src/Cmd.h
-
171src/Common.h
-
116src/Ftp.cpp
-
8src/Ftp.h
-
6src/HTMLaccesspoint_DE.h
-
6src/HTMLaccesspoint_EN.h
-
6src/HTMLmanagement_DE.h
-
6src/HTMLmanagement_EN.h
-
169src/IrReceiver.cpp
-
4src/IrReceiver.h
-
654src/Led.cpp
-
25src/Led.h
-
46src/Log.cpp
-
24src/Log.h
-
189src/LogMessages_DE.cpp
-
189src/LogMessages_EN.cpp
-
54src/MemX.cpp
-
6src/MemX.h
-
516src/Mqtt.cpp
-
25src/Mqtt.h
-
77src/Port.cpp
-
5src/Port.h
-
38src/Queues.cpp
-
8src/Queues.h
-
12src/Rfid.h
-
101src/RfidCommon.cpp
-
101src/RfidMfrc522.cpp
-
262src/RfidPn5180.cpp
-
78src/RotaryEncoder.cpp
-
5src/RotaryEncoder.h
-
235src/SdCard.cpp
-
14src/SdCard.h
-
237src/System.cpp
-
25src/System.h
-
1066src/Web.cpp
-
5src/Web.h
-
198src/Wlan.cpp
-
7src/Wlan.h
-
364src/logmessages.h
-
181src/logmessages_EN.h
-
5329src/main.cpp
-
8src/settings-custom.h
-
8src/settings-espa1s.h
-
8src/settings-lolin32.h
-
8src/settings-lolin_d32.h
-
8src/settings-lolin_d32_pro.h
-
8src/settings-ttgo_t8.h
-
105src/settings.h
1141
src/AudioPlayer.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,44 @@ |
|||
#pragma once |
|||
|
|||
typedef struct { // Bit field |
|||
uint8_t playMode: 4; // playMode |
|||
char **playlist; // playlist |
|||
bool repeatCurrentTrack: 1; // If current track should be looped |
|||
bool repeatPlaylist: 1; // If whole playlist should be looped |
|||
uint16_t currentTrackNumber: 9; // Current tracknumber |
|||
uint16_t numberOfTracks: 9; // Number of tracks in playlist |
|||
unsigned long startAtFilePos; // Offset to start play (in bytes) |
|||
uint8_t currentRelPos: 7; // Current relative playPosition (in %) |
|||
bool sleepAfterCurrentTrack: 1; // If uC should go to sleep after current track |
|||
bool sleepAfterPlaylist: 1; // If uC should go to sleep after whole playlist |
|||
bool saveLastPlayPosition: 1; // If playposition/current track should be saved (for AUDIOBOOK) |
|||
char playRfidTag[13]; // ID of RFID-tag that started playlist |
|||
bool pausePlay: 1; // If pause is active |
|||
bool trackFinished: 1; // If current track is finished |
|||
bool playlistFinished: 1; // If whole playlist is finished |
|||
uint8_t playUntilTrackNumber: 6; // Number of tracks to play after which uC goes to sleep |
|||
uint8_t seekmode: 2; // If seekmode is active and if yes: forward or backwards? |
|||
bool newPlayMono: 1; // true if mono; false if stereo (helper) |
|||
bool currentPlayMono: 1; // true if mono; false if stereo |
|||
} playProps; |
|||
|
|||
extern playProps gPlayProperties; |
|||
|
|||
void AudioPlayer_Init(void); |
|||
void AudioPlayer_Cyclic(void); |
|||
uint8_t AudioPlayer_GetRepeatMode(void); |
|||
void AudioPlayer_VolumeToQueueSender(const int32_t _newVolume, bool reAdjustRotary); |
|||
void AudioPlayer_TrackQueueDispatcher(const char *_itemToPlay, const uint32_t _lastPlayPos, const uint32_t _playMode, const uint16_t _trackLastPlayed); |
|||
void AudioPlayer_TrackControlToQueueSender(const uint8_t trackCommand); |
|||
|
|||
uint8_t AudioPlayer_GetCurrentVolume(void); |
|||
void AudioPlayer_SetCurrentVolume(uint8_t value); |
|||
uint8_t AudioPlayer_GetMaxVolume(void); |
|||
void AudioPlayer_SetMaxVolume(uint8_t value); |
|||
uint8_t AudioPlayer_GetMaxVolumeSpeaker(void); |
|||
void AudioPlayer_SetMaxVolumeSpeaker(uint8_t value); |
|||
uint8_t AudioPlayer_GetMinVolume(void); |
|||
void AudioPlayer_SetMinVolume(uint8_t value); |
|||
uint8_t AudioPlayer_GetInitVolume(void); |
|||
void AudioPlayer_SetInitVolume(uint8_t value); |
|||
void AudioPlayer_SetupVolume(void); |
@ -0,0 +1,113 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Log.h"
|
|||
#include "Battery.h"
|
|||
#include "Mqtt.h"
|
|||
#include "Led.h"
|
|||
#include "System.h"
|
|||
|
|||
constexpr uint16_t maxAnalogValue = 4095u; // Highest value given by analogRead(); don't change!
|
|||
|
|||
float warningLowVoltage = s_warningLowVoltage; |
|||
uint8_t voltageCheckInterval = s_voltageCheckInterval; |
|||
float voltageIndicatorLow = s_voltageIndicatorLow; |
|||
float voltageIndicatorHigh = s_voltageIndicatorHigh; |
|||
|
|||
void Battery_Init() |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
// Get voltages from NVS for Neopixel
|
|||
float vLowIndicator = gPrefsSettings.getFloat("vIndicatorLow", 999.99); |
|||
if (vLowIndicator <= 999) |
|||
{ |
|||
voltageIndicatorLow = vLowIndicator; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %.2f V", (char *)FPSTR(voltageIndicatorLowFromNVS), vLowIndicator); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ // preseed if not set
|
|||
gPrefsSettings.putFloat("vIndicatorLow", voltageIndicatorLow); |
|||
} |
|||
|
|||
float vHighIndicator = gPrefsSettings.getFloat("vIndicatorHigh", 999.99); |
|||
if (vHighIndicator <= 999) |
|||
{ |
|||
voltageIndicatorHigh = vHighIndicator; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %.2f V", (char *)FPSTR(voltageIndicatorHighFromNVS), vHighIndicator); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putFloat("vIndicatorHigh", voltageIndicatorHigh); |
|||
} |
|||
|
|||
float vLowWarning = gPrefsSettings.getFloat("wLowVoltage", 999.99); |
|||
if (vLowWarning <= 999) |
|||
{ |
|||
warningLowVoltage = vLowWarning; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %.2f V", (char *)FPSTR(warningLowVoltageFromNVS), vLowWarning); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putFloat("wLowVoltage", warningLowVoltage); |
|||
} |
|||
|
|||
uint32_t vInterval = gPrefsSettings.getUInt("vCheckIntv", 17777); |
|||
if (vInterval != 17777) |
|||
{ |
|||
voltageCheckInterval = vInterval; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u Minuten", (char *)FPSTR(voltageCheckIntervalFromNVS), vInterval); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putUInt("vCheckIntv", voltageCheckInterval); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
// The average of several analog reads will be taken to reduce the noise (Note: One analog read takes ~10µs)
|
|||
float Battery_GetVoltage(void) |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
float factor = 1 / ((float)rdiv2 / (rdiv2 + rdiv1)); |
|||
float averagedAnalogValue = 0; |
|||
uint8_t i; |
|||
for (i = 0; i <= 19; i++) |
|||
{ |
|||
averagedAnalogValue += (float)analogRead(VOLTAGE_READ_PIN); |
|||
} |
|||
averagedAnalogValue /= 20.0; |
|||
return (averagedAnalogValue / maxAnalogValue) * referenceVoltage * factor + offsetVoltage; |
|||
#endif
|
|||
} |
|||
|
|||
// Measures voltage of a battery as per interval or after bootup (after allowing a few seconds to settle down)
|
|||
void Battery_Cyclic(void) |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
static uint32_t lastVoltageCheckTimestamp = 0; |
|||
|
|||
if ((millis() - lastVoltageCheckTimestamp >= voltageCheckInterval * 60000) || (!lastVoltageCheckTimestamp && millis() >= 10000)) |
|||
{ |
|||
float voltage = Battery_GetVoltage(); |
|||
|
|||
if (voltage <= warningLowVoltage) |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: (%.2f V)", (char *)FPSTR(voltageTooLow), voltage); |
|||
Log_Println(Log_Buffer, LOGLEVEL_ERROR); |
|||
Led_Indicate(LedIndicatorType::VoltageWarning); |
|||
} |
|||
|
|||
#ifdef MQTT_ENABLE
|
|||
char vstr[6]; |
|||
snprintf(vstr, 6, "%.2f", voltage); |
|||
publishMqtt((char *)FPSTR(topicBatteryVoltage), vstr, false); |
|||
#endif
|
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %.2f V", (char *)FPSTR(currentVoltageMsg), voltage); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
lastVoltageCheckTimestamp = millis(); |
|||
} |
|||
#endif
|
|||
} |
@ -0,0 +1,10 @@ |
|||
#pragma once |
|||
|
|||
extern float warningLowVoltage; |
|||
extern uint8_t voltageCheckInterval; |
|||
extern float voltageIndicatorLow; |
|||
extern float voltageIndicatorHigh; |
|||
|
|||
void Battery_Init(void); |
|||
void Battery_Cyclic(void); |
|||
float Battery_GetVoltage(void); |
@ -0,0 +1,46 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Bluetooth.h"
|
|||
#include "System.h"
|
|||
|
|||
#ifdef BLUETOOTH_ENABLE
|
|||
#include "esp_bt.h"
|
|||
#include "BluetoothA2DPSink.h"
|
|||
#endif
|
|||
|
|||
#ifdef BLUETOOTH_ENABLE
|
|||
BluetoothA2DPSink *a2dp_sink; |
|||
#endif
|
|||
|
|||
void Bluetooth_Init(void) |
|||
{ |
|||
#ifdef BLUETOOTH_ENABLE
|
|||
if (System_GetOperationMode() == OPMODE_BLUETOOTH) |
|||
{ |
|||
a2dp_sink = new BluetoothA2DPSink(); |
|||
i2s_pin_config_t pin_config = { |
|||
.bck_io_num = I2S_BCLK, |
|||
.ws_io_num = I2S_LRC, |
|||
.data_out_num = I2S_DOUT, |
|||
.data_in_num = I2S_PIN_NO_CHANGE}; |
|||
a2dp_sink->set_pin_config(pin_config); |
|||
a2dp_sink->start((char *)FPSTR(nameBluetoothDevice)); |
|||
} |
|||
else |
|||
{ |
|||
esp_bt_mem_release(ESP_BT_MODE_BTDM); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void Bluetooth_Cyclic(void) |
|||
{ |
|||
#ifdef BLUETOOTH_ENABLE
|
|||
esp_a2d_audio_state_t state = a2dp_sink->get_audio_state(); |
|||
// Reset Sleep Timer when audio is playing
|
|||
if (state == ESP_A2D_AUDIO_STATE_STARTED) |
|||
{ |
|||
System_UpdateActivityTimer(); |
|||
} |
|||
#endif
|
|||
} |
@ -0,0 +1,4 @@ |
|||
#pragma once |
|||
|
|||
void Bluetooth_Init(void); |
|||
void Bluetooth_Cyclic(void); |
@ -0,0 +1,360 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Log.h"
|
|||
#include "Button.h"
|
|||
#include "Cmd.h"
|
|||
#include "Port.h"
|
|||
#include "System.h"
|
|||
|
|||
// Only enable those buttons that are not disabled (99 or >115)
|
|||
// 0 -> 39: GPIOs
|
|||
// 100 -> 115: Port-expander
|
|||
#if (NEXT_BUTTON >= 0 && NEXT_BUTTON <= 39)
|
|||
#define BUTTON_0_ENABLE
|
|||
#elif (NEXT_BUTTON >= 100 && NEXT_BUTTON <= 115)
|
|||
#define EXPANDER_0_ENABLE
|
|||
#endif
|
|||
#if (PREVIOUS_BUTTON >= 0 && PREVIOUS_BUTTON <= 39)
|
|||
#define BUTTON_1_ENABLE
|
|||
#elif (PREVIOUS_BUTTON >= 100 && PREVIOUS_BUTTON <= 115)
|
|||
#define EXPANDER_1_ENABLE
|
|||
#endif
|
|||
#if (PAUSEPLAY_BUTTON >= 0 && PAUSEPLAY_BUTTON <= 39)
|
|||
#define BUTTON_2_ENABLE
|
|||
#elif (PAUSEPLAY_BUTTON >= 100 && PAUSEPLAY_BUTTON <= 115)
|
|||
#define EXPANDER_2_ENABLE
|
|||
#endif
|
|||
#ifdef USEROTARY_ENABLE
|
|||
#if (DREHENCODER_BUTTON >= 0 && DREHENCODER_BUTTON <= 39)
|
|||
#define BUTTON_3_ENABLE
|
|||
#elif (DREHENCODER_BUTTON >= 100 && DREHENCODER_BUTTON <= 115)
|
|||
#define EXPANDER_3_ENABLE
|
|||
#endif
|
|||
#endif
|
|||
#if (BUTTON_4 >= 0 && BUTTON_4 <= 39)
|
|||
#define BUTTON_4_ENABLE
|
|||
#elif (BUTTON_4 >= 100 && BUTTON_4 <= 115)
|
|||
#define EXPANDER_4_ENABLE
|
|||
#endif
|
|||
#if (BUTTON_5 >= 0 && BUTTON_5 <= 39)
|
|||
#define BUTTON_5_ENABLE
|
|||
#elif (BUTTON_5 >= 100 && BUTTON_5 <= 115)
|
|||
#define EXPANDER_5_ENABLE
|
|||
#endif
|
|||
|
|||
t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
|
|||
uint8_t gShutdownButton = 99; // Helper used for Neopixel: stores button-number of shutdown-button
|
|||
|
|||
static volatile SemaphoreHandle_t Button_TimerSemaphore; |
|||
|
|||
#ifndef IR_CONTROL_ENABLE
|
|||
hw_timer_t *Button_Timer = NULL; |
|||
#endif
|
|||
|
|||
static void IRAM_ATTR onTimer(); |
|||
|
|||
static void Button_DoButtonActions(void); |
|||
|
|||
void Button_Init() |
|||
{ |
|||
#if (WAKEUP_BUTTON <= 39)
|
|||
esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_BUTTON, 0); |
|||
#endif
|
|||
|
|||
#ifdef NEOPIXEL_ENABLE // Try to find button that is used for shutdown via longpress-action (only necessary for Neopixel)
|
|||
#if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
|
|||
#if (BUTTON_0_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 0; |
|||
#endif
|
|||
#endif
|
|||
#if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
|
|||
#if (BUTTON_1_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 1; |
|||
#endif
|
|||
#endif
|
|||
#if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
|
|||
#if (BUTTON_2_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 2; |
|||
#endif
|
|||
#endif
|
|||
#if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
|
|||
#if (BUTTON_3_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 3; |
|||
#endif
|
|||
#endif
|
|||
#if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
|
|||
#if (BUTTON_4_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 4; |
|||
#endif
|
|||
#endif
|
|||
#if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
|
|||
#if (BUTTON_5_LONG == CMD_SLEEPMODE)
|
|||
gShutdownButton = 5; |
|||
#endif
|
|||
#endif
|
|||
#endif
|
|||
|
|||
// Activate internal pullups for all enabled buttons
|
|||
#ifdef BUTTON_0_ENABLE
|
|||
pinMode(NEXT_BUTTON, INPUT_PULLUP); |
|||
#endif
|
|||
#ifdef BUTTON_1_ENABLE
|
|||
pinMode(PREVIOUS_BUTTON, INPUT_PULLUP); |
|||
#endif
|
|||
#ifdef BUTTON_2_ENABLE
|
|||
pinMode(PAUSEPLAY_BUTTON, INPUT_PULLUP); |
|||
#endif
|
|||
#ifdef BUTTON_3_ENABLE
|
|||
pinMode(DREHENCODER_BUTTON, INPUT_PULLUP); |
|||
#endif
|
|||
#ifdef BUTTON_4_ENABLE
|
|||
pinMode(BUTTON_4, INPUT_PULLUP); |
|||
#endif
|
|||
#ifdef BUTTON_5_ENABLE
|
|||
pinMode(BUTTON_5, INPUT_PULLUP); |
|||
#endif
|
|||
|
|||
// Create 1000Hz-HW-Timer (currently only used for buttons)
|
|||
Button_TimerSemaphore = xSemaphoreCreateBinary(); |
|||
Button_Timer = timerBegin(0, 240, true); // Prescaler: CPU-clock in MHz
|
|||
timerAttachInterrupt(Button_Timer, &onTimer, true); |
|||
timerAlarmWrite(Button_Timer, 10000, true); // 100 Hz
|
|||
timerAlarmEnable(Button_Timer); |
|||
} |
|||
|
|||
// If timer-semaphore is set, read buttons (unless controls are locked)
|
|||
void Button_Cyclic() |
|||
{ |
|||
if (xSemaphoreTake(Button_TimerSemaphore, 0) == pdTRUE) |
|||
{ |
|||
if (System_AreControlsLocked()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
unsigned long currentTimestamp = millis(); |
|||
|
|||
// Buttons can be mixed between GPIO and port-expander.
|
|||
// But at the same time only one of them can be for example NEXT_BUTTON
|
|||
#if defined(BUTTON_0_ENABLE) || defined(EXPANDER_0_ENABLE)
|
|||
gButtons[0].currentState = Port_Read(NEXT_BUTTON); |
|||
#endif
|
|||
#if defined(BUTTON_1_ENABLE) || defined(EXPANDER_1_ENABLE)
|
|||
gButtons[1].currentState = Port_Read(PREVIOUS_BUTTON); |
|||
#endif
|
|||
#if defined(BUTTON_2_ENABLE) || defined(EXPANDER_2_ENABLE)
|
|||
gButtons[2].currentState = Port_Read(PAUSEPLAY_BUTTON); |
|||
#endif
|
|||
#if defined(BUTTON_3_ENABLE) || defined(EXPANDER_3_ENABLE)
|
|||
gButtons[3].currentState = Port_Read(DREHENCODER_BUTTON); |
|||
#endif
|
|||
#if defined(BUTTON_4_ENABLE) || defined(EXPANDER_4_ENABLE)
|
|||
gButtons[4].currentState = Port_Read(BUTTON_4); |
|||
#endif
|
|||
#if defined(BUTTON_5_ENABLE) || defined(EXPANDER_5_ENABLE)
|
|||
gButtons[5].currentState = Port_Read(BUTTON_5); |
|||
#endif
|
|||
|
|||
// Iterate over all buttons in struct-array
|
|||
for (uint8_t i = 0; i < sizeof(gButtons) / sizeof(gButtons[0]); i++) |
|||
{ |
|||
if (gButtons[i].currentState != gButtons[i].lastState && currentTimestamp - gButtons[i].lastPressedTimestamp > buttonDebounceInterval) |
|||
{ |
|||
if (!gButtons[i].currentState) |
|||
{ |
|||
gButtons[i].isPressed = true; |
|||
gButtons[i].lastPressedTimestamp = currentTimestamp; |
|||
} |
|||
else |
|||
{ |
|||
gButtons[i].isReleased = true; |
|||
gButtons[i].lastReleasedTimestamp = currentTimestamp; |
|||
} |
|||
} |
|||
gButtons[i].lastState = gButtons[i].currentState; |
|||
} |
|||
} |
|||
Button_DoButtonActions(); |
|||
} |
|||
|
|||
// Do corresponding actions for all buttons
|
|||
void Button_DoButtonActions(void) |
|||
{ |
|||
if (gButtons[0].isPressed && gButtons[1].isPressed) |
|||
{ |
|||
gButtons[0].isPressed = false; |
|||
gButtons[1].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_01); |
|||
} |
|||
else if (gButtons[0].isPressed && gButtons[2].isPressed) |
|||
{ |
|||
gButtons[0].isPressed = false; |
|||
gButtons[2].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_02); |
|||
} |
|||
else if (gButtons[0].isPressed && gButtons[3].isPressed) |
|||
{ |
|||
gButtons[0].isPressed = false; |
|||
gButtons[3].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_03); |
|||
} |
|||
else if (gButtons[0].isPressed && gButtons[4].isPressed) |
|||
{ |
|||
gButtons[0].isPressed = false; |
|||
gButtons[4].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_04); |
|||
} |
|||
else if (gButtons[0].isPressed && gButtons[5].isPressed) |
|||
{ |
|||
gButtons[0].isPressed = false; |
|||
gButtons[5].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_05); |
|||
} |
|||
else if (gButtons[1].isPressed && gButtons[2].isPressed) |
|||
{ |
|||
gButtons[1].isPressed = false; |
|||
gButtons[2].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_12); |
|||
} |
|||
else if (gButtons[1].isPressed && gButtons[3].isPressed) |
|||
{ |
|||
gButtons[1].isPressed = false; |
|||
gButtons[3].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_13); |
|||
} |
|||
else if (gButtons[1].isPressed && gButtons[4].isPressed) |
|||
{ |
|||
gButtons[1].isPressed = false; |
|||
gButtons[4].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_14); |
|||
} |
|||
else if (gButtons[1].isPressed && gButtons[5].isPressed) |
|||
{ |
|||
gButtons[1].isPressed = false; |
|||
gButtons[5].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_15); |
|||
} |
|||
else if (gButtons[2].isPressed && gButtons[3].isPressed) |
|||
{ |
|||
gButtons[2].isPressed = false; |
|||
gButtons[3].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_23); |
|||
} |
|||
else if (gButtons[2].isPressed && gButtons[4].isPressed) |
|||
{ |
|||
gButtons[2].isPressed = false; |
|||
gButtons[4].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_24); |
|||
} |
|||
else if (gButtons[2].isPressed && gButtons[5].isPressed) |
|||
{ |
|||
gButtons[2].isPressed = false; |
|||
gButtons[5].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_25); |
|||
} |
|||
else if (gButtons[3].isPressed && gButtons[4].isPressed) |
|||
{ |
|||
gButtons[3].isPressed = false; |
|||
gButtons[4].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_34); |
|||
} |
|||
else if (gButtons[3].isPressed && gButtons[5].isPressed) |
|||
{ |
|||
gButtons[3].isPressed = false; |
|||
gButtons[5].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_35); |
|||
} |
|||
else if (gButtons[4].isPressed && gButtons[5].isPressed) |
|||
{ |
|||
gButtons[4].isPressed = false; |
|||
gButtons[5].isPressed = false; |
|||
Cmd_Action(BUTTON_MULTI_45); |
|||
} |
|||
else |
|||
{ |
|||
for (uint8_t i = 0; i < sizeof(gButtons) / sizeof(gButtons[0]); i++) |
|||
{ |
|||
if (gButtons[i].isPressed) |
|||
{ |
|||
if (gButtons[i].lastReleasedTimestamp > gButtons[i].lastPressedTimestamp) |
|||
{ |
|||
if (gButtons[i].lastReleasedTimestamp - gButtons[i].lastPressedTimestamp >= intervalToLongPress) |
|||
{ |
|||
switch (i) // Long-press-actions
|
|||
{ |
|||
case 0: |
|||
Cmd_Action(BUTTON_0_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 1: |
|||
Cmd_Action(BUTTON_1_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 2: |
|||
Cmd_Action(BUTTON_2_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 3: |
|||
Cmd_Action(BUTTON_3_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 4: |
|||
Cmd_Action(BUTTON_4_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 5: |
|||
Cmd_Action(BUTTON_5_LONG); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
switch (i) // Short-press-actions
|
|||
{ |
|||
case 0: |
|||
Cmd_Action(BUTTON_0_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 1: |
|||
Cmd_Action(BUTTON_1_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 2: |
|||
Cmd_Action(BUTTON_2_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 3: |
|||
Cmd_Action(BUTTON_3_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 4: |
|||
Cmd_Action(BUTTON_4_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
|
|||
case 5: |
|||
Cmd_Action(BUTTON_5_SHORT); |
|||
gButtons[i].isPressed = false; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
void IRAM_ATTR onTimer() |
|||
{ |
|||
xSemaphoreGiveFromISR(Button_TimerSemaphore, NULL); |
|||
} |
@ -0,0 +1,15 @@ |
|||
#pragma once |
|||
|
|||
typedef struct { |
|||
bool lastState : 1; |
|||
bool currentState : 1; |
|||
bool isPressed : 1; |
|||
bool isReleased : 1; |
|||
unsigned long lastPressedTimestamp; |
|||
unsigned long lastReleasedTimestamp; |
|||
} t_button; |
|||
|
|||
extern uint8_t gShutdownButton; |
|||
|
|||
void Button_Init(void); |
|||
void Button_Cyclic(void); |
@ -0,0 +1,381 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Cmd.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Battery.h"
|
|||
#include "Ftp.h"
|
|||
#include "Led.h"
|
|||
#include "Log.h"
|
|||
#include "Mqtt.h"
|
|||
#include "System.h"
|
|||
#include "Wlan.h"
|
|||
|
|||
void Cmd_Action(const uint16_t mod) |
|||
{ |
|||
switch (mod) |
|||
{ |
|||
case LOCK_BUTTONS_MOD: |
|||
{ // Locks/unlocks all buttons
|
|||
System_ToggleLockControls(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_TIMER_MOD_15: |
|||
{ // Enables/disables sleep after 15 minutes
|
|||
System_SetSleepTimer(15u); |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.sleepAfterPlaylist = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_TIMER_MOD_30: |
|||
{ // Enables/disables sleep after 30 minutes
|
|||
System_SetSleepTimer(30u); |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.sleepAfterPlaylist = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_TIMER_MOD_60: |
|||
{ // Enables/disables sleep after 60 minutes
|
|||
System_SetSleepTimer(60u); |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.sleepAfterPlaylist = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_TIMER_MOD_120: |
|||
{ // Enables/disables sleep after 2 hrs
|
|||
System_SetSleepTimer(120u); |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.sleepAfterPlaylist = false; // deactivate/overwrite if already active
|
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_AFTER_END_OF_TRACK: |
|||
{ // Puts uC to sleep after end of current track
|
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_NOTICE); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
if (gPlayProperties.sleepAfterCurrentTrack) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorSleepAtEOTd), LOGLEVEL_NOTICE); |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "0", false); |
|||
#endif
|
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToInitialBrightness(); |
|||
#endif
|
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorSleepAtEOT), LOGLEVEL_NOTICE); |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "EOT", false); |
|||
#endif
|
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToNightBrightness(); |
|||
Log_Println((char *)FPSTR(ledsDimmedToNightmode), LOGLEVEL_INFO); |
|||
#endif
|
|||
} |
|||
gPlayProperties.sleepAfterCurrentTrack = !gPlayProperties.sleepAfterCurrentTrack; |
|||
gPlayProperties.sleepAfterPlaylist = false; |
|||
System_DisableSleepTimer(); |
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
|
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_AFTER_END_OF_PLAYLIST: |
|||
{ // Puts uC to sleep after end of whole playlist (can take a while :->)
|
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_NOTICE); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
if (gPlayProperties.sleepAfterCurrentTrack) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "0", false); |
|||
#endif
|
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToInitialBrightness(); |
|||
#endif
|
|||
Log_Println((char *)FPSTR(modificatorSleepAtEOPd), LOGLEVEL_NOTICE); |
|||
} |
|||
else |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToNightBrightness(); |
|||
Log_Println((char *)FPSTR(ledsDimmedToNightmode), LOGLEVEL_INFO); |
|||
#endif
|
|||
Log_Println((char *)FPSTR(modificatorSleepAtEOP), LOGLEVEL_NOTICE); |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "EOP", false); |
|||
#endif
|
|||
} |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; |
|||
gPlayProperties.sleepAfterPlaylist = !gPlayProperties.sleepAfterPlaylist; |
|||
System_DisableSleepTimer(); |
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case SLEEP_AFTER_5_TRACKS: |
|||
{ |
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_NOTICE); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
|
|||
gPlayProperties.sleepAfterCurrentTrack = false; |
|||
gPlayProperties.sleepAfterPlaylist = false; |
|||
System_DisableSleepTimer(); |
|||
|
|||
if (gPlayProperties.playUntilTrackNumber > 0) |
|||
{ |
|||
gPlayProperties.playUntilTrackNumber = 0; |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "0", false); |
|||
#endif
|
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToInitialBrightness(); |
|||
#endif
|
|||
Log_Println((char *)FPSTR(modificatorSleepd), LOGLEVEL_NOTICE); |
|||
} |
|||
else |
|||
{ |
|||
if (gPlayProperties.currentTrackNumber + 5 > gPlayProperties.numberOfTracks) |
|||
{ // If currentTrack + 5 exceeds number of tracks in playlist, sleep after end of playlist
|
|||
gPlayProperties.sleepAfterPlaylist = true; |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "EOP", false); |
|||
#endif
|
|||
} |
|||
else |
|||
{ |
|||
gPlayProperties.playUntilTrackNumber = gPlayProperties.currentTrackNumber + 5; |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), "EO5T", false); |
|||
#endif
|
|||
} |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToNightBrightness(); |
|||
#endif
|
|||
Log_Println((char *)FPSTR(sleepTimerEO5), LOGLEVEL_NOTICE); |
|||
} |
|||
|
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case REPEAT_PLAYLIST: |
|||
{ |
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_NOTICE); |
|||
System_IndicateError(); |
|||
} |
|||
else |
|||
{ |
|||
if (gPlayProperties.repeatPlaylist) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorPlaylistLoopDeactive), LOGLEVEL_NOTICE); |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorPlaylistLoopActive), LOGLEVEL_NOTICE); |
|||
} |
|||
gPlayProperties.repeatPlaylist = !gPlayProperties.repeatPlaylist; |
|||
char rBuf[2]; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
case REPEAT_TRACK: |
|||
{ // Introduces looping for track-mode
|
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_NOTICE); |
|||
System_IndicateError(); |
|||
} |
|||
else |
|||
{ |
|||
if (gPlayProperties.repeatCurrentTrack) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorTrackDeactive), LOGLEVEL_NOTICE); |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorTrackActive), LOGLEVEL_NOTICE); |
|||
} |
|||
gPlayProperties.repeatCurrentTrack = !gPlayProperties.repeatCurrentTrack; |
|||
char rBuf[2]; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
} |
|||
break; |
|||
} |
|||
|
|||
case DIMM_LEDS_NIGHTMODE: |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
#endif
|
|||
Log_Println((char *)FPSTR(ledsDimmedToNightmode), LOGLEVEL_INFO); |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_ResetToNightBrightness(); |
|||
#endif
|
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
|
|||
case TOGGLE_WIFI_STATUS: |
|||
{ |
|||
Wlan_ToggleEnable(); |
|||
System_IndicateOk(); |
|||
break; |
|||
} |
|||
#ifdef BLUETOOTH_ENABLE
|
|||
case TOGGLE_BLUETOOTH_MODE: |
|||
{ |
|||
if (System_GetOperationModeFromNvs() == OPMODE_NORMAL) |
|||
{ |
|||
System_IndicateOk(); |
|||
System_SetOperationMode(OPMODE_BLUETOOTH); |
|||
} |
|||
else if (System_GetOperationModeFromNvs() == OPMODE_BLUETOOTH) |
|||
{ |
|||
System_IndicateOk(); |
|||
System_SetOperationMode(OPMODE_NORMAL); |
|||
} |
|||
else |
|||
{ |
|||
System_IndicateError(); |
|||
} |
|||
break; |
|||
} |
|||
#endif
|
|||
#ifdef FTP_ENABLE
|
|||
case ENABLE_FTP_SERVER: |
|||
{ |
|||
Ftp_EnableServer(); |
|||
break; |
|||
} |
|||
#endif
|
|||
case CMD_PLAYPAUSE: |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(PAUSEPLAY); |
|||
break; |
|||
} |
|||
case CMD_PREVTRACK: |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(PREVIOUSTRACK); |
|||
break; |
|||
} |
|||
case CMD_NEXTTRACK: |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(NEXTTRACK); |
|||
break; |
|||
} |
|||
case CMD_FIRSTTRACK: |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(FIRSTTRACK); |
|||
break; |
|||
} |
|||
case CMD_LASTTRACK: |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(LASTTRACK); |
|||
break; |
|||
} |
|||
case CMD_VOLUMEINIT: |
|||
{ |
|||
AudioPlayer_VolumeToQueueSender(AudioPlayer_GetInitVolume(), true); |
|||
break; |
|||
} |
|||
case CMD_VOLUMEUP: |
|||
{ |
|||
AudioPlayer_VolumeToQueueSender(AudioPlayer_GetCurrentVolume() + 1, true); |
|||
break; |
|||
} |
|||
case CMD_VOLUMEDOWN: |
|||
{ |
|||
AudioPlayer_VolumeToQueueSender(AudioPlayer_GetCurrentVolume() - 1, true); |
|||
break; |
|||
} |
|||
case CMD_MEASUREBATTERY: |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
float voltage = Battery_GetVoltage(); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %.2f V", (char *)FPSTR(currentVoltageMsg), voltage); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
Led_Indicate(LedIndicatorType::Voltage); |
|||
#ifdef MQTT_ENABLE
|
|||
char vstr[6]; |
|||
snprintf(vstr, 6, "%.2f", voltage); |
|||
publishMqtt((char *)FPSTR(topicBatteryVoltage), vstr, false); |
|||
#endif
|
|||
#endif
|
|||
break; |
|||
} |
|||
case CMD_SLEEPMODE: |
|||
{ |
|||
System_RequestSleep(); |
|||
break; |
|||
} |
|||
case CMD_SEEK_FORWARDS: |
|||
{ |
|||
gPlayProperties.seekmode = SEEK_FORWARDS; |
|||
break; |
|||
} |
|||
case CMD_SEEK_BACKWARDS: |
|||
{ |
|||
gPlayProperties.seekmode = SEEK_BACKWARDS; |
|||
break; |
|||
} |
|||
default: |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s %d !", (char *)FPSTR(modificatorDoesNotExist), mod); |
|||
Log_Println(Log_Buffer, LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,3 @@ |
|||
#pragma once |
|||
|
|||
void Cmd_Action(const uint16_t mod); |
@ -0,0 +1,171 @@ |
|||
#pragma once |
|||
|
|||
// FilePathLength |
|||
#define MAX_FILEPATH_LENTGH 256 |
|||
|
|||
constexpr char stringDelimiter[] = "#"; // Character used to encapsulate data in linear NVS-strings (don't change) |
|||
constexpr char stringOuterDelimiter[] = "^"; // Character used to encapsulate encapsulated data along with RFID-ID in backup-file |
|||
|
|||
inline bool isNumber(const char *str) |
|||
{ |
|||
byte i = 0; |
|||
|
|||
while (*(str + i) != '\0') |
|||
{ |
|||
if (!isdigit(*(str + i++))) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (i > 0) |
|||
{ |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
// Checks if string starts with prefix |
|||
// Returns true if so |
|||
inline bool startsWith(const char *str, const char *pre) |
|||
{ |
|||
if (strlen(pre) < 1) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return !strncmp(str, pre, strlen(pre)); |
|||
} |
|||
|
|||
// Checks if string ends with suffix |
|||
// Returns true if so |
|||
inline bool endsWith(const char *str, const char *suf) |
|||
{ |
|||
const char *a = str + strlen(str); |
|||
const char *b = suf + strlen(suf); |
|||
|
|||
while (a != str && b != suf) |
|||
{ |
|||
if (*--a != *--b) |
|||
break; |
|||
} |
|||
|
|||
return b == suf && *a == *b; |
|||
} |
|||
|
|||
inline void convertUtf8ToAscii(String utf8String, char *asciiString) |
|||
{ |
|||
|
|||
int k = 0; |
|||
bool f_C3_seen = false; |
|||
|
|||
for (int i = 0; i < utf8String.length() && k < MAX_FILEPATH_LENTGH - 1; i++) |
|||
{ |
|||
|
|||
if (utf8String[i] == 195) |
|||
{ // C3 |
|||
f_C3_seen = true; |
|||
continue; |
|||
} |
|||
else |
|||
{ |
|||
if (f_C3_seen == true) |
|||
{ |
|||
f_C3_seen = false; |
|||
switch (utf8String[i]) |
|||
{ |
|||
case 0x84: |
|||
asciiString[k++] = 0x8e; |
|||
break; // Ä |
|||
case 0xa4: |
|||
asciiString[k++] = 0x84; |
|||
break; // ä |
|||
case 0x9c: |
|||
asciiString[k++] = 0x9a; |
|||
break; // Ü |
|||
case 0xbc: |
|||
asciiString[k++] = 0x81; |
|||
break; // ü |
|||
case 0x96: |
|||
asciiString[k++] = 0x99; |
|||
break; // Ö |
|||
case 0xb6: |
|||
asciiString[k++] = 0x94; |
|||
break; // ö |
|||
case 0x9f: |
|||
asciiString[k++] = 0xe1; |
|||
break; // ß |
|||
default: |
|||
asciiString[k++] = 0xdb; // Unknow... |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
asciiString[k++] = utf8String[i]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
asciiString[k] = 0; |
|||
} |
|||
|
|||
inline void convertAsciiToUtf8(String asciiString, char *utf8String) |
|||
{ |
|||
|
|||
int k = 0; |
|||
|
|||
for (int i = 0; i < asciiString.length() && k < MAX_FILEPATH_LENTGH - 2; i++) |
|||
{ |
|||
|
|||
switch (asciiString[i]) |
|||
{ |
|||
case 0x8e: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0x84; |
|||
break; // Ä |
|||
case 0x84: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0xa4; |
|||
break; // ä |
|||
case 0x9a: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0x9c; |
|||
break; // Ü |
|||
case 0x81: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0xbc; |
|||
break; // ü |
|||
case 0x99: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0x96; |
|||
break; // Ö |
|||
case 0x94: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0xb6; |
|||
break; // ö |
|||
case 0xe1: |
|||
utf8String[k++] = 0xc3; |
|||
utf8String[k++] = 0x9f; |
|||
break; // ß |
|||
default: |
|||
utf8String[k++] = asciiString[i]; |
|||
} |
|||
} |
|||
|
|||
utf8String[k] = 0; |
|||
} |
|||
|
|||
// Release previously allocated memory |
|||
inline void freeMultiCharArray(char **arr, const uint32_t cnt) |
|||
{ |
|||
for (uint32_t i = 0; i <= cnt; i++) |
|||
{ |
|||
/*snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *) FPSTR(freePtr), *(arr+i)); |
|||
Log_Println(Log_Buffer, LOGLEVEL_DEBUG);*/ |
|||
free(*(arr + i)); |
|||
} |
|||
*arr = NULL; |
|||
} |
@ -0,0 +1,116 @@ |
|||
#include <Arduino.h>
|
|||
#include <WiFi.h>
|
|||
#include "settings.h"
|
|||
#include "Ftp.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "SdCard.h"
|
|||
#include "System.h"
|
|||
#include "Wlan.h"
|
|||
|
|||
#ifdef FTP_ENABLE
|
|||
#include "ESP32FtpServer.h"
|
|||
#endif
|
|||
|
|||
// FTP
|
|||
char *Ftp_User = x_strndup((char *)"esp32", ftpUserLength); // FTP-user (default; can be changed later via GUI)
|
|||
char *Ftp_Password = x_strndup((char *)"esp32", ftpPasswordLength); // FTP-password (default; can be changed later via GUI)
|
|||
|
|||
// FTP
|
|||
#ifdef FTP_ENABLE
|
|||
FtpServer *ftpSrv; // Heap-alloction takes place later (when needed)
|
|||
bool ftpEnableLastStatus = false; |
|||
bool ftpEnableCurrentStatus = false; |
|||
#endif
|
|||
|
|||
void ftpManager(void); |
|||
|
|||
void Ftp_Init(void) |
|||
{ |
|||
// Get FTP-user from NVS
|
|||
String nvsFtpUser = gPrefsSettings.getString("ftpuser", "-1"); |
|||
if (!nvsFtpUser.compareTo("-1")) |
|||
{ |
|||
gPrefsSettings.putString("ftpuser", (String)Ftp_User); |
|||
Log_Println((char *)FPSTR(wroteFtpUserToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
else |
|||
{ |
|||
strncpy(Ftp_User, nvsFtpUser.c_str(), ftpUserLength); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredFtpUserFromNvs), nvsFtpUser.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Get FTP-password from NVS
|
|||
String nvsFtpPassword = gPrefsSettings.getString("ftppassword", "-1"); |
|||
if (!nvsFtpPassword.compareTo("-1")) |
|||
{ |
|||
gPrefsSettings.putString("ftppassword", (String)Ftp_Password); |
|||
Log_Println((char *)FPSTR(wroteFtpPwdToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
else |
|||
{ |
|||
strncpy(Ftp_Password, nvsFtpPassword.c_str(), ftpPasswordLength); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredFtpPwdFromNvs), nvsFtpPassword.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
} |
|||
|
|||
void Ftp_Cyclic(void) |
|||
{ |
|||
#ifdef FTP_ENABLE
|
|||
ftpManager(); |
|||
|
|||
if (WL_CONNECTED == WiFi.status()) |
|||
{ |
|||
if (ftpEnableLastStatus && ftpEnableCurrentStatus) |
|||
{ |
|||
ftpSrv->handleFTP(); |
|||
} |
|||
} |
|||
|
|||
if (ftpEnableLastStatus && ftpEnableCurrentStatus) |
|||
{ |
|||
if (ftpSrv->isConnected()) |
|||
{ |
|||
System_UpdateActivityTimer(); // Re-adjust timer while client is connected to avoid ESP falling asleep
|
|||
} |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void Ftp_EnableServer(void) |
|||
{ |
|||
if (Wlan_IsConnected() && !ftpEnableLastStatus && !ftpEnableCurrentStatus) |
|||
{ |
|||
ftpEnableLastStatus = true; |
|||
System_IndicateOk(); |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToStartFtpServer), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
} |
|||
} |
|||
|
|||
// Creates FTP-instance only when requested
|
|||
void ftpManager(void) |
|||
{ |
|||
#ifdef FTP_ENABLE
|
|||
if (ftpEnableLastStatus && !ftpEnableCurrentStatus) |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(freeHeapWithoutFtp), ESP.getFreeHeap()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_DEBUG); |
|||
ftpEnableCurrentStatus = true; |
|||
ftpSrv = new FtpServer(); |
|||
ftpSrv->begin(gFSystem, Ftp_User, Ftp_Password); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(freeHeapWithFtp), ESP.getFreeHeap()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_DEBUG); |
|||
#if (LANGUAGE == 1)
|
|||
Serial.println(F("FTP-Server gestartet")); |
|||
#else
|
|||
Serial.println(F("FTP-server started")); |
|||
#endif
|
|||
} |
|||
#endif
|
|||
} |
@ -0,0 +1,8 @@ |
|||
#pragma once |
|||
|
|||
constexpr uint8_t ftpUserLength = 10u; // Length will be published n-1 as maxlength to GUI |
|||
constexpr uint8_t ftpPasswordLength = 15u; // Length will be published n-1 as maxlength to GUI |
|||
|
|||
void Ftp_Init(void); |
|||
void Ftp_Cyclic(void); |
|||
void Ftp_EnableServer(void); |
@ -0,0 +1,169 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "IrReceiver.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Cmd.h"
|
|||
#include "Queues.h"
|
|||
#include "System.h"
|
|||
|
|||
#ifdef IR_CONTROL_ENABLE
|
|||
#include <IRremote.h>
|
|||
#endif
|
|||
|
|||
// HW-Timer
|
|||
#ifdef IR_CONTROL_ENABLE
|
|||
uint32_t IrReceiver_LastRcCmdTimestamp = 0u; |
|||
#endif
|
|||
|
|||
void IrReceiver_Init() |
|||
{ |
|||
#ifdef IR_CONTROL_ENABLE
|
|||
IrReceiver.begin(IRLED_PIN); |
|||
#endif
|
|||
} |
|||
|
|||
void IrReceiver_Cyclic() |
|||
{ |
|||
#ifdef IR_CONTROL_ENABLE
|
|||
static uint8_t lastVolume = 0; |
|||
|
|||
if (IrReceiver.decode()) |
|||
{ |
|||
|
|||
// Print a short summary of received data
|
|||
IrReceiver.printIRResultShort(&Serial); |
|||
Serial.println(); |
|||
IrReceiver.resume(); // Enable receiving of the next value
|
|||
bool rcActionOk = false; |
|||
if (millis() - IrReceiver_LastRcCmdTimestamp >= IR_DEBOUNCE) |
|||
{ |
|||
rcActionOk = true; // not used for volume up/down
|
|||
IrReceiver_LastRcCmdTimestamp = millis(); |
|||
} |
|||
|
|||
switch (IrReceiver.decodedIRData.command) |
|||
{ |
|||
case RC_PLAY: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_PLAYPAUSE); |
|||
Serial.println(F("RC: Play")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_PAUSE: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_PLAYPAUSE); |
|||
Serial.println(F("RC: Pause")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_NEXT: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_NEXTTRACK); |
|||
Serial.println(F("RC: Next")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_PREVIOUS: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_PREVTRACK); |
|||
Serial.println(F("RC: Previous")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_FIRST: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_FIRSTTRACK); |
|||
Serial.println(F("RC: First")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_LAST: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(CMD_LASTTRACK); |
|||
Serial.println(F("RC: Last")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_MUTE: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
if (AudioPlayer_GetCurrentVolume() > 0) |
|||
{ |
|||
lastVolume = AudioPlayer_GetCurrentVolume(); |
|||
AudioPlayer_SetCurrentVolume(0u); |
|||
} |
|||
else |
|||
{ |
|||
AudioPlayer_SetCurrentVolume(lastVolume); // Remember last volume if mute is pressed again
|
|||
} |
|||
|
|||
uint8_t currentVolume = AudioPlayer_GetCurrentVolume(); |
|||
xQueueSend(gVolumeQueue, ¤tVolume, 0); |
|||
Serial.println(F("RC: Mute")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_BLUETOOTH: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(TOGGLE_BLUETOOTH_MODE); |
|||
Serial.println(F("RC: Bluetooth")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_FTP: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Cmd_Action(ENABLE_FTP_SERVER); |
|||
Serial.println(F("RC: FTP")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_SHUTDOWN: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
System_RequestSleep(); |
|||
Serial.println(F("RC: Shutdown")); |
|||
} |
|||
break; |
|||
} |
|||
case RC_VOL_DOWN: |
|||
{ |
|||
Cmd_Action(CMD_VOLUMEDOWN); |
|||
Serial.println(F("RC: Volume down")); |
|||
break; |
|||
} |
|||
case RC_VOL_UP: |
|||
{ |
|||
Cmd_Action(CMD_VOLUMEUP); |
|||
Serial.println(F("RC: Volume up")); |
|||
break; |
|||
} |
|||
default: |
|||
{ |
|||
if (rcActionOk) |
|||
{ |
|||
Serial.println(F("RC: unknown")); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|||
} |
@ -0,0 +1,4 @@ |
|||
#pragma once |
|||
|
|||
void IrReceiver_Init(); |
|||
void IrReceiver_Cyclic(); |
@ -0,0 +1,654 @@ |
|||
#include <Arduino.h>
|
|||
#include <WiFi.h>
|
|||
#include <esp_task_wdt.h>
|
|||
#include "settings.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Battery.h"
|
|||
#include "Button.h"
|
|||
#include "Led.h"
|
|||
#include "Log.h"
|
|||
#include "System.h"
|
|||
#include "Wlan.h"
|
|||
|
|||
#ifdef NEOPIXEL_ENABLE
|
|||
#include <FastLED.h>
|
|||
|
|||
#define LED_INITIAL_BRIGHTNESS 16u
|
|||
#define LED_INITIAL_NIGHT_BRIGHTNESS 2u
|
|||
|
|||
#define LED_INDICATOR_SET(indicator) ((Led_Indicators) |= (1u << ((uint8_t)indicator)))
|
|||
#define LED_INDICATOR_IS_SET(indicator) (((Led_Indicators) & (1u << ((uint8_t)indicator))) > 0u)
|
|||
#define LED_INDICATOR_CLEAR(indicator) ((Led_Indicators) &= ~(1u << ((uint8_t)indicator)))
|
|||
|
|||
extern t_button gButtons[7]; // next + prev + pplay + rotEnc + button4 + button5 + dummy-button
|
|||
extern uint8_t gShutdownButton; |
|||
|
|||
static uint32_t Led_Indicators = 0u; |
|||
|
|||
static bool Led_Pause = false; // Used to pause Neopixel-signalisation (while NVS-writes as this leads to exceptions; don't know why)
|
|||
|
|||
static uint8_t Led_InitialBrightness = LED_INITIAL_BRIGHTNESS; |
|||
static uint8_t Led_Brightness = LED_INITIAL_BRIGHTNESS; |
|||
static uint8_t Led_NightBrightness = LED_INITIAL_NIGHT_BRIGHTNESS; |
|||
|
|||
static void Led_Task(void *parameter); |
|||
static uint8_t Led_Address(uint8_t number); |
|||
|
|||
#endif
|
|||
|
|||
void Led_Init(void) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
// Get some stuff from NVS...
|
|||
// Get initial LED-brightness from NVS
|
|||
uint8_t nvsILedBrightness = gPrefsSettings.getUChar("iLedBrightness", 0); |
|||
if (nvsILedBrightness) |
|||
{ |
|||
Led_InitialBrightness = nvsILedBrightness; |
|||
Led_Brightness = nvsILedBrightness; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %d", (char *)FPSTR(initialBrightnessfromNvs), nvsILedBrightness); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putUChar("iLedBrightness", Led_InitialBrightness); |
|||
Log_Println((char *)FPSTR(wroteInitialBrightnessToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
// Get night LED-brightness from NVS
|
|||
uint8_t nvsNLedBrightness = gPrefsSettings.getUChar("nLedBrightness", 0); |
|||
if (nvsNLedBrightness) |
|||
{ |
|||
Led_NightBrightness = nvsNLedBrightness; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %d", (char *)FPSTR(restoredInitialBrightnessForNmFromNvs), nvsNLedBrightness); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putUChar("nLedBrightness", Led_NightBrightness); |
|||
Log_Println((char *)FPSTR(wroteNmBrightnessToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
xTaskCreatePinnedToCore( |
|||
Led_Task, /* Function to implement the task */ |
|||
"Led_Task", /* Name of the task */ |
|||
2000, /* Stack size in words */ |
|||
NULL, /* Task input parameter */ |
|||
1, /* Priority of the task */ |
|||
NULL, /* Task handle. */ |
|||
0 /* Core where the task should run */ |
|||
); |
|||
#endif
|
|||
} |
|||
|
|||
void Led_Exit(void) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
FastLED.clear(); |
|||
FastLED.show(); |
|||
#endif
|
|||
} |
|||
|
|||
void Led_Indicate(LedIndicatorType value) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
LED_INDICATOR_SET(value); |
|||
#endif
|
|||
} |
|||
|
|||
void Led_SetPause(boolean value) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_Pause = value; |
|||
#endif
|
|||
} |
|||
|
|||
void Led_ResetToInitialBrightness(void) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_Brightness = Led_InitialBrightness; |
|||
#endif
|
|||
} |
|||
|
|||
void Led_ResetToNightBrightness(void) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_Brightness = Led_NightBrightness; |
|||
Log_Println((char *)FPSTR(ledsDimmedToNightmode), LOGLEVEL_INFO); |
|||
#endif
|
|||
} |
|||
|
|||
uint8_t Led_GetBrightness(void) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
return Led_Brightness; |
|||
#else
|
|||
return 0u; |
|||
#endif
|
|||
} |
|||
|
|||
void Led_SetBrightness(uint8_t value) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
Led_Brightness = value; |
|||
#endif
|
|||
} |
|||
|
|||
// Switches Neopixel-addressing from clockwise to counter clockwise (and vice versa)
|
|||
uint8_t Led_Address(uint8_t number) |
|||
{ |
|||
#ifdef NEOPIXEL_REVERSE_ROTATION
|
|||
return NUM_LEDS - 1 - number; |
|||
#else
|
|||
return number; |
|||
#endif
|
|||
} |
|||
|
|||
static void Led_Task(void *parameter) |
|||
{ |
|||
#ifdef NEOPIXEL_ENABLE
|
|||
static uint8_t hlastVolume = AudioPlayer_GetCurrentVolume(); |
|||
static uint8_t lastPos = gPlayProperties.currentRelPos; |
|||
static bool lastPlayState = false; |
|||
static bool lastLockState = false; |
|||
static bool ledBusyShown = false; |
|||
static bool notificationShown = false; |
|||
static bool volumeChangeShown = false; |
|||
static bool showEvenError = false; |
|||
static bool turnedOffLeds = false; |
|||
static uint8_t ledPosWebstream = 0; |
|||
static uint8_t ledSwitchInterval = 5; // time in secs (webstream-only)
|
|||
static uint8_t webstreamColor = 0; |
|||
static unsigned long lastSwitchTimestamp = 0; |
|||
static bool redrawProgress = false; |
|||
static uint8_t lastLedBrightness = Led_Brightness; |
|||
static CRGB::HTMLColorCode idleColor; |
|||
static CRGB leds[NUM_LEDS]; |
|||
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalSMD5050); |
|||
FastLED.setBrightness(Led_Brightness); |
|||
|
|||
for (;;) |
|||
{ |
|||
if (Led_Pause) |
|||
{ // Workaround to prevent exceptions while NVS-writes take place
|
|||
vTaskDelay(portTICK_RATE_MS * 10); |
|||
continue; |
|||
} |
|||
if (System_IsSleepRequested()) |
|||
{ // If deepsleep is planned, turn off LEDs first in order to avoid LEDs still glowing when ESP32 is in deepsleep
|
|||
if (!turnedOffLeds) |
|||
{ |
|||
FastLED.clear(true); |
|||
turnedOffLeds = true; |
|||
} |
|||
|
|||
vTaskDelay(portTICK_RATE_MS * 10); |
|||
continue; |
|||
} |
|||
if (!LED_INDICATOR_IS_SET(LedIndicatorType::BootComplete)) |
|||
{ // Rotates orange unless boot isn't complete
|
|||
FastLED.clear(); |
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
if (showEvenError) |
|||
{ |
|||
if (Led_Address(led) % 2 == 0) |
|||
{ |
|||
if (millis() <= 10000) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Orange; |
|||
} |
|||
else |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (millis() >= 10000) |
|||
{ // Flashes red after 10s (will remain forever if SD cannot be mounted)
|
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
else |
|||
{ |
|||
if (Led_Address(led) % 2 == 1) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Orange; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
FastLED.show(); |
|||
showEvenError = !showEvenError; |
|||
vTaskDelay(portTICK_RATE_MS * 500); |
|||
esp_task_wdt_reset(); |
|||
continue; |
|||
} |
|||
|
|||
if (lastLedBrightness != Led_Brightness) |
|||
{ |
|||
FastLED.setBrightness(Led_Brightness); |
|||
lastLedBrightness = Led_Brightness; |
|||
} |
|||
|
|||
// LEDs growing red as long button for sleepmode is pressed.
|
|||
if (gShutdownButton < (sizeof(gButtons) / sizeof(gButtons[0])) - 1) |
|||
{ // Only show animation, if CMD_SLEEPMODE was assigned to BUTTON_n_LONG + button is pressed
|
|||
if (!gButtons[gShutdownButton].currentState) |
|||
{ |
|||
FastLED.clear(); |
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
if (gButtons[gShutdownButton].currentState) |
|||
{ |
|||
FastLED.show(); |
|||
delay(5); |
|||
break; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(intervalToLongPress / NUM_LEDS * portTICK_RATE_MS); |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
gShutdownButton = (sizeof(gButtons) / sizeof(gButtons[0])) - 1; // If CMD_SLEEPMODE was not assigned to an enabled button, dummy-button is used
|
|||
if (!gButtons[gShutdownButton].currentState) |
|||
{ |
|||
gButtons[gShutdownButton].currentState = true; |
|||
} |
|||
} |
|||
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::Error)) |
|||
{ // If error occured (e.g. RFID-modification not accepted)
|
|||
LED_INDICATOR_CLEAR(LedIndicatorType::Error); |
|||
notificationShown = true; |
|||
FastLED.clear(); |
|||
|
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 200); |
|||
} |
|||
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::Ok)) |
|||
{ // If action was accepted
|
|||
LED_INDICATOR_CLEAR(LedIndicatorType::Ok); |
|||
notificationShown = true; |
|||
FastLED.clear(); |
|||
|
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Green; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 400); |
|||
} |
|||
|
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning)) |
|||
{ // Flashes red three times if battery-voltage is low
|
|||
LED_INDICATOR_CLEAR(LedIndicatorType::VoltageWarning); |
|||
notificationShown = true; |
|||
for (uint8_t i = 0; i < 3; i++) |
|||
{ |
|||
FastLED.clear(); |
|||
|
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 200); |
|||
FastLED.clear(); |
|||
|
|||
for (uint8_t led = 0; led < NUM_LEDS; led++) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Black; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 200); |
|||
} |
|||
} |
|||
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::Voltage)) |
|||
{ |
|||
LED_INDICATOR_CLEAR(LedIndicatorType::Voltage); |
|||
float currentVoltage = Battery_GetVoltage(); |
|||
float vDiffIndicatorRange = voltageIndicatorHigh - voltageIndicatorLow; |
|||
float vDiffCurrent = currentVoltage - voltageIndicatorLow; |
|||
|
|||
if (vDiffCurrent < 0) |
|||
{ // If voltage is too low or no battery is connected
|
|||
LED_INDICATOR_SET(LedIndicatorType::Error); |
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
uint8_t numLedsToLight = ((float)vDiffCurrent / vDiffIndicatorRange) * NUM_LEDS; |
|||
FastLED.clear(); |
|||
for (uint8_t led = 0; led < numLedsToLight; led++) |
|||
{ |
|||
if (((float)numLedsToLight / NUM_LEDS) >= 0.6) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Green; |
|||
} |
|||
else if (((float)numLedsToLight / NUM_LEDS) <= 0.6 && ((float)numLedsToLight / NUM_LEDS) >= 0.3) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Orange; |
|||
} |
|||
else |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 20); |
|||
} |
|||
|
|||
for (uint8_t i = 0; i <= 100; i++) |
|||
{ |
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
vTaskDelay(portTICK_RATE_MS * 20); |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|||
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume()) |
|||
{ // If volume has been changed
|
|||
uint8_t numLedsToLight = map(AudioPlayer_GetCurrentVolume(), 0, AudioPlayer_GetMaxVolume(), 0, NUM_LEDS); |
|||
hlastVolume = AudioPlayer_GetCurrentVolume(); |
|||
volumeChangeShown = true; |
|||
FastLED.clear(); |
|||
|
|||
for (int led = 0; led < numLedsToLight; led++) |
|||
{ // (Inverse) color-gradient from green (85) back to (still) red (245) using unsigned-cast
|
|||
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)95 / NUM_LEDS) * led)); |
|||
} |
|||
FastLED.show(); |
|||
|
|||
for (uint8_t i = 0; i <= 50; i++) |
|||
{ |
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume()) |
|||
{ |
|||
volumeChangeShown = false; |
|||
} |
|||
break; |
|||
} |
|||
|
|||
vTaskDelay(portTICK_RATE_MS * 20); |
|||
} |
|||
} |
|||
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::Rewind)) |
|||
{ |
|||
LED_INDICATOR_CLEAR(LedIndicatorType::Rewind); |
|||
for (uint8_t i = NUM_LEDS - 1; i > 0; i--) |
|||
{ |
|||
leds[Led_Address(i)] = CRGB::Black; |
|||
FastLED.show(); |
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
vTaskDelay(portTICK_RATE_MS * 30); |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (LED_INDICATOR_IS_SET(LedIndicatorType::PlaylistProgress)) |
|||
{ |
|||
LED_INDICATOR_CLEAR(LedIndicatorType::PlaylistProgress); |
|||
if (gPlayProperties.numberOfTracks > 1 && gPlayProperties.currentTrackNumber < gPlayProperties.numberOfTracks) |
|||
{ |
|||
uint8_t numLedsToLight = map(gPlayProperties.currentTrackNumber, 0, gPlayProperties.numberOfTracks - 1, 0, NUM_LEDS); |
|||
FastLED.clear(); |
|||
for (uint8_t i = 0; i < numLedsToLight; i++) |
|||
{ |
|||
leds[Led_Address(i)] = CRGB::Blue; |
|||
FastLED.show(); |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning) || LED_INDICATOR_IS_SET(LedIndicatorType::Voltage) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#else
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#endif
|
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
vTaskDelay(portTICK_RATE_MS * 30); |
|||
} |
|||
} |
|||
|
|||
for (uint8_t i = 0; i <= 100; i++) |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning) || LED_INDICATOR_IS_SET(LedIndicatorType::Voltage) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#else
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#endif
|
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
vTaskDelay(portTICK_RATE_MS * 15); |
|||
} |
|||
} |
|||
|
|||
for (uint8_t i = numLedsToLight; i > 0; i--) |
|||
{ |
|||
leds[Led_Address(i) - 1] = CRGB::Black; |
|||
FastLED.show(); |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning) || LED_INDICATOR_IS_SET(LedIndicatorType::Voltage) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#else
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#endif
|
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
vTaskDelay(portTICK_RATE_MS * 30); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
switch (gPlayProperties.playMode) |
|||
{ |
|||
case NO_PLAYLIST: // If no playlist is active (idle)
|
|||
if (System_GetOperationMode() == OPMODE_BLUETOOTH) |
|||
{ |
|||
idleColor = CRGB::Blue; |
|||
} |
|||
else |
|||
{ |
|||
if (Wlan_IsConnected()) |
|||
{ |
|||
idleColor = CRGB::White; |
|||
} |
|||
else |
|||
{ |
|||
idleColor = CRGB::Green; |
|||
} |
|||
} |
|||
if (hlastVolume == AudioPlayer_GetCurrentVolume() && lastLedBrightness == Led_Brightness) |
|||
{ |
|||
for (uint8_t i = 0; i < NUM_LEDS; i++) |
|||
{ |
|||
FastLED.clear(); |
|||
if (Led_Address(i) == 0) |
|||
{ // White if Wifi is enabled and blue if not
|
|||
leds[0] = idleColor; |
|||
leds[NUM_LEDS / 4] = idleColor; |
|||
leds[NUM_LEDS / 2] = idleColor; |
|||
leds[NUM_LEDS / 4 * 3] = idleColor; |
|||
} |
|||
else |
|||
{ |
|||
leds[Led_Address(i) % NUM_LEDS] = idleColor; |
|||
leds[(Led_Address(i) + NUM_LEDS / 4) % NUM_LEDS] = idleColor; |
|||
leds[(Led_Address(i) + NUM_LEDS / 2) % NUM_LEDS] = idleColor; |
|||
leds[(Led_Address(i) + NUM_LEDS / 4 * 3) % NUM_LEDS] = idleColor; |
|||
} |
|||
FastLED.show(); |
|||
for (uint8_t i = 0; i <= 50; i++) |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning) || LED_INDICATOR_IS_SET(LedIndicatorType::Voltage) || gPlayProperties.playMode != NO_PLAYLIST || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#else
|
|||
if (hlastVolume != AudioPlayer_GetCurrentVolume() || lastLedBrightness != Led_Brightness || LED_INDICATOR_IS_SET(LedIndicatorType::Error) || LED_INDICATOR_IS_SET(LedIndicatorType::Ok) || gPlayProperties.playMode != NO_PLAYLIST || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#endif
|
|||
break; |
|||
} |
|||
else |
|||
{ |
|||
vTaskDelay(portTICK_RATE_MS * 10); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
break; |
|||
|
|||
case BUSY: // If uC is busy (parsing SD-card)
|
|||
ledBusyShown = true; |
|||
for (uint8_t i = 0; i < NUM_LEDS; i++) |
|||
{ |
|||
FastLED.clear(); |
|||
if (Led_Address(i) == 0) |
|||
{ |
|||
leds[0] = CRGB::BlueViolet; |
|||
leds[NUM_LEDS / 4] = CRGB::BlueViolet; |
|||
leds[NUM_LEDS / 2] = CRGB::BlueViolet; |
|||
leds[NUM_LEDS / 4 * 3] = CRGB::BlueViolet; |
|||
} |
|||
else |
|||
{ |
|||
leds[Led_Address(i) % NUM_LEDS] = CRGB::BlueViolet; |
|||
leds[(Led_Address(i) + NUM_LEDS / 4) % NUM_LEDS] = CRGB::BlueViolet; |
|||
leds[(Led_Address(i) + NUM_LEDS / 2) % NUM_LEDS] = CRGB::BlueViolet; |
|||
leds[(Led_Address(i) + NUM_LEDS / 4 * 3) % NUM_LEDS] = CRGB::BlueViolet; |
|||
} |
|||
FastLED.show(); |
|||
if (gPlayProperties.playMode != BUSY) |
|||
{ |
|||
break; |
|||
} |
|||
vTaskDelay(portTICK_RATE_MS * 50); |
|||
} |
|||
break; |
|||
|
|||
default: // If playlist is active (doesn't matter which type)
|
|||
if (!gPlayProperties.playlistFinished) |
|||
{ |
|||
#ifdef MEASURE_BATTERY_VOLTAGE
|
|||
if (gPlayProperties.pausePlay != lastPlayState || System_AreControlsLocked() != lastLockState || notificationShown || ledBusyShown || volumeChangeShown || LED_INDICATOR_IS_SET(LedIndicatorType::VoltageWarning) || LED_INDICATOR_IS_SET(LedIndicatorType::Voltage) || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#else
|
|||
if (gPlayProperties.pausePlay != lastPlayState || System_AreControlsLocked() != lastLockState || notificationShown || ledBusyShown || volumeChangeShown || !gButtons[gShutdownButton].currentState || System_IsSleepRequested()) |
|||
{ |
|||
#endif
|
|||
lastPlayState = gPlayProperties.pausePlay; |
|||
lastLockState = System_AreControlsLocked(); |
|||
notificationShown = false; |
|||
volumeChangeShown = false; |
|||
if (ledBusyShown) |
|||
{ |
|||
ledBusyShown = false; |
|||
FastLED.clear(); |
|||
FastLED.show(); |
|||
} |
|||
redrawProgress = true; |
|||
} |
|||
|
|||
if (gPlayProperties.playMode != WEBSTREAM) |
|||
{ |
|||
if (gPlayProperties.currentRelPos != lastPos || redrawProgress) |
|||
{ |
|||
redrawProgress = false; |
|||
lastPos = gPlayProperties.currentRelPos; |
|||
uint8_t numLedsToLight = map(gPlayProperties.currentRelPos, 0, 98, 0, NUM_LEDS); |
|||
FastLED.clear(); |
|||
for (uint8_t led = 0; led < numLedsToLight; led++) |
|||
{ |
|||
if (System_AreControlsLocked()) |
|||
{ |
|||
leds[Led_Address(led)] = CRGB::Red; |
|||
} |
|||
else if (!gPlayProperties.pausePlay) |
|||
{ // Hue-rainbow
|
|||
leds[Led_Address(led)].setHue((uint8_t)(85 - ((double)95 / NUM_LEDS) * led)); |
|||
} |
|||
} |
|||
if (gPlayProperties.pausePlay) |
|||
{ |
|||
leds[Led_Address(0)] = CRGB::Orange; |
|||
leds[(Led_Address(NUM_LEDS / 4)) % NUM_LEDS] = CRGB::Orange; |
|||
leds[(Led_Address(NUM_LEDS / 2)) % NUM_LEDS] = CRGB::Orange; |
|||
leds[(Led_Address(NUM_LEDS / 4 * 3)) % NUM_LEDS] = CRGB::Orange; |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ // ... but do things a little bit different for Webstream as there's no progress available
|
|||
if (lastSwitchTimestamp == 0 || (millis() - lastSwitchTimestamp >= ledSwitchInterval * 1000) || redrawProgress) |
|||
{ |
|||
redrawProgress = false; |
|||
lastSwitchTimestamp = millis(); |
|||
FastLED.clear(); |
|||
if (ledPosWebstream + 1 < NUM_LEDS) |
|||
{ |
|||
ledPosWebstream++; |
|||
} |
|||
else |
|||
{ |
|||
ledPosWebstream = 0; |
|||
} |
|||
if (System_AreControlsLocked()) |
|||
{ |
|||
leds[Led_Address(ledPosWebstream)] = CRGB::Red; |
|||
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS] = CRGB::Red; |
|||
} |
|||
else if (!gPlayProperties.pausePlay) |
|||
{ |
|||
leds[Led_Address(ledPosWebstream)].setHue(webstreamColor); |
|||
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS].setHue(webstreamColor++); |
|||
} |
|||
else if (gPlayProperties.pausePlay) |
|||
{ |
|||
leds[Led_Address(ledPosWebstream)] = CRGB::Orange; |
|||
leds[(Led_Address(ledPosWebstream) + NUM_LEDS / 2) % NUM_LEDS] = CRGB::Orange; |
|||
} |
|||
} |
|||
} |
|||
FastLED.show(); |
|||
vTaskDelay(portTICK_RATE_MS * 5); |
|||
} |
|||
} |
|||
//vTaskDelay(portTICK_RATE_MS * 10);
|
|||
esp_task_wdt_reset(); |
|||
} |
|||
vTaskDelete(NULL); |
|||
#endif
|
|||
} |
@ -0,0 +1,25 @@ |
|||
#pragma once |
|||
|
|||
typedef enum class LedIndicator |
|||
{ |
|||
BootComplete = 0, |
|||
Error, |
|||
Ok, |
|||
PlaylistProgress, |
|||
Rewind, |
|||
Voltage, |
|||
VoltageWarning |
|||
} LedIndicatorType; |
|||
|
|||
void Led_Init(void); |
|||
void Led_Exit(void); |
|||
void Led_Indicate(LedIndicatorType value); |
|||
void Led_SetPause(boolean value); |
|||
void Led_ResetToInitialBrightness(void); |
|||
void Led_ResetToNightBrightness(void); |
|||
uint8_t Led_GetBrightness(void); |
|||
void Led_SetBrightness(uint8_t value); |
|||
uint8_t AudioPlayer_GetInitVolume(void); |
|||
void AudioPlayer_SetInitVolume(uint8_t value); |
|||
uint8_t AudioPlayer_GetInitVolume(void); |
|||
void AudioPlayer_SetInitVolume(uint8_t value); |
@ -0,0 +1,46 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "LogRingBuffer.h"
|
|||
|
|||
// Serial-logging buffer
|
|||
uint8_t Log_BufferLength = 200; |
|||
char *Log_Buffer = (char *)calloc(Log_BufferLength, sizeof(char)); // Buffer for all log-messages
|
|||
|
|||
static LogRingBuffer Log_RingBuffer; |
|||
|
|||
void Log_Init(void) |
|||
{ |
|||
Serial.begin(115200); |
|||
Log_Buffer = (char *)x_calloc(Log_BufferLength, sizeof(char)); // Buffer for all log-messages
|
|||
} |
|||
|
|||
/* Wrapper-function for serial-logging (with newline)
|
|||
_logBuffer: char* to log |
|||
_minLogLevel: loglevel configured for this message. |
|||
If (SERIAL_LOGLEVEL <= _minLogLevel) message will be logged |
|||
*/ |
|||
void Log_Println(const char *_logBuffer, const uint8_t _minLogLevel) |
|||
{ |
|||
if (SERIAL_LOGLEVEL >= _minLogLevel) |
|||
{ |
|||
Serial.println(_logBuffer); |
|||
Log_RingBuffer.println(_logBuffer); |
|||
} |
|||
} |
|||
|
|||
/* Wrapper-function for serial-logging (without newline) */ |
|||
void Log_Print(const char *_logBuffer, const uint8_t _minLogLevel) |
|||
{ |
|||
if (SERIAL_LOGLEVEL >= _minLogLevel) |
|||
{ |
|||
Serial.print(_logBuffer); |
|||
Log_RingBuffer.print(_logBuffer); |
|||
} |
|||
} |
|||
|
|||
String Log_GetRingBuffer(void) |
|||
{ |
|||
return Log_RingBuffer.get(); |
|||
} |
@ -0,0 +1,24 @@ |
|||
#pragma once |
|||
#include "LogMessages.h" |
|||
|
|||
// Loglevels available (don't change!) |
|||
#define LOGLEVEL_ERROR 1 // only errors |
|||
#define LOGLEVEL_NOTICE 2 // errors + important messages |
|||
#define LOGLEVEL_INFO 3 // infos + errors + important messages |
|||
#define LOGLEVEL_DEBUG 4 // almost everything |
|||
|
|||
extern uint8_t Log_BufferLength; |
|||
extern char *Log_Buffer; // Buffer for all log-messages |
|||
|
|||
/* Wrapper-function for serial-logging (with newline) |
|||
_logBuffer: char* to log |
|||
_minLogLevel: loglevel configured for this message. |
|||
If (_currentLogLevel <= _minLogLevel) message will be logged |
|||
*/ |
|||
void Log_Println(const char *_logBuffer, const uint8_t _minLogLevel); |
|||
|
|||
/* Wrapper-function for serial-logging (without newline) */ |
|||
void Log_Print(const char *_logBuffer, const uint8_t _minLogLevel); |
|||
|
|||
void Log_Init(void); |
|||
String Log_GetRingBuffer(void); |
@ -0,0 +1,189 @@ |
|||
|
|||
#include "settings.h"
|
|||
|
|||
#if (LANGUAGE == 1)
|
|||
#include "Log.h"
|
|||
|
|||
const char stillOnlineMqtt[] PROGMEM = "MQTT: Bin noch online."; |
|||
const char tryConnectMqttS[] PROGMEM = "Versuche Verbindung zu MQTT-Broker aufzubauen"; |
|||
const char mqttOk[] PROGMEM = "MQTT-Session aufgebaut."; |
|||
const char sleepTimerEOP[] PROGMEM = "Sleep-Timer: Nach dem letzten Track der Playlist."; |
|||
const char sleepTimerEOT[] PROGMEM = "Sleep-Timer: Nach dem Ende des laufenden Tracks."; |
|||
const char sleepTimerStop[] PROGMEM = "Sleep-Timer wurde deaktiviert."; |
|||
const char sleepTimerEO5[] PROGMEM = "Sleep Timer: Nach Ende des Titels oder, wenn früher, Ende der Playlist"; |
|||
const char sleepTimerAlreadyStopped[] PROGMEM = "Sleep-Timer ist bereits deaktiviert."; |
|||
const char sleepTimerSetTo[] PROGMEM = "Sleep-Timer gesetzt auf"; |
|||
const char allowButtons[] PROGMEM = "Alle Tasten werden freigegeben."; |
|||
const char lockButtons[] PROGMEM = "Alle Tasten werden gesperrt."; |
|||
const char noPlaylistNotAllowedMqtt[] PROGMEM = "Playmode kann nicht auf 'Keine Playlist' gesetzt werden via MQTT."; |
|||
const char playmodeChangedMQtt[] PROGMEM = "Playmode per MQTT angepasst."; |
|||
const char noPlaymodeChangeIfIdle[] PROGMEM = "Playmode kann nicht verändert werden, wenn keine Playlist aktiv ist."; |
|||
const char noValidTopic[] PROGMEM = "Kein gültiges Topic"; |
|||
const char freePtr[] PROGMEM = "Ptr-Freigabe"; |
|||
const char freeMemory[] PROGMEM = "Freier Speicher"; |
|||
const char writeEntryToNvs[] PROGMEM = "Schreibe Eintrag in NVS"; |
|||
const char freeMemoryAfterFree[] PROGMEM = "Freier Speicher nach Aufräumen"; |
|||
const char releaseMemoryOfOldPlaylist[] PROGMEM = "Gebe Speicher der alten Playlist frei."; |
|||
const char dirOrFileDoesNotExist[] PROGMEM = "Datei oder Verzeichnis existiert nicht "; |
|||
const char unableToAllocateMemForPlaylist[] PROGMEM = "Speicher für Playlist konnte nicht allokiert werden!"; |
|||
const char unableToAllocateMem[] PROGMEM = "Speicher konnte nicht allokiert werden!"; |
|||
const char fileModeDetected[] PROGMEM = "Dateimodus erkannt."; |
|||
const char nameOfFileFound[] PROGMEM = "Gefundenes File"; |
|||
const char reallocCalled[] PROGMEM = "Speicher reallokiert."; |
|||
const char unableToAllocateMemForLinearPlaylist[] PROGMEM = "Speicher für lineare Playlist konnte nicht allokiert werden!"; |
|||
const char numberOfValidFiles[] PROGMEM = "Anzahl gültiger Files"; |
|||
const char newLoudnessReceivedQueue[] PROGMEM = "Neue Lautstärke empfangen via Queue"; |
|||
const char newCntrlReceivedQueue[] PROGMEM = "Kontroll-Kommando empfangen via Queue"; |
|||
const char newPlaylistReceived[] PROGMEM = "Neue Playlist empfangen"; |
|||
const char repeatTrackDueToPlaymode[] PROGMEM = "Wiederhole Titel aufgrund von Playmode."; |
|||
const char repeatPlaylistDueToPlaymode[] PROGMEM = "Wiederhole Playlist aufgrund von Playmode."; |
|||
const char cmndStop[] PROGMEM = "Kommando: Stop"; |
|||
const char cmndPause[] PROGMEM = "Kommando: Pause"; |
|||
const char cmndNextTrack[] PROGMEM = "Kommando: Nächster Titel"; |
|||
const char cmndPrevTrack[] PROGMEM = "Kommando: Vorheriger Titel"; |
|||
const char cmndFirstTrack[] PROGMEM = "Kommando: Erster Titel von Playlist"; |
|||
const char cmndLastTrack[] PROGMEM = "Kommando: Letzter Titel von Playlist"; |
|||
const char cmndDoesNotExist[] PROGMEM = "Dieses Kommando existiert nicht."; |
|||
const char lastTrackAlreadyActive[] PROGMEM = "Es wird bereits der letzte Track gespielt."; |
|||
const char firstTrackAlreadyActive[] PROGMEM = "Es wird bereits der erste Track gespielt."; |
|||
const char trackStartAudiobook[] PROGMEM = "Titel wird im Hörspielmodus von vorne gespielt."; |
|||
const char trackStart[] PROGMEM = "Titel wird von vorne gespielt."; |
|||
const char trackChangeWebstream[] PROGMEM = "Im Webradio-Modus kann nicht an den Anfang gesprungen werden."; |
|||
const char endOfPlaylistReached[] PROGMEM = "Ende der Playlist erreicht."; |
|||
const char trackStartatPos[] PROGMEM = "Titel wird abgespielt ab Position"; |
|||
const char rfidScannerReady[] PROGMEM = "RFID-Tags koennen jetzt gescannt werden..."; |
|||
const char rfidTagDetected[] PROGMEM = "RFID-Karte erkannt: "; |
|||
const char rfid15693TagDetected[] PROGMEM = "RFID-Karte (ISO-15693) erkannt: "; |
|||
const char rfidTagReceived[] PROGMEM = "RFID-Karte empfangen"; |
|||
const char rfidTagUnknownInNvs[] PROGMEM = "RFID-Karte ist im NVS nicht hinterlegt."; |
|||
const char goToSleepDueToIdle[] PROGMEM = "Gehe in Deep Sleep wegen Inaktivität..."; |
|||
const char goToSleepDueToTimer[] PROGMEM = "Gehe in Deep Sleep wegen Sleep Timer..."; |
|||
const char goToSleepNow[] PROGMEM = "Gehe jetzt in Deep Sleep!"; |
|||
const char maxLoudnessReached[] PROGMEM = "Maximale Lautstärke bereits erreicht!"; |
|||
const char minLoudnessReached[] PROGMEM = "Minimale Lautstärke bereits erreicht!"; |
|||
const char errorOccured[] PROGMEM = "Fehler aufgetreten!"; |
|||
const char noMp3FilesInDir[] PROGMEM = "Verzeichnis beinhaltet keine mp3-Files."; |
|||
const char modeSingleTrack[] PROGMEM = "Modus: Einzelner Track"; |
|||
const char modeSingleTrackLoop[] PROGMEM = "Modus: Einzelner Track in Endlosschleife"; |
|||
const char modeSingleAudiobook[] PROGMEM = "Modus: Hoerspiel"; |
|||
const char modeSingleAudiobookLoop[] PROGMEM = "Modus: Hoerspiel in Endlosschleife"; |
|||
const char modeAllTrackAlphSorted[] PROGMEM = "Modus: Spiele alle Tracks (alphabetisch sortiert) des Ordners"; |
|||
const char modeAllTrackRandom[] PROGMEM = "Modus: Alle Tracks eines Ordners zufällig"; |
|||
const char modeAllTrackAlphSortedLoop[] PROGMEM = "Modus: Alle Tracks eines Ordners sortiert (alphabetisch) in Endlosschleife"; |
|||
const char modeAllTrackRandomLoop[] PROGMEM = "Modus: Alle Tracks eines Ordners zufällig in Endlosschleife"; |
|||
const char modeWebstream[] PROGMEM = "Modus: Webstream"; |
|||
const char webstreamNotAvailable[] PROGMEM = "Aktuell kein Webstream möglich, da keine WLAN-Verbindung vorhanden!"; |
|||
const char modeDoesNotExist[] PROGMEM = "Abspielmodus existiert nicht!"; |
|||
const char modeRepeatNone[] PROGMEM = "Repeatmodus: Kein Repeat"; |
|||
const char modeRepeatTrack[] PROGMEM = "Repeatmodus: Aktueller Titel"; |
|||
const char modeRepeatPlaylist[] PROGMEM = "Repeatmodus: Gesamte Playlist"; |
|||
const char modeRepeatTracknPlaylist[] PROGMEM = "Repeatmodus: Track und Playlist"; |
|||
const char modificatorAllButtonsLocked[] PROGMEM = "Modifikator: Alle Tasten werden per RFID gesperrt."; |
|||
const char modificatorAllButtonsUnlocked[] PROGMEM = "Modifikator: Alle Tasten werden per RFID freigegeben."; |
|||
const char modificatorSleepd[] PROGMEM = "Modifikator: Sleep-Timer wieder deaktiviert."; |
|||
const char modificatorSleepTimer15[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (15 Minuten)."; |
|||
const char modificatorSleepTimer30[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (30 Minuten)."; |
|||
const char modificatorSleepTimer60[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (60 Minuten)."; |
|||
const char modificatorSleepTimer120[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (2 Stunden)."; |
|||
const char ledsDimmedToNightmode[] PROGMEM = "LEDs wurden auf Nachtmodus gedimmt."; |
|||
const char modificatorNotallowedWhenIdle[] PROGMEM = "Modifikator kann bei nicht aktivierter Playlist nicht angewendet werden."; |
|||
const char modificatorSleepAtEOT[] PROGMEM = "Modifikator: Sleep-Timer am Ende des Titels aktiviert."; |
|||
const char modificatorSleepAtEOTd[] PROGMEM = "Modifikator: Sleep-Timer am Ende des Titels deaktiviert."; |
|||
const char modificatorSleepAtEOP[] PROGMEM = "Modifikator: Sleep-Timer am Ende der Playlist aktiviert."; |
|||
const char modificatorSleepAtEOPd[] PROGMEM = "Modifikator: Sleep-Timer am Ende der Playlist deaktiviert."; |
|||
const char modificatorAllTrackAlphSortedLoop[] PROGMEM = "Modifikator: Alle Titel (alphabetisch sortiert) in Endlosschleife."; |
|||
const char modificatorAllTrackRandomLoop[] PROGMEM = "Modifikator: Alle Titel (zufällige Reihenfolge) in Endlosschleife."; |
|||
const char modificatorCurTrackLoop[] PROGMEM = "Modifikator: Aktueller Titel in Endlosschleife."; |
|||
const char modificatorCurAudiobookLoop[] PROGMEM = "Modifikator: Aktuelles Hörspiel in Endlosschleife."; |
|||
const char modificatorPlaylistLoopActive[] PROGMEM = "Modifikator: Alle Titel in Endlosschleife aktiviert."; |
|||
const char modificatorPlaylistLoopDeactive[] PROGMEM = "Modifikator: Alle Titel in Endlosschleife deaktiviert."; |
|||
const char modificatorTrackActive[] PROGMEM = "Modifikator: Titel in Endlosschleife aktiviert."; |
|||
const char modificatorTrackDeactive[] PROGMEM = "Modifikator: Titel in Endlosschleife deaktiviert."; |
|||
const char modificatorNotAllowed[] PROGMEM = "Modifikator konnte nicht angewendet werden."; |
|||
const char modificatorLoopRev[] PROGMEM = "Modifikator: Endlosschleife beendet."; |
|||
const char modificatorDoesNotExist[] PROGMEM = "Ein Karten-Modifikator existiert nicht vom Typ"; |
|||
const char errorOccuredNvs[] PROGMEM = "Es ist ein Fehler aufgetreten beim Lesen aus dem NVS!"; |
|||
const char statementsReceivedByServer[] PROGMEM = "Vom Server wurde Folgendes empfangen"; |
|||
const char savedSsidInNvs[] PROGMEM = "Speichere SSID in NVS"; |
|||
const char savedWifiPwdInNvs[] PROGMEM = "Speichere WLAN-Password in NVS"; |
|||
const char apReady[] PROGMEM = "Access-Point geöffnet"; |
|||
const char httpReady[] PROGMEM = "HTTP-Server gestartet."; |
|||
const char unableToMountSd[] PROGMEM = "SD-Karte konnte nicht gemountet werden."; |
|||
const char unableToCreateVolQ[] PROGMEM = "Konnte Volume-Queue nicht anlegen."; |
|||
const char unableToCreateRfidQ[] PROGMEM = "Konnte RFID-Queue nicht anlegen."; |
|||
const char unableToCreateMgmtQ[] PROGMEM = "Konnte Play-Management-Queue nicht anlegen."; |
|||
const char unableToCreatePlayQ[] PROGMEM = "Konnte Track-Queue nicht anlegen.."; |
|||
const char initialBrightnessfromNvs[] PROGMEM = "Initiale LED-Helligkeit wurde aus NVS geladen"; |
|||
const char wroteInitialBrightnessToNvs[] PROGMEM = "Initiale LED-Helligkeit wurde ins NVS geschrieben."; |
|||
const char restoredInitialBrightnessForNmFromNvs[] PROGMEM = "LED-Helligkeit für Nachtmodus wurde aus NVS geladen"; |
|||
const char wroteNmBrightnessToNvs[] PROGMEM = "LED-Helligkeit für Nachtmodus wurde ins NVS geschrieben."; |
|||
const char wroteFtpUserToNvs[] PROGMEM = "FTP-User wurde ins NVS geschrieben."; |
|||
const char restoredFtpUserFromNvs[] PROGMEM = "FTP-User wurde aus NVS geladen"; |
|||
const char wroteFtpPwdToNvs[] PROGMEM = "FTP-Passwort wurde ins NVS geschrieben."; |
|||
const char restoredFtpPwdFromNvs[] PROGMEM = "FTP-Passwort wurde aus NVS geladen"; |
|||
const char restoredMaxInactivityFromNvs[] PROGMEM = "Maximale Inaktivitätszeit wurde aus NVS geladen"; |
|||
const char wroteMaxInactivityToNvs[] PROGMEM = "Maximale Inaktivitätszeit wurde ins NVS geschrieben."; |
|||
const char restoredInitialLoudnessFromNvs[] PROGMEM = "Initiale Lautstärke wurde aus NVS geladen"; |
|||
const char wroteInitialLoudnessToNvs[] PROGMEM = "Initiale Lautstärke wurde ins NVS geschrieben."; |
|||
const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Maximale Lautstärke für Lautsprecher wurde aus NVS geladen"; |
|||
const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde aus NVS geladen"; |
|||
const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Maximale Lautstärke für Lautsprecher wurde ins NVS geschrieben."; |
|||
const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde ins NVS geschrieben."; |
|||
const char maxVolumeSet[] PROGMEM = "Maximale Lautstärke wurde gesetzt auf"; |
|||
const char wroteMqttFlagToNvs[] PROGMEM = "MQTT-Flag wurde ins NVS geschrieben."; |
|||
const char restoredMqttActiveFromNvs[] PROGMEM = "MQTT-Flag (aktiviert) wurde aus NVS geladen"; |
|||
const char restoredMqttDeactiveFromNvs[] PROGMEM = "MQTT-Flag (deaktiviert) wurde aus NVS geladen"; |
|||
const char wroteMqttServerToNvs[] PROGMEM = "MQTT-Server wurde ins NVS geschrieben."; |
|||
const char restoredMqttServerFromNvs[] PROGMEM = "MQTT-Server wurde aus NVS geladen"; |
|||
const char wroteMqttUserToNvs[] PROGMEM = "MQTT-User wurde ins NVS geschrieben."; |
|||
const char restoredMqttUserFromNvs[] PROGMEM = "MQTT-User wurde aus NVS geladen"; |
|||
const char wroteMqttPwdToNvs[] PROGMEM = "MQTT-Passwort wurde ins NVS geschrieben."; |
|||
const char restoredMqttPwdFromNvs[] PROGMEM = "MQTT-Passwort wurde aus NVS geladen"; |
|||
const char restoredMqttPortFromNvs[] PROGMEM = "MQTT-Port wurde aus NVS geladen"; |
|||
const char mqttWithPwd[] PROGMEM = "Verbinde zu MQTT-Server mit User und Passwort"; |
|||
const char mqttWithoutPwd[] PROGMEM = "Verbinde zu MQTT-Server ohne User und Passwort"; |
|||
const char ssidNotFoundInNvs[] PROGMEM = "SSID wurde im NVS nicht gefunden."; |
|||
const char wifiPwdNotFoundInNvs[] PROGMEM = "WLAN-Passwort wurde im NVS nicht gefunden."; |
|||
const char wifiStaticIpConfigNotFoundInNvs[] PROGMEM = "Statische WLAN-IP-Konfiguration wurde im NVS nicht gefunden."; |
|||
const char wifiHostnameNotSet[] PROGMEM = "Keine Hostname-Konfiguration im NVS gefunden."; |
|||
const char mqttConnFailed[] PROGMEM = "Verbindung fehlgeschlagen, versuche in Kürze erneut"; |
|||
const char restoredHostnameFromNvs[] PROGMEM = "Hostname aus NVS geladen"; |
|||
const char currentVoltageMsg[] PROGMEM = "Aktuelle Batteriespannung"; |
|||
const char voltageTooLow[] PROGMEM = "Batteriespannung niedrig"; |
|||
const char sdBootFailedDeepsleep[] PROGMEM = "Bootgang wegen SD fehlgeschlagen. Gehe in Deepsleep..."; |
|||
const char wifiEnabledAfterRestart[] PROGMEM = "WLAN wird aktiviert."; |
|||
const char wifiDisabledAfterRestart[] PROGMEM = "WLAN wird deaktiviert."; |
|||
const char voltageIndicatorLowFromNVS[] PROGMEM = "Unterer Spannungslevel (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
const char voltageIndicatorHighFromNVS[] PROGMEM = "Oberer Spannungslevel (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
const char voltageCheckIntervalFromNVS[] PROGMEM = "Zyklus für Spannungsmessung (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
const char warningLowVoltageFromNVS[] PROGMEM = "Spannungslevel (Batterie) fuer Warnung via Neopixel aus NVS geladen"; |
|||
const char unableToRestoreLastRfidFromNVS[] PROGMEM = "Letzte RFID konnte nicht aus NVS geladen werden"; |
|||
const char restoredLastRfidFromNVS[] PROGMEM = "Letzte RFID wurde aus NVS geladen"; |
|||
const char failedOpenFileForWrite[] PROGMEM = "Öffnen der Datei für den Schreibvorgang fehlgeschlagen"; |
|||
const char fileWritten[] PROGMEM = "Datei geschrieben"; |
|||
const char writeFailed[] PROGMEM = "Schreibvorgang fehlgeschlagen"; |
|||
const char writingFile[] PROGMEM = "Schreibe Datei"; |
|||
const char failedToOpenFileForAppending[] PROGMEM = "Öffnen der Datei zum Schreiben der JSON-Datei fehlgeschlagen"; |
|||
const char listingDirectory[] PROGMEM = "Verzeichnisinhalt anzeigen"; |
|||
const char failedToOpenDirectory[] PROGMEM = "Öffnen des Verzeichnisses fehlgeschlagen"; |
|||
const char notADirectory[] PROGMEM = "Kein Verzeichnis"; |
|||
const char sdMountedMmc1BitMode[] PROGMEM = "Versuche SD-Karte wird im SD_MMC-Modus (1 Bit) zu mounten..."; |
|||
const char sdMountedSpiMode[] PROGMEM = "Versuche SD-Karte wird im SPI-Modus zu mounten..."; |
|||
const char backupRecoveryWebsite[] PROGMEM = "<p>Das Backup-File wird eingespielt...<br />Zur letzten Seite <a href=\"javascript:history.back()\">zurückkehren</a>.</p>"; |
|||
const char restartWebsite[] PROGMEM = "<p>Der ESPuino wird neu gestartet...<br />Zur letzten Seite <a href=\"javascript:history.back()\">zurückkehren</a>.</p>"; |
|||
const char shutdownWebsite[] PROGMEM = "<p>Der ESPuino wird ausgeschaltet...</p>"; |
|||
const char mqttMsgReceived[] PROGMEM = "MQTT-Nachricht empfangen"; |
|||
const char trackPausedAtPos[] PROGMEM = "Titel pausiert bei Position"; |
|||
const char freeHeapWithoutFtp[] PROGMEM = "Freier Heap-Speicher vor FTP-Instanzierung"; |
|||
const char freeHeapWithFtp[] PROGMEM = "Freier Heap-Speicher nach FTP-Instanzierung"; |
|||
const char freeHeapAfterSetup[] PROGMEM = "Freier Heap-Speicher nach Setup-Routine"; |
|||
const char tryStaticIpConfig[] PROGMEM = "Statische IP-Konfiguration wird durchgeführt..."; |
|||
const char staticIPConfigFailed[] PROGMEM = "Statische IP-Konfiguration fehlgeschlagen"; |
|||
const char wakeUpRfidNoIso14443[] PROGMEM = "ESP32 wurde vom Kartenleser aus dem Deepsleep aufgeweckt. Allerdings wurde keine ISO-14443-Karte gefunden. Gehe zurück in den Deepsleep..."; |
|||
const char lowPowerCardSuccess[] PROGMEM = "Kartenerkennung via 'low power' erfolgreich durchgeführt"; |
|||
const char rememberLastVolume[] PROGMEM = "Lautstärke vor dem letzten Shutdown wird wiederhergestellt. Dies überschreibt die Einstellung der initialen Lautstärke aus der GUI."; |
|||
const char unableToStartFtpServer[] PROGMEM = "Der FTP-Server konnte nicht gestartet werden. Entweder weil er ist bereits gestartet oder kein WLAN verfügbar ist."; |
|||
const char newPlayModeStereo[] PROGMEM = "Neuer Modus: stereo"; |
|||
const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono"; |
|||
|
|||
#endif
|
@ -0,0 +1,189 @@ |
|||
|
|||
#include "settings.h"
|
|||
|
|||
#if (LANGUAGE == 2)
|
|||
#include "Log.h"
|
|||
|
|||
const char stillOnlineMqtt[] PROGMEM = "MQTT: still online."; |
|||
const char tryConnectMqttS[] PROGMEM = "Trying to connect to MQTT-broker"; |
|||
const char mqttOk[] PROGMEM = "MQTT-connection established."; |
|||
const char sleepTimerEOP[] PROGMEM = "Sleep-timer: after last track of playlist."; |
|||
const char sleepTimerEOT[] PROGMEM = "Sleep-timer: after end of current track."; |
|||
const char sleepTimerStop[] PROGMEM = "Sleep-timer has been disabled."; |
|||
const char sleepTimerEO5[] PROGMEM = "Sleep-timer: after five track or end of playlist - whatever is reached first"; |
|||
const char sleepTimerAlreadyStopped[] PROGMEM = "sleep-timer is already disabled."; |
|||
const char sleepTimerSetTo[] PROGMEM = "sleep-timer adjusted to"; |
|||
const char allowButtons[] PROGMEM = "Unlocking all keys."; |
|||
const char lockButtons[] PROGMEM = "Locking all keys."; |
|||
const char noPlaylistNotAllowedMqtt[] PROGMEM = "Playmode cannot be adjusted to 'no playlist' via MQTT."; |
|||
const char playmodeChangedMQtt[] PROGMEM = "Playlist adjusted via MQTT."; |
|||
const char noPlaymodeChangeIfIdle[] PROGMEM = "Playlist cannot be adjusted while no playlist is active."; |
|||
const char noValidTopic[] PROGMEM = "No valid MQTT-topic"; |
|||
const char freePtr[] PROGMEM = "Releasing Pointer"; |
|||
const char freeMemory[] PROGMEM = "Free memory"; |
|||
const char writeEntryToNvs[] PROGMEM = "Storing data to NVS"; |
|||
const char freeMemoryAfterFree[] PROGMEM = "Free memory after cleaning"; |
|||
const char releaseMemoryOfOldPlaylist[] PROGMEM = "Releasing memory of old playlist."; |
|||
const char dirOrFileDoesNotExist[] PROGMEM = "File of directory does not exist"; |
|||
const char unableToAllocateMemForPlaylist[] PROGMEM = "Unable to allocate memory for playlist!"; |
|||
const char unableToAllocateMem[] PROGMEM = "Unable to allocate memory!"; |
|||
const char fileModeDetected[] PROGMEM = "File-mode detected."; |
|||
const char nameOfFileFound[] PROGMEM = "File found"; |
|||
const char reallocCalled[] PROGMEM = "Reallocated memory."; |
|||
const char unableToAllocateMemForLinearPlaylist[] PROGMEM = "Unable to allocate memory for linear playlist!"; |
|||
const char numberOfValidFiles[] PROGMEM = "Number of valid files"; |
|||
const char newLoudnessReceivedQueue[] PROGMEM = "New volume received via queue"; |
|||
const char newCntrlReceivedQueue[] PROGMEM = "Control-command received via queue"; |
|||
const char newPlaylistReceived[] PROGMEM = "New playlist received"; |
|||
const char repeatTrackDueToPlaymode[] PROGMEM = "Repeating track due to playmode configured."; |
|||
const char repeatPlaylistDueToPlaymode[] PROGMEM = "Repeating playlist due to playmode configured."; |
|||
const char cmndStop[] PROGMEM = "Command: stop"; |
|||
const char cmndPause[] PROGMEM = "Command: pause"; |
|||
const char cmndNextTrack[] PROGMEM = "Command: next track"; |
|||
const char cmndPrevTrack[] PROGMEM = "Command: previous track"; |
|||
const char cmndFirstTrack[] PROGMEM = "Command: first track of playlist"; |
|||
const char cmndLastTrack[] PROGMEM = "Command: last track of playlist"; |
|||
const char cmndDoesNotExist[] PROGMEM = "Command requested does not exist."; |
|||
const char lastTrackAlreadyActive[] PROGMEM = "Already playing last track."; |
|||
const char firstTrackAlreadyActive[] PROGMEM = "Already playing first track."; |
|||
const char trackStartAudiobook[] PROGMEM = "Starting track in playmode from the very beginning."; |
|||
const char trackStart[] PROGMEM = "Starting track from the very beginning."; |
|||
const char trackChangeWebstream[] PROGMEM = "Playing from the very beginning is not possible while webradio-mode is active."; |
|||
const char endOfPlaylistReached[] PROGMEM = "Reached end of playlist."; |
|||
const char trackStartatPos[] PROGMEM = "Starting track at position"; |
|||
const char rfidScannerReady[] PROGMEM = "RFID-tags can now be applied..."; |
|||
const char rfidTagDetected[] PROGMEM = "RFID-tag detected: "; |
|||
const char rfid15693TagDetected[] PROGMEM = "RFID-ta (ISO-15693) detected: "; |
|||
const char rfidTagReceived[] PROGMEM = "RFID-tag received"; |
|||
const char rfidTagUnknownInNvs[] PROGMEM = "RFID-tag is unkown to NVS."; |
|||
const char goToSleepDueToIdle[] PROGMEM = "Going to deepsleep due to inactivity-timer..."; |
|||
const char goToSleepDueToTimer[] PROGMEM = "Going to deepsleep due to sleep timer..."; |
|||
const char goToSleepNow[] PROGMEM = "Going to deepsleep now!"; |
|||
const char maxLoudnessReached[] PROGMEM = "Already reached max volume!"; |
|||
const char minLoudnessReached[] PROGMEM = "Already reached min volume!"; |
|||
const char errorOccured[] PROGMEM = "Error occured!"; |
|||
const char noMp3FilesInDir[] PROGMEM = "Directory does not contain mp3-files."; |
|||
const char modeSingleTrack[] PROGMEM = "Mode: Single track"; |
|||
const char modeSingleTrackLoop[] PROGMEM = "Mode: single track as infinite loop"; |
|||
const char modeSingleAudiobook[] PROGMEM = "Mode: audiobook"; |
|||
const char modeSingleAudiobookLoop[] PROGMEM = "Mode: audiobook as infinite loop"; |
|||
const char modeAllTrackAlphSorted[] PROGMEM = "Mode: all tracks (in alph. order) of directory"; |
|||
const char modeAllTrackRandom[] PROGMEM = "Mode: all tracks (in random. order) of directory"; |
|||
const char modeAllTrackAlphSortedLoop[] PROGMEM = "Mode: all tracks (in alph. order) of directory as infinite loop"; |
|||
const char modeAllTrackRandomLoop[] PROGMEM = "Mode: all tracks (in random order) of directory as infinite loop"; |
|||
const char modeWebstream[] PROGMEM = "Mode: webstream"; |
|||
const char webstreamNotAvailable[] PROGMEM = "Unable to access webstream as no wifi-connection is available!"; |
|||
const char modeDoesNotExist[] PROGMEM = "Playmode does not exist!"; |
|||
const char modeRepeatNone[] PROGMEM = "Repeatmode: no repeat"; |
|||
const char modeRepeatTrack[] PROGMEM = "Repeatmode: current track"; |
|||
const char modeRepeatPlaylist[] PROGMEM = "Repeatmode: whole playlist"; |
|||
const char modeRepeatTracknPlaylist[] PROGMEM = "Repeatmode: track and playlist"; |
|||
const char modificatorAllButtonsLocked[] PROGMEM = "Modificator: locking all keys via RFID-tag."; |
|||
const char modificatorAllButtonsUnlocked[] PROGMEM = "Modificator: unlocking all keys via RFID-tag."; |
|||
const char modificatorSleepd[] PROGMEM = "Modificator: sleep-Timer deactivated."; |
|||
const char modificatorSleepTimer15[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (15 minutes)."; |
|||
const char modificatorSleepTimer30[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (30 minutes)."; |
|||
const char modificatorSleepTimer60[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (60 minutes)."; |
|||
const char modificatorSleepTimer120[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (2 hours)."; |
|||
const char ledsDimmedToNightmode[] PROGMEM = "Dimmed LEDs to nightmode."; |
|||
const char modificatorNotallowedWhenIdle[] PROGMEM = "Modificator cannot be applied while playlist is inactive."; |
|||
const char modificatorSleepAtEOT[] PROGMEM = "Modificator: adjusted sleep-timer to after end of current track."; |
|||
const char modificatorSleepAtEOTd[] PROGMEM = "Modificator: disabled sleep-timer after end of current track."; |
|||
const char modificatorSleepAtEOP[] PROGMEM = "Modificator: adjusted sleep-timer to after end of playlist."; |
|||
const char modificatorSleepAtEOPd[] PROGMEM = "Modificator: disabled sleep-timer after end of playlist."; |
|||
const char modificatorAllTrackAlphSortedLoop[] PROGMEM = "Modificator: adjusted to all tracks (in alph. order) as infinite loop."; |
|||
const char modificatorAllTrackRandomLoop[] PROGMEM = "Modificator: adjusted to all tracks (in random order) as infinite loop."; |
|||
const char modificatorCurTrackLoop[] PROGMEM = "Modificator: adjusted to current track as infinite loop."; |
|||
const char modificatorCurAudiobookLoop[] PROGMEM = "Modificator: adjusted to current audiobook as infinite loop."; |
|||
const char modificatorPlaylistLoopActive[] PROGMEM = "Modificator: adjusted to all tracks as infinite loop."; |
|||
const char modificatorPlaylistLoopDeactive[] PROGMEM = "Modificator: disabled all tracks as infinite loop."; |
|||
const char modificatorTrackActive[] PROGMEM = "Modificator: adjusted to current track as infinite loop."; |
|||
const char modificatorTrackDeactive[] PROGMEM = "Modificator: disabled current track as infinite loop."; |
|||
const char modificatorNotAllowed[] PROGMEM = "Unable to apply modificator."; |
|||
const char modificatorLoopRev[] PROGMEM = "Modificator: infinite loop ended."; |
|||
const char modificatorDoesNotExist[] PROGMEM = "This type of card-modificator does not exist"; |
|||
const char errorOccuredNvs[] PROGMEM = "Error occured while reading from NVS!"; |
|||
const char statementsReceivedByServer[] PROGMEM = "Data received from server"; |
|||
const char savedSsidInNvs[] PROGMEM = "Storing SSID to NVS"; |
|||
const char savedWifiPwdInNvs[] PROGMEM = "Storing wifi-password to NVS"; |
|||
const char apReady[] PROGMEM = "Started wifi-access-point"; |
|||
const char httpReady[] PROGMEM = "Started HTTP-server."; |
|||
const char unableToMountSd[] PROGMEM = "Unable to mount sd-card."; |
|||
const char unableToCreateVolQ[] PROGMEM = "Unable to create volume-queue."; |
|||
const char unableToCreateRfidQ[] PROGMEM = "Unable to create RFID-queue."; |
|||
const char unableToCreateMgmtQ[] PROGMEM = "Unable to play-management-queue."; |
|||
const char unableToCreatePlayQ[] PROGMEM = "Unable to create track-queue.."; |
|||
const char initialBrightnessfromNvs[] PROGMEM = "Restoring initial LED-brightness from NVS"; |
|||
const char wroteInitialBrightnessToNvs[] PROGMEM = "Storing initial LED-brightness to NVS."; |
|||
const char restoredInitialBrightnessForNmFromNvs[] PROGMEM = "Restored LED-brightness for nightmode from NVS"; |
|||
const char wroteNmBrightnessToNvs[] PROGMEM = "Stored LED-brightness for nightmode to NVS."; |
|||
const char wroteFtpUserToNvs[] PROGMEM = "Stored FTP-user to NVS."; |
|||
const char restoredFtpUserFromNvs[] PROGMEM = "Restored FTP-user from NVS"; |
|||
const char wroteFtpPwdToNvs[] PROGMEM = "Stored FTP-password to NVS."; |
|||
const char restoredFtpPwdFromNvs[] PROGMEM = "Restored FTP-password from NVS"; |
|||
const char restoredMaxInactivityFromNvs[] PROGMEM = "Restored maximum inactivity-time from NVS."; |
|||
const char wroteMaxInactivityToNvs[] PROGMEM = "Stored maximum inactivity-time to NVS."; |
|||
const char restoredInitialLoudnessFromNvs[] PROGMEM = "Restored initial volume from NVS"; |
|||
const char wroteInitialLoudnessToNvs[] PROGMEM = "Stored initial volume to NVS."; |
|||
const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Restored maximum volume for speaker from NVS"; |
|||
const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Restored maximum volume for headphone from NVS"; |
|||
const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Wrote maximum volume for speaker to NVS."; |
|||
const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Wrote maximum volume for headphone to NVS."; |
|||
const char maxVolumeSet[] PROGMEM = "Maximum volume set to"; |
|||
const char wroteMqttFlagToNvs[] PROGMEM = "Stored MQTT-flag to NVS."; |
|||
const char restoredMqttActiveFromNvs[] PROGMEM = "Restored MQTT-flag (enabled) from NVS"; |
|||
const char restoredMqttDeactiveFromNvs[] PROGMEM = "Restored MQTT-flag (disabled) from NVS"; |
|||
const char wroteMqttServerToNvs[] PROGMEM = "Stored MQTT-server to NVS."; |
|||
const char restoredMqttServerFromNvs[] PROGMEM = "Restored MQTT-Server from NVS"; |
|||
const char wroteMqttUserToNvs[] PROGMEM = "Stored MQTT-user to NVS."; |
|||
const char restoredMqttUserFromNvs[] PROGMEM = "Restored MQTT-user from NVS"; |
|||
const char wroteMqttPwdToNvs[] PROGMEM = "Stored MQTT-password to NVS."; |
|||
const char restoredMqttPwdFromNvs[] PROGMEM = "Restored MQTT-password from NVS"; |
|||
const char restoredMqttPortFromNvs[] PROGMEM = "Restored MQTT-port from NVS"; |
|||
const char mqttWithPwd[] PROGMEM = "Try to connect to MQTT-server with user und password"; |
|||
const char mqttWithoutPwd[] PROGMEM = "Try to connect to MQTT-server without user und password"; |
|||
const char ssidNotFoundInNvs[] PROGMEM = "Unable to find SSID to NVS."; |
|||
const char wifiPwdNotFoundInNvs[] PROGMEM = "Unable to find wifi-password to NVS."; |
|||
const char wifiStaticIpConfigNotFoundInNvs[] PROGMEM = "Unable to find wifi-ip-configuration to NVS."; |
|||
const char wifiHostnameNotSet[] PROGMEM = "Unable to find hostname-configuration to NVS."; |
|||
const char mqttConnFailed[] PROGMEM = "Unable to establish mqtt-connection, trying again..."; |
|||
const char restoredHostnameFromNvs[] PROGMEM = "Restored hostname from NVS"; |
|||
const char currentVoltageMsg[] PROGMEM = "Current battery-voltage"; |
|||
const char voltageTooLow[] PROGMEM = "Low battery-voltage"; |
|||
const char sdBootFailedDeepsleep[] PROGMEM = "Failed to boot due to SD. Will go to deepsleep..."; |
|||
const char wifiEnabledAfterRestart[] PROGMEM = "WiFi will be enabled."; |
|||
const char wifiDisabledAfterRestart[] PROGMEM = "WiFi will be disabled ."; |
|||
const char voltageIndicatorLowFromNVS[] PROGMEM = "Restored lower voltage-level for Neopixel-display from NVS"; |
|||
const char voltageIndicatorHighFromNVS[] PROGMEM = "Restored upper voltage-level for Neopixel-display from NVS"; |
|||
const char voltageCheckIntervalFromNVS[] PROGMEM = "Restored interval of battery-measurement or Neopixel-display from NVS"; |
|||
const char warningLowVoltageFromNVS[] PROGMEM = "Restored battery-voltage-level for warning via Neopixel from NVS"; |
|||
const char unableToRestoreLastRfidFromNVS[] PROGMEM = "Unable to restore last RFID from NVS"; |
|||
const char restoredLastRfidFromNVS[] PROGMEM = "Restored last RFID from NVS"; |
|||
const char failedOpenFileForWrite[] PROGMEM = "Failed to open file for writing"; |
|||
const char fileWritten[] PROGMEM = "File written"; |
|||
const char writeFailed[] PROGMEM = "Write failed"; |
|||
const char writingFile[] PROGMEM = "Writing file"; |
|||
const char failedToOpenFileForAppending[] PROGMEM = "Failed to open file for appending"; |
|||
const char listingDirectory[] PROGMEM = "Listing directory"; |
|||
const char failedToOpenDirectory[] PROGMEM = "Failed to open directory"; |
|||
const char notADirectory[] PROGMEM = "Not a directory"; |
|||
const char sdMountedMmc1BitMode[] PROGMEM = "SD card mounted in SPI-mode configured..."; |
|||
const char sdMountedSpiMode[] PROGMEM = "Mounting SD card in SPI-mode..."; |
|||
const char backupRecoveryWebsite[] PROGMEM = "<p>Backup-file is being applied...<br />Back to <a href=\"javascript:history.back()\">last page</a>.</p>"; |
|||
const char restartWebsite[] PROGMEM = "<p>ESPuino is being restarted...<br />Back to <a href=\"javascript:history.back()\">last page</a>.</p>"; |
|||
const char shutdownWebsite[] PROGMEM = "<p>Der ESPuino is being shutdown...</p>"; |
|||
const char mqttMsgReceived[] PROGMEM = "MQTT-message received"; |
|||
const char trackPausedAtPos[] PROGMEM = "Track paused at position"; |
|||
const char freeHeapWithoutFtp[] PROGMEM = "Free heap before FTP-allocation"; |
|||
const char freeHeapWithFtp[] PROGMEM = "Free heap after FTP-allocation"; |
|||
const char freeHeapAfterSetup[] PROGMEM = "Free heap after setup"; |
|||
const char tryStaticIpConfig[] PROGMEM = "Performing IP-configuration..."; |
|||
const char staticIPConfigFailed[] PROGMEM = "IP-configuration failed"; |
|||
const char wakeUpRfidNoIso14443[] PROGMEM = "Wakeup caused by low power card-detection. RF-field changed but no ISO-14443 card on reader was found. So I'll return back to sleep now..."; |
|||
const char lowPowerCardSuccess[] PROGMEM = "Switch to low power card-detection: success"; |
|||
const char rememberLastVolume[] PROGMEM = "Restored volume used before last shutdown. This overwrites the initial volume configured via webgui."; |
|||
const char unableToStartFtpServer[] PROGMEM = "FTP-server cannot be started. This is because FTP-service is already active of because WiFi is unavailable."; |
|||
const char newPlayModeStereo[] PROGMEM = "New mode: stereo"; |
|||
const char newPlayModeMono[] PROGMEM = "New mode: mono"; |
|||
|
|||
#endif
|
@ -0,0 +1,54 @@ |
|||
#include <Arduino.h>
|
|||
#include "MemX.h"
|
|||
|
|||
// Wraps strdup(). Without PSRAM, strdup is called => so heap is used.
|
|||
// With PSRAM being available, the same is done what strdup() does, but with allocation on PSRAM.
|
|||
char * x_strdup(const char *_str) { |
|||
if (!psramInit()) { |
|||
return strdup(_str); |
|||
} else { |
|||
char *dst = (char *) ps_malloc(strlen (_str) + 1); |
|||
if (dst == NULL) { |
|||
return NULL; |
|||
} |
|||
strcpy(dst, _str); |
|||
return dst; |
|||
} |
|||
} |
|||
|
|||
|
|||
// Wraps strndup(). Without PSRAM, strdup is called => so heap is used.
|
|||
// With PSRAM being available, the same is done what strndup() does, but with allocation on PSRAM.
|
|||
char * x_strndup(const char *_str, uint32_t _len) { |
|||
if (!psramInit()) { |
|||
return strndup(_str, _len); |
|||
} else { |
|||
char *dst = (char *) ps_malloc(_len + 1); |
|||
if (dst == NULL) { |
|||
return NULL; |
|||
} |
|||
strncpy(dst, _str, _len); |
|||
dst[_len] = '\0'; |
|||
return dst; |
|||
} |
|||
} |
|||
|
|||
|
|||
// Wraps ps_malloc() and malloc(). Selection depends on whether PSRAM is available or not.
|
|||
char * x_malloc(uint32_t _allocSize) { |
|||
if (psramInit()) { |
|||
return (char *) ps_malloc(_allocSize); |
|||
} else { |
|||
return (char *) malloc(_allocSize); |
|||
} |
|||
} |
|||
|
|||
|
|||
// Wraps ps_calloc() and calloc(). Selection depends on whether PSRAM is available or not.
|
|||
char * x_calloc(uint32_t _allocSize, uint32_t _unitSize) { |
|||
if (psramInit()) { |
|||
return (char *) ps_calloc(_allocSize, _unitSize); |
|||
} else { |
|||
return (char *) calloc(_allocSize, _unitSize); |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
#pragma once |
|||
|
|||
char *x_calloc(uint32_t _allocSize, uint32_t _unitSize); |
|||
char *x_malloc(uint32_t _allocSize); |
|||
char *x_strdup(const char *_str); |
|||
char *x_strndup(const char *_str, uint32_t _len); |
@ -0,0 +1,516 @@ |
|||
#include <Arduino.h>
|
|||
#include <WiFi.h>
|
|||
#include "settings.h"
|
|||
#include "Mqtt.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Led.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "System.h"
|
|||
#include "Queues.h"
|
|||
#include "Wlan.h"
|
|||
|
|||
#ifdef MQTT_ENABLE
|
|||
#define MQTT_SOCKET_TIMEOUT 1 // https://github.com/knolleary/pubsubclient/issues/403
|
|||
#include <PubSubClient.h>
|
|||
#endif
|
|||
|
|||
constexpr uint8_t stillOnlineInterval = 60u; // Interval 'I'm still alive' is sent via MQTT (in seconds)
|
|||
|
|||
// MQTT-helper
|
|||
#ifdef MQTT_ENABLE
|
|||
static WiFiClient Mqtt_WifiClient; |
|||
static PubSubClient Mqtt_PubSubClient(Mqtt_WifiClient); |
|||
#endif
|
|||
|
|||
// Please note: all of them are defaults that can be changed later via GUI
|
|||
char *gMqttServer = x_strndup((char *)"192.168.2.43", mqttServerLength); // IP-address of MQTT-server (if not found in NVS this one will be taken)
|
|||
char *gMqttUser = x_strndup((char *)"mqtt-user", mqttUserLength); // MQTT-user
|
|||
char *gMqttPassword = x_strndup((char *)"mqtt-password", mqttPasswordLength); // MQTT-password*/
|
|||
uint16_t gMqttPort = 1883; // MQTT-Port
|
|||
|
|||
// MQTT
|
|||
static bool Mqtt_Enabled = true; |
|||
|
|||
static void Mqtt_ClientCallback(const char *topic, const byte *payload, uint32_t length); |
|||
static bool Mqtt_Reconnect(void); |
|||
static void Mqtt_PostHeartbeatViaMqtt(void); |
|||
|
|||
void Mqtt_Init() |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
// Get MQTT-enable from NVS
|
|||
uint8_t nvsEnableMqtt = gPrefsSettings.getUChar("enableMQTT", 99); |
|||
switch (nvsEnableMqtt) |
|||
{ |
|||
case 99: |
|||
gPrefsSettings.putUChar("enableMQTT", Mqtt_Enabled); |
|||
Log_Println((char *)FPSTR(wroteMqttFlagToNvs), LOGLEVEL_ERROR); |
|||
break; |
|||
case 1: |
|||
Mqtt_Enabled = nvsEnableMqtt; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(restoredMqttActiveFromNvs), nvsEnableMqtt); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
break; |
|||
case 0: |
|||
Mqtt_Enabled = nvsEnableMqtt; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(restoredMqttDeactiveFromNvs), nvsEnableMqtt); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
break; |
|||
} |
|||
|
|||
// Get MQTT-server from NVS
|
|||
String nvsMqttServer = gPrefsSettings.getString("mqttServer", "-1"); |
|||
if (!nvsMqttServer.compareTo("-1")) |
|||
{ |
|||
gPrefsSettings.putString("mqttServer", (String)gMqttServer); |
|||
Log_Println((char *)FPSTR(wroteMqttServerToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
else |
|||
{ |
|||
strncpy(gMqttServer, nvsMqttServer.c_str(), mqttServerLength); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredMqttServerFromNvs), nvsMqttServer.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Get MQTT-user from NVS
|
|||
String nvsMqttUser = gPrefsSettings.getString("mqttUser", "-1"); |
|||
if (!nvsMqttUser.compareTo("-1")) |
|||
{ |
|||
gPrefsSettings.putString("mqttUser", (String)gMqttUser); |
|||
Log_Println((char *)FPSTR(wroteMqttUserToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
else |
|||
{ |
|||
strncpy(gMqttUser, nvsMqttUser.c_str(), mqttUserLength); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredMqttUserFromNvs), nvsMqttUser.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Get MQTT-password from NVS
|
|||
String nvsMqttPassword = gPrefsSettings.getString("mqttPassword", "-1"); |
|||
if (!nvsMqttPassword.compareTo("-1")) |
|||
{ |
|||
gPrefsSettings.putString("mqttPassword", (String)gMqttPassword); |
|||
Log_Println((char *)FPSTR(wroteMqttPwdToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
else |
|||
{ |
|||
strncpy(gMqttPassword, nvsMqttPassword.c_str(), mqttPasswordLength); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredMqttPwdFromNvs), nvsMqttPassword.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Get MQTT-password from NVS
|
|||
uint32_t nvsMqttPort = gPrefsSettings.getUInt("mqttPort", 99999); |
|||
if (nvsMqttPort == 99999) |
|||
{ |
|||
gPrefsSettings.putUInt("mqttPort", gMqttPort); |
|||
} |
|||
else |
|||
{ |
|||
gMqttPort = nvsMqttPort; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(restoredMqttPortFromNvs), gMqttPort); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Only enable MQTT if requested
|
|||
if (Mqtt_Enabled) |
|||
{ |
|||
Mqtt_PubSubClient.setServer(gMqttServer, gMqttPort); |
|||
Mqtt_PubSubClient.setCallback(Mqtt_ClientCallback); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void Mqtt_Cyclic(void) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
if (Mqtt_Enabled && Wlan_IsConnected()) |
|||
{ |
|||
Mqtt_Reconnect(); |
|||
Mqtt_PubSubClient.loop(); |
|||
Mqtt_PostHeartbeatViaMqtt(); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
void Mqtt_Exit(void) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicState), "Offline", false); |
|||
publishMqtt((char *)FPSTR(topicTrackState), "---", false); |
|||
Mqtt_PubSubClient.disconnect(); |
|||
#endif
|
|||
} |
|||
|
|||
bool Mqtt_IsEnabled(void) |
|||
{ |
|||
return Mqtt_Enabled; |
|||
} |
|||
|
|||
/* Wrapper-functions for MQTT-publish */ |
|||
bool publishMqtt(const char *topic, const char *payload, bool retained) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
if (strcmp(topic, "") != 0) |
|||
{ |
|||
if (Mqtt_PubSubClient.connected()) |
|||
{ |
|||
Mqtt_PubSubClient.publish(topic, payload, retained); |
|||
delay(100); |
|||
return true; |
|||
} |
|||
} |
|||
#endif
|
|||
return false; |
|||
} |
|||
|
|||
bool publishMqtt(const char *topic, int32_t payload, bool retained) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
char buf[11]; |
|||
snprintf(buf, sizeof(buf) / sizeof(buf[0]), "%d", payload); |
|||
return publishMqtt(topic, buf, retained); |
|||
#else
|
|||
return false; |
|||
#endif
|
|||
} |
|||
|
|||
bool publishMqtt(const char *topic, unsigned long payload, bool retained) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
char buf[11]; |
|||
snprintf(buf, sizeof(buf) / sizeof(buf[0]), "%lu", payload); |
|||
return publishMqtt(topic, buf, retained); |
|||
#else
|
|||
return false; |
|||
#endif
|
|||
} |
|||
|
|||
bool publishMqtt(const char *topic, uint32_t payload, bool retained) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
char buf[11]; |
|||
snprintf(buf, sizeof(buf) / sizeof(buf[0]), "%u", payload); |
|||
return publishMqtt(topic, buf, retained); |
|||
#else
|
|||
return false; |
|||
#endif
|
|||
} |
|||
|
|||
/* Cyclic posting via MQTT that ESP is still alive. Use case: when ESPuino is switched off, it will post via
|
|||
MQTT it's gonna be offline now. But when unplugging ESPuino e.g. openHAB doesn't know ESPuino is offline. |
|||
One way to recognize this is to determine, when a topic has been updated for the last time. So by |
|||
telling openHAB connection is timed out after 2mins for instance, this is the right topic to check for. */ |
|||
void Mqtt_PostHeartbeatViaMqtt(void) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
static unsigned long lastOnlineTimestamp = 0u; |
|||
|
|||
if (millis() - lastOnlineTimestamp >= stillOnlineInterval * 1000) |
|||
{ |
|||
lastOnlineTimestamp = millis(); |
|||
if (publishMqtt((char *)FPSTR(topicState), "Online", false)) |
|||
{ |
|||
Log_Println((char *)FPSTR(stillOnlineMqtt), LOGLEVEL_DEBUG); |
|||
} |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
/* Connects/reconnects to MQTT-Broker unless connection is not already available.
|
|||
Manages MQTT-subscriptions. |
|||
*/ |
|||
bool Mqtt_Reconnect() |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
static uint32_t mqttLastRetryTimestamp = 0u; |
|||
uint8_t connect = false; |
|||
uint8_t i = 0; |
|||
|
|||
if (!mqttLastRetryTimestamp || millis() - mqttLastRetryTimestamp >= mqttRetryInterval * 1000) |
|||
{ |
|||
mqttLastRetryTimestamp = millis(); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
while (!Mqtt_PubSubClient.connected() && i < mqttMaxRetriesPerInterval) |
|||
{ |
|||
i++; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s %s", (char *)FPSTR(tryConnectMqttS), gMqttServer); |
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
|
|||
// Try to connect to MQTT-server. If username AND password are set, they'll be used
|
|||
if (strlen(gMqttUser) < 1 || strlen(gMqttPassword) < 1) |
|||
{ |
|||
Log_Println((char *)FPSTR(mqttWithoutPwd), LOGLEVEL_NOTICE); |
|||
if (Mqtt_PubSubClient.connect(DEVICE_HOSTNAME)) |
|||
{ |
|||
connect = true; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(mqttWithPwd), LOGLEVEL_NOTICE); |
|||
if (Mqtt_PubSubClient.connect(DEVICE_HOSTNAME, gMqttUser, gMqttPassword)) |
|||
{ |
|||
connect = true; |
|||
} |
|||
} |
|||
if (connect) |
|||
{ |
|||
Log_Println((char *)FPSTR(mqttOk), LOGLEVEL_NOTICE); |
|||
|
|||
// Deepsleep-subscription
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicSleepCmnd)); |
|||
|
|||
// RFID-Tag-ID-subscription
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicRfidCmnd)); |
|||
|
|||
// Loudness-subscription
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicLoudnessCmnd)); |
|||
|
|||
// Sleep-Timer-subscription
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicSleepTimerCmnd)); |
|||
|
|||
// Next/previous/stop/play-track-subscription
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicTrackControlCmnd)); |
|||
|
|||
// Lock controls
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicLockControlsCmnd)); |
|||
|
|||
// Current repeat-Mode
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicRepeatModeCmnd)); |
|||
|
|||
// LED-brightness
|
|||
Mqtt_PubSubClient.subscribe((char *)FPSTR(topicLedBrightnessCmnd)); |
|||
|
|||
// Publish some stuff
|
|||
publishMqtt((char *)FPSTR(topicState), "Online", false); |
|||
publishMqtt((char *)FPSTR(topicTrackState), "---", false); |
|||
publishMqtt((char *)FPSTR(topicLoudnessState), AudioPlayer_GetCurrentVolume(), false); |
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), System_GetSleepTimerTimeStamp(), false); |
|||
publishMqtt((char *)FPSTR(topicLockControlsState), "OFF", false); |
|||
publishMqtt((char *)FPSTR(topicPlaymodeState), gPlayProperties.playMode, false); |
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), 0, false); |
|||
publishMqtt((char *)FPSTR(topicCurrentIPv4IP), Wlan_GetIpAddress().c_str(), false); |
|||
|
|||
return Mqtt_PubSubClient.connected(); |
|||
} |
|||
else |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: rc=%i (%d / %d)", (char *)FPSTR(mqttConnFailed), Mqtt_PubSubClient.state(), i, mqttMaxRetriesPerInterval); |
|||
Log_Println(Log_Buffer, LOGLEVEL_ERROR); |
|||
} |
|||
} |
|||
return false; |
|||
#endif
|
|||
} |
|||
|
|||
// Is called if there's a new MQTT-message for us
|
|||
void Mqtt_ClientCallback(const char *topic, const byte *payload, uint32_t length) |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
char *receivedString = x_strndup((char *)payload, length); |
|||
char *mqttTopic = x_strdup(topic); |
|||
|
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: [Topic: %s] [Command: %s]", (char *)FPSTR(mqttMsgReceived), mqttTopic, receivedString); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
|
|||
// Go to sleep?
|
|||
if (strcmp_P(topic, topicSleepCmnd) == 0) |
|||
{ |
|||
if ((strcmp(receivedString, "OFF") == 0) || (strcmp(receivedString, "0") == 0)) |
|||
{ |
|||
System_RequestSleep(); |
|||
} |
|||
} |
|||
|
|||
// New track to play? Take RFID-ID as input
|
|||
else if (strcmp_P(topic, topicRfidCmnd) == 0) |
|||
{ |
|||
char *_rfidId = x_strdup(receivedString); |
|||
xQueueSend(gRfidCardQueue, &_rfidId, 0); |
|||
//free(_rfidId);
|
|||
} |
|||
// Loudness to change?
|
|||
else if (strcmp_P(topic, topicLoudnessCmnd) == 0) |
|||
{ |
|||
unsigned long vol = strtoul(receivedString, NULL, 10); |
|||
AudioPlayer_VolumeToQueueSender(vol, true); |
|||
} |
|||
// Modify sleep-timer?
|
|||
else if (strcmp_P(topic, topicSleepTimerCmnd) == 0) |
|||
{ |
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ // Don't allow sleep-modications if no playlist is active
|
|||
Log_Println((char *)FPSTR(modificatorNotallowedWhenIdle), LOGLEVEL_INFO); |
|||
publishMqtt((char *)FPSTR(topicSleepState), 0, false); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
if (strcmp(receivedString, "EOP") == 0) |
|||
{ |
|||
gPlayProperties.sleepAfterPlaylist = true; |
|||
Log_Println((char *)FPSTR(sleepTimerEOP), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
return; |
|||
} |
|||
else if (strcmp(receivedString, "EOT") == 0) |
|||
{ |
|||
gPlayProperties.sleepAfterCurrentTrack = true; |
|||
Log_Println((char *)FPSTR(sleepTimerEOT), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
return; |
|||
} |
|||
else if (strcmp(receivedString, "EO5T") == 0) |
|||
{ |
|||
if ((gPlayProperties.numberOfTracks - 1) >= (gPlayProperties.currentTrackNumber + 5)) |
|||
{ |
|||
gPlayProperties.playUntilTrackNumber = gPlayProperties.currentTrackNumber + 5; |
|||
} |
|||
else |
|||
{ |
|||
gPlayProperties.sleepAfterPlaylist = true; |
|||
} |
|||
Log_Println((char *)FPSTR(sleepTimerEO5), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
return; |
|||
} |
|||
else if (strcmp(receivedString, "0") == 0) |
|||
{ |
|||
if (System_IsSleepTimerEnabled()) |
|||
{ |
|||
System_DisableSleepTimer(); |
|||
Log_Println((char *)FPSTR(sleepTimerStop), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
publishMqtt((char *)FPSTR(topicSleepState), 0, false); |
|||
return; |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(sleepTimerAlreadyStopped), LOGLEVEL_INFO); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
} |
|||
System_SetSleepTimer((uint8_t)strtoul(receivedString, NULL, 10)); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u Minute(n)", (char *)FPSTR(sleepTimerSetTo), System_GetSleepTimer()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
|
|||
gPlayProperties.sleepAfterPlaylist = false; |
|||
gPlayProperties.sleepAfterCurrentTrack = false; |
|||
} |
|||
// Track-control (pause/play, stop, first, last, next, previous)
|
|||
else if (strcmp_P(topic, topicTrackControlCmnd) == 0) |
|||
{ |
|||
uint8_t controlCommand = strtoul(receivedString, NULL, 10); |
|||
AudioPlayer_TrackControlToQueueSender(controlCommand); |
|||
} |
|||
|
|||
// Check if controls should be locked
|
|||
else if (strcmp_P(topic, topicLockControlsCmnd) == 0) |
|||
{ |
|||
if (strcmp(receivedString, "OFF") == 0) |
|||
{ |
|||
System_SetLockControls(false); |
|||
Log_Println((char *)FPSTR(allowButtons), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
} |
|||
else if (strcmp(receivedString, "ON") == 0) |
|||
{ |
|||
System_SetLockControls(true); |
|||
Log_Println((char *)FPSTR(lockButtons), LOGLEVEL_NOTICE); |
|||
System_IndicateOk(); |
|||
} |
|||
} |
|||
|
|||
// Check if playmode should be adjusted
|
|||
else if (strcmp_P(topic, topicRepeatModeCmnd) == 0) |
|||
{ |
|||
char rBuf[2]; |
|||
uint8_t repeatMode = strtoul(receivedString, NULL, 10); |
|||
Serial.printf("Repeat: %d", repeatMode); |
|||
if (gPlayProperties.playMode != NO_PLAYLIST) |
|||
{ |
|||
if (gPlayProperties.playMode == NO_PLAYLIST) |
|||
{ |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
Log_Println((char *)FPSTR(noPlaylistNotAllowedMqtt), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
} |
|||
else |
|||
{ |
|||
switch (repeatMode) |
|||
{ |
|||
case NO_REPEAT: |
|||
gPlayProperties.repeatCurrentTrack = false; |
|||
gPlayProperties.repeatPlaylist = false; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
Log_Println((char *)FPSTR(modeRepeatNone), LOGLEVEL_INFO); |
|||
System_IndicateOk(); |
|||
break; |
|||
|
|||
case TRACK: |
|||
gPlayProperties.repeatCurrentTrack = true; |
|||
gPlayProperties.repeatPlaylist = false; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
Log_Println((char *)FPSTR(modeRepeatTrack), LOGLEVEL_INFO); |
|||
System_IndicateOk(); |
|||
break; |
|||
|
|||
case PLAYLIST: |
|||
gPlayProperties.repeatCurrentTrack = false; |
|||
gPlayProperties.repeatPlaylist = true; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
Log_Println((char *)FPSTR(modeRepeatPlaylist), LOGLEVEL_INFO); |
|||
System_IndicateOk(); |
|||
break; |
|||
|
|||
case TRACK_N_PLAYLIST: |
|||
gPlayProperties.repeatCurrentTrack = true; |
|||
gPlayProperties.repeatPlaylist = true; |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
Log_Println((char *)FPSTR(modeRepeatTracknPlaylist), LOGLEVEL_INFO); |
|||
System_IndicateOk(); |
|||
break; |
|||
|
|||
default: |
|||
System_IndicateError(); |
|||
snprintf(rBuf, 2, "%u", AudioPlayer_GetRepeatMode()); |
|||
publishMqtt((char *)FPSTR(topicRepeatModeState), rBuf, false); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Check if LEDs should be dimmed
|
|||
else if (strcmp_P(topic, topicLedBrightnessCmnd) == 0) |
|||
{ |
|||
Led_SetBrightness(strtoul(receivedString, NULL, 10)); |
|||
} |
|||
|
|||
// Requested something that isn't specified?
|
|||
else |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(noValidTopic), topic); |
|||
Log_Println(Log_Buffer, LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
} |
|||
|
|||
free(receivedString); |
|||
free(mqttTopic); |
|||
#endif
|
|||
} |
@ -0,0 +1,25 @@ |
|||
#pragma once |
|||
|
|||
#ifdef MQTT_ENABLE |
|||
#define MQTT_SOCKET_TIMEOUT 1 // https://github.com/knolleary/pubsubclient/issues/403 |
|||
#include <PubSubClient.h> |
|||
#endif |
|||
// MQTT-configuration |
|||
// Please note: all lengths will be published n-1 as maxlength to GUI |
|||
constexpr uint8_t mqttServerLength = 32u; |
|||
constexpr uint8_t mqttUserLength = 16u; |
|||
constexpr uint8_t mqttPasswordLength = 16u; |
|||
|
|||
extern char *gMqttUser; |
|||
extern char *gMqttPassword; |
|||
extern uint16_t gMqttPort; |
|||
|
|||
void Mqtt_Init(void); |
|||
void Mqtt_Cyclic(void); |
|||
void Mqtt_Exit(void); |
|||
bool Mqtt_IsEnabled(void); |
|||
|
|||
bool publishMqtt(const char *topic, const char *payload, bool retained); |
|||
bool publishMqtt(const char *topic, int32_t payload, bool retained); |
|||
bool publishMqtt(const char *topic, unsigned long payload, bool retained); |
|||
bool publishMqtt(const char *topic, uint32_t payload, bool retained); |
@ -0,0 +1,77 @@ |
|||
#include <Arduino.h>
|
|||
#include <Wire.h>
|
|||
#include "settings.h"
|
|||
#include "Port.h"
|
|||
|
|||
#ifdef PORT_EXPANDER_ENABLE
|
|||
extern TwoWire i2cBusTwo; |
|||
|
|||
uint8_t Port_ExpanderPorts[portsToRead]; |
|||
bool Port_ExpanderHandler(void); |
|||
#endif
|
|||
|
|||
void Port_Init(void) |
|||
{ |
|||
} |
|||
|
|||
void Port_Cyclic(void) |
|||
{ |
|||
#ifdef PORT_EXPANDER_ENABLE
|
|||
Port_ExpanderHandler(); |
|||
#endif
|
|||
} |
|||
|
|||
// Wrapper: reads from GPIOs (via digitalRead()) or from port-expander (if enabled)
|
|||
// Behaviour like digitalRead(): returns true if not pressed and false if pressed
|
|||
bool Port_Read(const uint8_t _channel) |
|||
{ |
|||
switch (_channel) |
|||
{ |
|||
case 0 ... 39: // GPIO
|
|||
return digitalRead(_channel); |
|||
|
|||
#ifdef PORT_EXPANDER_ENABLE
|
|||
case 100 ... 107: // Port-expander (port 0)
|
|||
return (Port_ExpanderPorts[0] & (1 << (_channel - 100))); // Remove offset 100 (return false if pressed)
|
|||
|
|||
case 108 ... 115: // Port-expander (port 1)
|
|||
if (portsToRead == 2) |
|||
{ // Make sure portsToRead != 1 when channel > 107
|
|||
return (Port_ExpanderPorts[1] & (1 << (_channel - 108))); // Remove offset 100 + 8 (return false if pressed)
|
|||
} |
|||
else |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
#endif
|
|||
|
|||
default: // Everything else (doesn't make sense at all) isn't supposed to be pressed
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
#ifdef PORT_EXPANDER_ENABLE
|
|||
// Reads input from port-expander and writes output into global array
|
|||
// Datasheet: https://www.nxp.com/docs/en/data-sheet/PCA9555.pdf
|
|||
bool Port_ExpanderHandler() |
|||
{ |
|||
i2cBusTwo.beginTransmission(expanderI2cAddress); |
|||
for (uint8_t i = 0; i < portsToRead; i++) |
|||
{ |
|||
i2cBusTwo.write(0x00 + i); // Go to input-register...
|
|||
i2cBusTwo.endTransmission(); |
|||
i2cBusTwo.requestFrom(expanderI2cAddress, 1); // ...and read its byte
|
|||
|
|||
if (i2cBusTwo.available()) |
|||
{ |
|||
Port_ExpanderPorts[i] = i2cBusTwo.read(); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
#endif
|
@ -0,0 +1,5 @@ |
|||
#pragma once |
|||
|
|||
void Port_Init(void); |
|||
void Port_Cyclic(void); |
|||
bool Port_Read(const uint8_t _channel); |
@ -0,0 +1,38 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Log.h"
|
|||
#include "Rfid.h"
|
|||
|
|||
QueueHandle_t gVolumeQueue; |
|||
QueueHandle_t gTrackQueue; |
|||
QueueHandle_t gTrackControlQueue; |
|||
QueueHandle_t gRfidCardQueue; |
|||
|
|||
void Queues_Init(void) |
|||
{ |
|||
// Create queues
|
|||
gVolumeQueue = xQueueCreate(1, sizeof(int)); |
|||
if (gVolumeQueue == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToCreateVolQ), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
gRfidCardQueue = xQueueCreate(1, cardIdStringSize); |
|||
if (gRfidCardQueue == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToCreateRfidQ), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
gTrackControlQueue = xQueueCreate(1, sizeof(uint8_t)); |
|||
if (gTrackControlQueue == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToCreateMgmtQ), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
char **playlistArray; |
|||
gTrackQueue = xQueueCreate(1, sizeof(playlistArray)); |
|||
if (gTrackQueue == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToCreatePlayQ), LOGLEVEL_ERROR); |
|||
} |
|||
} |
@ -0,0 +1,8 @@ |
|||
#pragma once |
|||
|
|||
extern QueueHandle_t gVolumeQueue; |
|||
extern QueueHandle_t gTrackQueue; |
|||
extern QueueHandle_t gTrackControlQueue; |
|||
extern QueueHandle_t gRfidCardQueue; |
|||
|
|||
void Queues_Init(void); |
@ -0,0 +1,12 @@ |
|||
#pragma once |
|||
|
|||
constexpr uint8_t cardIdSize = 4u; |
|||
constexpr uint8_t cardIdStringSize = (cardIdSize * 3u) + 1u; |
|||
|
|||
extern char *gCurrentRfidTagId; |
|||
|
|||
void Rfid_Init(void); |
|||
void Rfid_Cyclic(void); |
|||
void Rfid_Exit(void); |
|||
void Rfid_WakeupCheck(void); |
|||
void Rfid_PreferenceLookupHandler(void); |
@ -0,0 +1,101 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Rfid.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Cmd.h"
|
|||
#include "Common.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "Mqtt.h"
|
|||
#include "Queues.h"
|
|||
#include "System.h"
|
|||
#include "Web.h"
|
|||
|
|||
unsigned long Rfid_LastRfidCheckTimestamp = 0; |
|||
char *gCurrentRfidTagId = NULL; |
|||
|
|||
// Tries to lookup RFID-tag-string in NVS and extracts parameter from it if found
|
|||
void Rfid_PreferenceLookupHandler(void) |
|||
{ |
|||
BaseType_t rfidStatus; |
|||
char rfidTagId[cardIdStringSize]; |
|||
char _file[255]; |
|||
uint32_t _lastPlayPos = 0; |
|||
uint16_t _trackLastPlayed = 0; |
|||
uint32_t _playMode = 1; |
|||
|
|||
rfidStatus = xQueueReceive(gRfidCardQueue, &rfidTagId, 0); |
|||
if (rfidStatus == pdPASS) |
|||
{ |
|||
System_UpdateActivityTimer(); |
|||
free(gCurrentRfidTagId); |
|||
gCurrentRfidTagId = x_strdup(rfidTagId); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(rfidTagReceived), gCurrentRfidTagId); |
|||
Web_SendWebsocketData(0, 10); // Push new rfidTagId to all websocket-clients
|
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
|
|||
String s = gPrefsRfid.getString(gCurrentRfidTagId, "-1"); // Try to lookup rfidId in NVS
|
|||
if (!s.compareTo("-1")) |
|||
{ |
|||
Log_Println((char *)FPSTR(rfidTagUnknownInNvs), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
return; |
|||
} |
|||
|
|||
char *token; |
|||
uint8_t i = 1; |
|||
token = strtok((char *)s.c_str(), stringDelimiter); |
|||
while (token != NULL) |
|||
{ // Try to extract data from string after lookup
|
|||
if (i == 1) |
|||
{ |
|||
strncpy(_file, token, sizeof(_file) / sizeof(_file[0])); |
|||
} |
|||
else if (i == 2) |
|||
{ |
|||
_lastPlayPos = strtoul(token, NULL, 10); |
|||
} |
|||
else if (i == 3) |
|||
{ |
|||
_playMode = strtoul(token, NULL, 10); |
|||
} |
|||
else if (i == 4) |
|||
{ |
|||
_trackLastPlayed = strtoul(token, NULL, 10); |
|||
} |
|||
i++; |
|||
token = strtok(NULL, stringDelimiter); |
|||
} |
|||
|
|||
if (i != 5) |
|||
{ |
|||
Log_Println((char *)FPSTR(errorOccuredNvs), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
} |
|||
else |
|||
{ |
|||
// Only pass file to queue if strtok revealed 3 items
|
|||
if (_playMode >= 100) |
|||
{ |
|||
// Modification-cards can change some settings (e.g. introducing track-looping or sleep after track/playlist).
|
|||
Cmd_Action(_playMode); |
|||
} |
|||
else |
|||
{ |
|||
#ifdef MQTT_ENABLE
|
|||
publishMqtt((char *)FPSTR(topicRfidState), gCurrentRfidTagId, false); |
|||
#endif
|
|||
|
|||
#ifdef BLUETOOTH_ENABLE
|
|||
// if music rfid was read, go back to normal mode
|
|||
if (System_GetOperationMode() == OPMODE_BLUETOOTH) |
|||
{ |
|||
System_SetOperationMode(OPMODE_NORMAL); |
|||
} |
|||
#endif
|
|||
|
|||
AudioPlayer_TrackQueueDispatcher(_file, _lastPlayPos, _playMode, _trackLastPlayed); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,101 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "Rfid.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "Queues.h"
|
|||
#include "System.h"
|
|||
|
|||
#if defined RFID_READER_TYPE_MFRC522_SPI || defined RFID_READER_TYPE_MFRC522_I2C
|
|||
|
|||
#ifdef RFID_READER_TYPE_MFRC522_SPI
|
|||
#include <MFRC522.h>
|
|||
#endif
|
|||
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(PORT_EXPANDER_ENABLE)
|
|||
#include "Wire.h"
|
|||
#endif
|
|||
#ifdef RFID_READER_TYPE_MFRC522_I2C
|
|||
#include <MFRC522_I2C.h>
|
|||
#endif
|
|||
|
|||
extern unsigned long Rfid_LastRfidCheckTimestamp; |
|||
|
|||
#ifdef RFID_READER_TYPE_MFRC522_I2C
|
|||
extern TwoWire i2cBusTwo; |
|||
|
|||
static MFRC522_I2C mfrc522(MFRC522_ADDR, MFRC522_RST_PIN, &i2cBusTwo); |
|||
#endif
|
|||
#ifdef RFID_READER_TYPE_MFRC522_SPI
|
|||
static MFRC522 mfrc522(RFID_CS, RST_PIN); |
|||
#endif
|
|||
|
|||
void Rfid_Init(void) |
|||
{ |
|||
#ifdef RFID_READER_TYPE_MFRC522_SPI
|
|||
SPI.begin(RFID_SCK, RFID_MISO, RFID_MOSI, RFID_CS); |
|||
SPI.setFrequency(1000000); |
|||
#endif
|
|||
|
|||
// Init RC522 Card-Reader
|
|||
#if defined(RFID_READER_TYPE_MFRC522_I2C) || defined(RFID_READER_TYPE_MFRC522_SPI)
|
|||
mfrc522.PCD_Init(); |
|||
mfrc522.PCD_SetAntennaGain(rfidGain); |
|||
delay(50); |
|||
Log_Println((char *)FPSTR(rfidScannerReady), LOGLEVEL_DEBUG); |
|||
#endif
|
|||
} |
|||
|
|||
void Rfid_Cyclic(void) |
|||
{ |
|||
byte cardId[cardIdSize]; |
|||
String cardIdString; |
|||
|
|||
if ((millis() - Rfid_LastRfidCheckTimestamp) >= RFID_SCAN_INTERVAL) |
|||
{ |
|||
Rfid_LastRfidCheckTimestamp = millis(); |
|||
// Reset the loop if no new card is present on the sensor/reader. This saves the entire process when idle.
|
|||
|
|||
if (!mfrc522.PICC_IsNewCardPresent()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// Select one of the cards
|
|||
if (!mfrc522.PICC_ReadCardSerial()) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
|
|||
mfrc522.PICC_HaltA(); |
|||
mfrc522.PCD_StopCrypto1(); |
|||
|
|||
memcpy(cardId, mfrc522.uid.uidByte, cardIdSize); |
|||
|
|||
Log_Print((char *)FPSTR(rfidTagDetected), LOGLEVEL_NOTICE); |
|||
for (uint8_t i = 0u; i < cardIdSize; i++) |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%02x%s", cardId[i], (i < cardIdSize - 1u) ? "-" : "\n"); |
|||
Log_Print(Log_Buffer, LOGLEVEL_NOTICE); |
|||
} |
|||
|
|||
for (uint8_t i = 0u; i < cardIdSize; i++) |
|||
{ |
|||
char num[4]; |
|||
snprintf(num, sizeof(num), "%03d", cardId[i]); |
|||
cardIdString += num; |
|||
} |
|||
|
|||
xQueueSend(gRfidCardQueue, cardIdString.c_str(), 0); |
|||
} |
|||
} |
|||
|
|||
void Rfid_Exit(void) |
|||
{ |
|||
} |
|||
|
|||
void Rfid_WakeupCheck(void) |
|||
{ |
|||
} |
|||
|
|||
#endif
|
@ -0,0 +1,262 @@ |
|||
#include <Arduino.h>
|
|||
#include <freertos/task.h>
|
|||
#include <esp_task_wdt.h>
|
|||
#include "settings.h"
|
|||
#include "Rfid.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "Queues.h"
|
|||
#include "System.h"
|
|||
|
|||
#ifdef RFID_READER_TYPE_PN5180
|
|||
#include <PN5180.h>
|
|||
#include <PN5180ISO14443.h>
|
|||
#include <PN5180ISO15693.h>
|
|||
#endif
|
|||
|
|||
#define RFID_PN5180_STATE_INIT 0u
|
|||
|
|||
#define RFID_PN5180_NFC14443_STATE_RESET 1u
|
|||
#define RFID_PN5180_NFC14443_STATE_SETUPRF 2u
|
|||
#define RFID_PN5180_NFC14443_STATE_READCARD 3u
|
|||
|
|||
#define RFID_PN5180_NFC15693_STATE_RESET 4u
|
|||
#define RFID_PN5180_NFC15693_STATE_SETUPRF 5u
|
|||
#define RFID_PN5180_NFC15693_STATE_DISABLEPRIVACYMODE 6u
|
|||
#define RFID_PN5180_NFC15693_STATE_GETINVENTORY 7u
|
|||
|
|||
extern unsigned long Rfid_LastRfidCheckTimestamp; |
|||
|
|||
#ifdef RFID_READER_TYPE_PN5180
|
|||
|
|||
static void Rfid_Task(void *parameter); |
|||
static void Rfid_Read(void); |
|||
|
|||
void Rfid_Init(void) |
|||
{ |
|||
#ifdef PN5180_ENABLE_LPCD
|
|||
// disable pin hold from deep sleep
|
|||
gpio_deep_sleep_hold_dis(); |
|||
gpio_hold_dis(gpio_num_t(RFID_CS)); // NSS
|
|||
gpio_hold_dis(gpio_num_t(RFID_RST)); // RST
|
|||
#endif
|
|||
|
|||
// Create task for rfid
|
|||
xTaskCreatePinnedToCore( |
|||
Rfid_Task, /* Function to implement the task */ |
|||
"Rfid_Task", /* Name of the task */ |
|||
1500, /* Stack size in words */ |
|||
NULL, /* Task input parameter */ |
|||
1, /* Priority of the task */ |
|||
NULL, /* Task handle. */ |
|||
0 /* Core where the task should run */ |
|||
); |
|||
} |
|||
|
|||
void Rfid_Cyclic(void) |
|||
{ |
|||
// Implemented via task
|
|||
} |
|||
|
|||
void Rfid_Task(void *parameter) |
|||
{ |
|||
for (;;) |
|||
{ |
|||
Rfid_Read(); |
|||
vTaskDelay(5u); |
|||
} |
|||
} |
|||
|
|||
void Rfid_Read(void) |
|||
{ |
|||
static PN5180ISO14443 nfc14443(RFID_CS, RFID_BUSY, RFID_RST); |
|||
static PN5180ISO15693 nfc15693(RFID_CS, RFID_BUSY, RFID_RST); |
|||
static uint8_t stateMachine = RFID_PN5180_STATE_INIT; |
|||
byte cardId[cardIdSize], lastCardId[cardIdSize]; |
|||
uint8_t uid[10]; |
|||
String cardIdString; |
|||
bool cardReceived = false; |
|||
|
|||
if (RFID_PN5180_STATE_INIT == stateMachine) |
|||
{ |
|||
nfc14443.begin(); |
|||
nfc14443.reset(); |
|||
// show PN5180 reader version
|
|||
uint8_t firmwareVersion[2]; |
|||
nfc14443.readEEprom(FIRMWARE_VERSION, firmwareVersion, sizeof(firmwareVersion)); |
|||
Serial.print(F("Firmware version=")); |
|||
Serial.print(firmwareVersion[1]); |
|||
Serial.print("."); |
|||
Serial.println(firmwareVersion[0]); |
|||
|
|||
// activate RF field
|
|||
delay(4); |
|||
Log_Println((char *)FPSTR(rfidScannerReady), LOGLEVEL_DEBUG); |
|||
} |
|||
// 1. check for an ISO-14443 card
|
|||
else if (RFID_PN5180_NFC14443_STATE_RESET == stateMachine) |
|||
{ |
|||
nfc14443.reset(); |
|||
} |
|||
else if (RFID_PN5180_NFC14443_STATE_SETUPRF == stateMachine) |
|||
{ |
|||
nfc14443.setupRF(); |
|||
} |
|||
else if (RFID_PN5180_NFC14443_STATE_READCARD == stateMachine) |
|||
{ |
|||
if (nfc14443.readCardSerial(uid) >= 4u) |
|||
{ |
|||
cardReceived = true; |
|||
} |
|||
} |
|||
// 2. check for an ISO-15693 card
|
|||
else if (RFID_PN5180_NFC15693_STATE_RESET == stateMachine) |
|||
{ |
|||
nfc15693.reset(); |
|||
} |
|||
else if (RFID_PN5180_NFC15693_STATE_SETUPRF == stateMachine) |
|||
{ |
|||
nfc15693.setupRF(); |
|||
} |
|||
else if (RFID_PN5180_NFC15693_STATE_DISABLEPRIVACYMODE == stateMachine) |
|||
{ |
|||
// check for ICODE-SLIX2 password protected tag
|
|||
// put your privacy password here, e.g.:
|
|||
// https://de.ifixit.com/Antworten/Ansehen/513422/nfc+Chips+f%C3%BCr+tonies+kaufen
|
|||
uint8_t password[] = {0x01, 0x02, 0x03, 0x04}; |
|||
ISO15693ErrorCode myrc = nfc15693.disablePrivacyMode(password); |
|||
if (ISO15693_EC_OK == myrc) |
|||
{ |
|||
Serial.println(F("disabling privacy-mode successful")); |
|||
} |
|||
} |
|||
else if (RFID_PN5180_NFC15693_STATE_GETINVENTORY == stateMachine) |
|||
{ |
|||
// try to read ISO15693 inventory
|
|||
ISO15693ErrorCode rc = nfc15693.getInventory(uid); |
|||
if (rc == ISO15693_EC_OK) |
|||
{ |
|||
cardReceived = true; |
|||
} |
|||
} |
|||
|
|||
// send card to queue
|
|||
if (cardReceived) |
|||
{ |
|||
memcpy(cardId, uid, cardIdSize); |
|||
|
|||
// check for different card id
|
|||
if (memcmp((const void *)cardId, (const void *)lastCardId, sizeof(cardId)) == 0) |
|||
{ |
|||
// reset state machine
|
|||
stateMachine = RFID_PN5180_NFC14443_STATE_RESET; |
|||
return; |
|||
} |
|||
|
|||
memcpy(lastCardId, cardId, cardIdSize); |
|||
|
|||
Log_Print((char *)FPSTR(rfidTagDetected), LOGLEVEL_NOTICE); |
|||
for (uint8_t i = 0u; i < cardIdSize; i++) |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%02x%s", cardId[i], (i < cardIdSize - 1u) ? "-" : "\n"); |
|||
Log_Print(Log_Buffer, LOGLEVEL_NOTICE); |
|||
} |
|||
|
|||
for (uint8_t i = 0u; i < cardIdSize; i++) |
|||
{ |
|||
char num[4]; |
|||
snprintf(num, sizeof(num), "%03d", cardId[i]); |
|||
cardIdString += num; |
|||
} |
|||
|
|||
xQueueSend(gRfidCardQueue, cardIdString.c_str(), 0); |
|||
} |
|||
|
|||
stateMachine++; |
|||
|
|||
if (stateMachine > RFID_PN5180_NFC15693_STATE_GETINVENTORY) |
|||
{ |
|||
stateMachine = RFID_PN5180_NFC14443_STATE_RESET; |
|||
} |
|||
} |
|||
|
|||
void Rfid_Exit(void) |
|||
{ |
|||
// goto low power card detection mode
|
|||
#ifdef PN5180_ENABLE_LPCD
|
|||
static PN5180 nfc(RFID_CS, RFID_BUSY, RFID_RST); |
|||
nfc.begin(); |
|||
// show PN5180 reader version
|
|||
uint8_t firmwareVersion[2]; |
|||
nfc.readEEprom(FIRMWARE_VERSION, firmwareVersion, sizeof(firmwareVersion)); |
|||
Serial.print(F("Firmware version=")); |
|||
Serial.print(firmwareVersion[1]); |
|||
Serial.print("."); |
|||
Serial.println(firmwareVersion[0]); |
|||
// check firmware version: PN5180 firmware < 4.0 has several bugs preventing the LPCD mode
|
|||
// you can flash latest firmware with this project: https://github.com/abidxraihan/PN5180_Updater_ESP32
|
|||
if (firmwareVersion[1] < 4) |
|||
{ |
|||
Serial.println(F("This PN5180 firmware does not work with LPCD! use firmware >= 4.0")); |
|||
return; |
|||
} |
|||
Serial.println(F("prepare low power card detection...")); |
|||
nfc.prepareLPCD(); |
|||
nfc.clearIRQStatus(0xffffffff); |
|||
Serial.print(F("PN5180 IRQ PIN: ")); |
|||
Serial.println(Port_Read(RFID_IRQ)); |
|||
// turn on LPCD
|
|||
uint16_t wakeupCounterInMs = 0x3FF; // must be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms.
|
|||
if (nfc.switchToLPCD(wakeupCounterInMs)) |
|||
{ |
|||
Serial.println(F("switch to low power card detection: success")); |
|||
// configure wakeup pin for deep-sleep wake-up, use ext1
|
|||
esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); |
|||
// freeze pin states in deep sleep
|
|||
gpio_hold_en(gpio_num_t(RFID_CS)); // CS/NSS
|
|||
gpio_hold_en(gpio_num_t(RFID_RST)); // RST
|
|||
gpio_deep_sleep_hold_en(); |
|||
} |
|||
else |
|||
{ |
|||
Serial.println(F("switchToLPCD failed")); |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
// wake up from LPCD, check card is present. This works only for ISO-14443 compatible cards
|
|||
void Rfid_WakeupCheck(void) |
|||
{ |
|||
#ifdef PN5180_ENABLE_LPCD
|
|||
static PN5180ISO14443 nfc14443(RFID_CS, RFID_BUSY, RFID_RST); |
|||
nfc14443.begin(); |
|||
nfc14443.reset(); |
|||
nfc14443.setupRF(); |
|||
if (!nfc14443.isCardPresent()) |
|||
{ |
|||
nfc14443.clearIRQStatus(0xffffffff); |
|||
Serial.print(F("Logic level at PN5180' IRQ-PIN: ")); |
|||
Serial.println(Port_Read(RFID_IRQ)); |
|||
// turn on LPCD
|
|||
uint16_t wakeupCounterInMs = 0x3FF; // needs to be in the range of 0x0 - 0xA82. max wake-up time is 2960 ms.
|
|||
if (nfc14443.switchToLPCD(wakeupCounterInMs)) |
|||
{ |
|||
Log_Println((char *)FPSTR(lowPowerCardSuccess), LOGLEVEL_INFO); |
|||
// configure wakeup pin for deep-sleep wake-up, use ext1
|
|||
esp_sleep_enable_ext1_wakeup((1ULL << (RFID_IRQ)), ESP_EXT1_WAKEUP_ANY_HIGH); |
|||
// freeze pin states in deep sleep
|
|||
gpio_hold_en(gpio_num_t(RFID_CS)); // CS/NSS
|
|||
gpio_hold_en(gpio_num_t(RFID_RST)); // RST
|
|||
gpio_deep_sleep_hold_en(); |
|||
Log_Println((char *)FPSTR(wakeUpRfidNoIso14443), LOGLEVEL_ERROR); |
|||
esp_deep_sleep_start(); |
|||
} |
|||
else |
|||
{ |
|||
Serial.println(F("switchToLPCD failed")); |
|||
} |
|||
} |
|||
#endif
|
|||
} |
|||
|
|||
#endif
|
@ -0,0 +1,78 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "RotaryEncoder.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Log.h"
|
|||
#include "System.h"
|
|||
|
|||
#ifdef USEROTARY_ENABLE
|
|||
#include <ESP32Encoder.h>
|
|||
#endif
|
|||
|
|||
// Rotary encoder-configuration
|
|||
#ifdef USEROTARY_ENABLE
|
|||
ESP32Encoder encoder; |
|||
// Rotary encoder-helper
|
|||
int32_t lastEncoderValue; |
|||
int32_t currentEncoderValue; |
|||
int32_t lastVolume = -1; // Don't change -1 as initial-value!
|
|||
#endif
|
|||
|
|||
void RotaryEncoder_Init(void) |
|||
{ |
|||
// Init rotary encoder
|
|||
#ifdef USEROTARY_ENABLE
|
|||
encoder.attachHalfQuad(DREHENCODER_CLK, DREHENCODER_DT); |
|||
encoder.clearCount(); |
|||
encoder.setCount(AudioPlayer_GetInitVolume() * 2); // Ganzes Raster ist immer +2, daher initiale Lautstärke mit 2 multiplizieren
|
|||
#endif
|
|||
} |
|||
|
|||
void RotaryEncoder_Readjust(void) |
|||
{ |
|||
#ifdef USEROTARY_ENABLE
|
|||
encoder.clearCount(); |
|||
encoder.setCount(AudioPlayer_GetCurrentVolume() * 2); |
|||
#endif
|
|||
} |
|||
|
|||
// Handles volume directed by rotary encoder
|
|||
void RotaryEncoder_Cyclic(void) |
|||
{ |
|||
#ifdef USEROTARY_ENABLE
|
|||
if (System_AreControlsLocked()) |
|||
{ |
|||
encoder.clearCount(); |
|||
encoder.setCount(AudioPlayer_GetCurrentVolume() * 2); |
|||
return; |
|||
} |
|||
|
|||
currentEncoderValue = encoder.getCount(); |
|||
// Only if initial run or value has changed. And only after "full step" of rotary encoder
|
|||
if (((lastEncoderValue != currentEncoderValue) || lastVolume == -1) && (currentEncoderValue % 2 == 0)) |
|||
{ |
|||
System_UpdateActivityTimer(); // Set inactive back if rotary encoder was used
|
|||
if ((AudioPlayer_GetMaxVolume() * 2) < currentEncoderValue) |
|||
{ |
|||
encoder.clearCount(); |
|||
encoder.setCount(AudioPlayer_GetMaxVolume() * 2); |
|||
Log_Println((char *)FPSTR(maxLoudnessReached), LOGLEVEL_INFO); |
|||
currentEncoderValue = encoder.getCount(); |
|||
} |
|||
else if (currentEncoderValue < AudioPlayer_GetMinVolume()) |
|||
{ |
|||
encoder.clearCount(); |
|||
encoder.setCount(AudioPlayer_GetMinVolume()); |
|||
Log_Println((char *)FPSTR(minLoudnessReached), LOGLEVEL_INFO); |
|||
currentEncoderValue = encoder.getCount(); |
|||
} |
|||
lastEncoderValue = currentEncoderValue; |
|||
AudioPlayer_SetCurrentVolume(lastEncoderValue / 2u); |
|||
if (AudioPlayer_GetCurrentVolume() != lastVolume) |
|||
{ |
|||
lastVolume = AudioPlayer_GetCurrentVolume(); |
|||
AudioPlayer_VolumeToQueueSender(AudioPlayer_GetCurrentVolume(), false); |
|||
} |
|||
} |
|||
#endif
|
|||
} |
@ -0,0 +1,5 @@ |
|||
#pragma once |
|||
|
|||
void RotaryEncoder_Init(void); |
|||
void RotaryEncoder_Cyclic(void); |
|||
void RotaryEncoder_Readjust(void); |
@ -0,0 +1,235 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "SdCard.h"
|
|||
#include "Common.h"
|
|||
#include "Led.h"
|
|||
#include "Log.h"
|
|||
#include "MemX.h"
|
|||
#include "System.h"
|
|||
|
|||
#ifdef SD_MMC_1BIT_MODE
|
|||
fs::FS gFSystem = (fs::FS)SD_MMC; |
|||
#else
|
|||
SPIClass spiSD(HSPI); |
|||
fs::FS gFSystem = (fs::FS)SD; |
|||
#endif
|
|||
|
|||
void SdCard_Init(void) |
|||
{ |
|||
#ifndef SINGLE_SPI_ENABLE
|
|||
#ifdef SD_MMC_1BIT_MODE
|
|||
pinMode(2, INPUT_PULLUP); |
|||
while (!SD_MMC.begin("/sdcard", true)) |
|||
{ |
|||
#else
|
|||
pinMode(SPISD_CS, OUTPUT); |
|||
digitalWrite(SPISD_CS, HIGH); |
|||
spiSD.begin(SPISD_SCK, SPISD_MISO, SPISD_MOSI, SPISD_CS); |
|||
spiSD.setFrequency(1000000); |
|||
while (!SD.begin(SPISD_CS, spiSD)) |
|||
{ |
|||
#endif
|
|||
#else
|
|||
#ifdef SD_MMC_1BIT_MODE
|
|||
pinMode(2, INPUT_PULLUP); |
|||
while (!SD_MMC.begin("/sdcard", true)) |
|||
{ |
|||
#else
|
|||
while (!SD.begin(SPISD_CS)) |
|||
{ |
|||
#endif
|
|||
#endif
|
|||
Log_Println((char *)FPSTR(unableToMountSd), LOGLEVEL_ERROR); |
|||
delay(500); |
|||
#ifdef SHUTDOWN_IF_SD_BOOT_FAILS
|
|||
if (millis() >= deepsleepTimeAfterBootFails * 1000) |
|||
{ |
|||
Log_Println((char *)FPSTR(sdBootFailedDeepsleep), LOGLEVEL_ERROR); |
|||
esp_deep_sleep_start(); |
|||
} |
|||
#endif
|
|||
} |
|||
} |
|||
|
|||
void SdCard_Exit(void) |
|||
{ |
|||
// SD card goto idle mode
|
|||
#ifdef SD_MMC_1BIT_MODE
|
|||
SD_MMC.end(); |
|||
#endif
|
|||
} |
|||
|
|||
sdcard_type_t SdCard_GetType(void) |
|||
{ |
|||
sdcard_type_t cardType; |
|||
#ifdef SD_MMC_1BIT_MODE
|
|||
Log_Println((char *)FPSTR(sdMountedMmc1BitMode), LOGLEVEL_NOTICE); |
|||
cardType = SD_MMC.cardType(); |
|||
#else
|
|||
Log_Println((char *)FPSTR(sdMountedSpiMode), LOGLEVEL_NOTICE); |
|||
cardType = SD.cardType(); |
|||
#endif
|
|||
return cardType; |
|||
} |
|||
|
|||
// Check if file-type is correct
|
|||
bool fileValid(const char *_fileItem) |
|||
{ |
|||
const char ch = '/'; |
|||
char *subst; |
|||
subst = strrchr(_fileItem, ch); // Don't use files that start with .
|
|||
|
|||
return (!startsWith(subst, (char *)"/.")) && |
|||
(endsWith(_fileItem, ".mp3") || endsWith(_fileItem, ".MP3") || |
|||
endsWith(_fileItem, ".aac") || endsWith(_fileItem, ".AAC") || |
|||
endsWith(_fileItem, ".m3u") || endsWith(_fileItem, ".M3U") || |
|||
endsWith(_fileItem, ".m4a") || endsWith(_fileItem, ".M4A") || |
|||
endsWith(_fileItem, ".wav") || endsWith(_fileItem, ".WAV") || |
|||
endsWith(_fileItem, ".flac") || endsWith(_fileItem, ".FLAC") || |
|||
endsWith(_fileItem, ".asx") || endsWith(_fileItem, ".ASX")); |
|||
} |
|||
|
|||
/* Puts SD-file(s) or directory into a playlist
|
|||
First element of array always contains the number of payload-items. */ |
|||
char **SdCard_ReturnPlaylist(const char *fileName) |
|||
{ |
|||
static char **files; |
|||
char fileNameBuf[255]; |
|||
|
|||
File fileOrDirectory = gFSystem.open(fileName); |
|||
|
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(freeMemory), ESP.getFreeHeap()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_DEBUG); |
|||
|
|||
if (files != NULL) |
|||
{ // If **ptr already exists, de-allocate its memory
|
|||
Log_Println((char *)FPSTR(releaseMemoryOfOldPlaylist), LOGLEVEL_DEBUG); |
|||
--files; |
|||
freeMultiCharArray(files, strtoul(*files, NULL, 10)); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(freeMemoryAfterFree), ESP.getFreeHeap()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_DEBUG); |
|||
} |
|||
|
|||
if (!fileOrDirectory) |
|||
{ |
|||
Log_Println((char *)FPSTR(dirOrFileDoesNotExist), LOGLEVEL_ERROR); |
|||
return NULL; |
|||
} |
|||
|
|||
// File-mode
|
|||
if (!fileOrDirectory.isDirectory()) |
|||
{ |
|||
files = (char **)x_malloc(sizeof(char *) * 2); |
|||
if (files == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToAllocateMemForPlaylist), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
return NULL; |
|||
} |
|||
Log_Println((char *)FPSTR(fileModeDetected), LOGLEVEL_INFO); |
|||
strncpy(fileNameBuf, (char *)fileOrDirectory.name(), sizeof(fileNameBuf) / sizeof(fileNameBuf[0])); |
|||
if (fileValid(fileNameBuf)) |
|||
{ |
|||
files = (char **)x_malloc(sizeof(char *) * 2); |
|||
files[1] = x_strdup(fileNameBuf); |
|||
} |
|||
files[0] = x_strdup("1"); // Number of files is always 1 in file-mode
|
|||
|
|||
return ++files; |
|||
} |
|||
|
|||
// Directory-mode
|
|||
uint16_t allocCount = 1; |
|||
uint16_t allocSize = 512; |
|||
if (psramInit()) |
|||
{ |
|||
allocSize = 16384; // There's enough PSRAM. So we don't have to care...
|
|||
} |
|||
char *serializedPlaylist; |
|||
|
|||
serializedPlaylist = (char *)x_calloc(allocSize, sizeof(char)); |
|||
|
|||
while (true) |
|||
{ |
|||
File fileItem = fileOrDirectory.openNextFile(); |
|||
if (!fileItem) |
|||
{ |
|||
break; |
|||
} |
|||
if (fileItem.isDirectory()) |
|||
{ |
|||
continue; |
|||
} |
|||
else |
|||
{ |
|||
strncpy(fileNameBuf, (char *)fileItem.name(), sizeof(fileNameBuf) / sizeof(fileNameBuf[0])); |
|||
|
|||
// Don't support filenames that start with "." and only allow .mp3
|
|||
if (fileValid(fileNameBuf)) |
|||
{ |
|||
/*snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *) FPSTR(nameOfFileFound), fileNameBuf);
|
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO);*/ |
|||
if ((strlen(serializedPlaylist) + strlen(fileNameBuf) + 2) >= allocCount * allocSize) |
|||
{ |
|||
serializedPlaylist = (char *)realloc(serializedPlaylist, ++allocCount * allocSize); |
|||
Log_Println((char *)FPSTR(reallocCalled), LOGLEVEL_DEBUG); |
|||
if (serializedPlaylist == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToAllocateMemForLinearPlaylist), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
return files; |
|||
} |
|||
} |
|||
strcat(serializedPlaylist, stringDelimiter); |
|||
strcat(serializedPlaylist, fileNameBuf); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Get number of elements out of serialized playlist
|
|||
uint32_t cnt = 0; |
|||
for (uint32_t k = 0; k < (strlen(serializedPlaylist)); k++) |
|||
{ |
|||
if (serializedPlaylist[k] == '#') |
|||
{ |
|||
cnt++; |
|||
} |
|||
} |
|||
|
|||
// Alloc only necessary number of playlist-pointers
|
|||
files = (char **)x_malloc(sizeof(char *) * cnt + 1); |
|||
|
|||
if (files == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToAllocateMemForPlaylist), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
free(serializedPlaylist); |
|||
return NULL; |
|||
} |
|||
|
|||
// Extract elements out of serialized playlist and copy to playlist
|
|||
char *token; |
|||
token = strtok(serializedPlaylist, stringDelimiter); |
|||
uint32_t pos = 1; |
|||
while (token != NULL) |
|||
{ |
|||
files[pos++] = x_strdup(token); |
|||
token = strtok(NULL, stringDelimiter); |
|||
} |
|||
|
|||
free(serializedPlaylist); |
|||
|
|||
files[0] = (char *)x_malloc(sizeof(char) * 5); |
|||
|
|||
if (files[0] == NULL) |
|||
{ |
|||
Log_Println((char *)FPSTR(unableToAllocateMemForPlaylist), LOGLEVEL_ERROR); |
|||
System_IndicateError(); |
|||
return NULL; |
|||
} |
|||
sprintf(files[0], "%u", cnt); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %d", (char *)FPSTR(numberOfValidFiles), cnt); |
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
|
|||
return ++files; // return ptr+1 (starting at 1st payload-item); ptr+0 contains number of items
|
|||
} |
@ -0,0 +1,14 @@ |
|||
#pragma once |
|||
#include "settings.h" |
|||
#ifdef SD_MMC_1BIT_MODE |
|||
#include "SD_MMC.h" |
|||
#else |
|||
#include "SD.h" |
|||
#endif |
|||
|
|||
extern fs::FS gFSystem; |
|||
|
|||
void SdCard_Init(void); |
|||
void SdCard_Exit(void); |
|||
sdcard_type_t SdCard_GetType(void); |
|||
char **SdCard_ReturnPlaylist(const char *fileName); |
@ -0,0 +1,237 @@ |
|||
#include <Arduino.h>
|
|||
#include "settings.h"
|
|||
#include "System.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "Rfid.h"
|
|||
#include "Led.h"
|
|||
#include "Log.h"
|
|||
#include "Mqtt.h"
|
|||
#include "SdCard.h"
|
|||
|
|||
constexpr const char prefsRfidNamespace[] PROGMEM = "rfidTags"; // Namespace used to save IDs of rfid-tags
|
|||
constexpr const char prefsSettingsNamespace[] PROGMEM = "settings"; // Namespace used for generic settings
|
|||
|
|||
Preferences gPrefsRfid; |
|||
Preferences gPrefsSettings; |
|||
|
|||
unsigned long System_LastTimeActiveTimestamp = 0u; // Timestamp of last user-interaction
|
|||
unsigned long System_SleepTimerStartTimestamp = 0u; // Flag if sleep-timer is active
|
|||
bool System_GoToSleep = false; // Flag for turning uC immediately into deepsleep
|
|||
bool System_Sleeping = false; // Flag for turning into deepsleep is in progress
|
|||
bool System_LockControls = false; // Flag if buttons and rotary encoder is locked
|
|||
uint8_t System_MaxInactivityTime = 10u; // Time in minutes, after uC is put to deep sleep because of inactivity (and modified later via GUI)
|
|||
uint8_t System_SleepTimer = 30u; // Sleep timer in minutes that can be optionally used (and modified later via MQTT or RFID)
|
|||
|
|||
// Operation Mode
|
|||
volatile uint8_t System_OperationMode; |
|||
|
|||
void System_SleepHandler(void); |
|||
void System_DeepSleepManager(void); |
|||
|
|||
void System_Init(void) |
|||
{ |
|||
srand(esp_random()); |
|||
pinMode(POWER, OUTPUT); |
|||
digitalWrite(POWER, HIGH); |
|||
|
|||
gPrefsRfid.begin((char *)FPSTR(prefsRfidNamespace)); |
|||
gPrefsSettings.begin((char *)FPSTR(prefsSettingsNamespace)); |
|||
|
|||
// Get maximum inactivity-time from NVS
|
|||
uint32_t nvsMInactivityTime = gPrefsSettings.getUInt("mInactiviyT", 0); |
|||
if (nvsMInactivityTime) |
|||
{ |
|||
System_MaxInactivityTime = nvsMInactivityTime; |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %u", (char *)FPSTR(restoredMaxInactivityFromNvs), nvsMInactivityTime); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
gPrefsSettings.putUInt("mInactiviyT", System_MaxInactivityTime); |
|||
Log_Println((char *)FPSTR(wroteMaxInactivityToNvs), LOGLEVEL_ERROR); |
|||
} |
|||
|
|||
System_OperationMode = gPrefsSettings.getUChar("operationMode", OPMODE_NORMAL); |
|||
} |
|||
|
|||
void System_Cyclic(void) |
|||
{ |
|||
System_SleepHandler(); |
|||
System_DeepSleepManager(); |
|||
} |
|||
|
|||
void System_UpdateActivityTimer(void) |
|||
{ |
|||
System_LastTimeActiveTimestamp = millis(); |
|||
} |
|||
|
|||
void System_RequestSleep(void) |
|||
{ |
|||
System_GoToSleep = true; |
|||
} |
|||
|
|||
bool System_IsSleepRequested(void) |
|||
{ |
|||
return System_GoToSleep; |
|||
} |
|||
|
|||
bool System_SetSleepTimer(uint8_t minutes) |
|||
{ |
|||
bool sleepTimerEnabled = false; |
|||
|
|||
if (System_SleepTimerStartTimestamp && (System_SleepTimer == minutes)) |
|||
{ |
|||
System_SleepTimerStartTimestamp = 0u; |
|||
Led_ResetToInitialBrightness(); |
|||
Log_Println((char *)FPSTR(modificatorSleepd), LOGLEVEL_NOTICE); |
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
} |
|||
else |
|||
{ |
|||
System_SleepTimer = minutes; |
|||
System_SleepTimerStartTimestamp = millis(); |
|||
sleepTimerEnabled = true; |
|||
|
|||
Led_ResetToNightBrightness(); |
|||
Log_Println((char *)FPSTR(modificatorSleepTimer60), LOGLEVEL_NOTICE); |
|||
publishMqtt((char *)FPSTR(topicSleepTimerState), System_SleepTimer, false); |
|||
publishMqtt((char *)FPSTR(topicLedBrightnessState), Led_GetBrightness(), false); |
|||
} |
|||
|
|||
return sleepTimerEnabled; |
|||
} |
|||
|
|||
void System_DisableSleepTimer(void) |
|||
{ |
|||
System_SleepTimerStartTimestamp = 0u; |
|||
} |
|||
|
|||
bool System_IsSleepTimerEnabled(void) |
|||
{ |
|||
return (System_SleepTimerStartTimestamp > 0u); |
|||
} |
|||
|
|||
uint32_t System_GetSleepTimerTimeStamp(void) |
|||
{ |
|||
return System_SleepTimerStartTimestamp; |
|||
} |
|||
|
|||
bool System_IsSleepPending(void) |
|||
{ |
|||
return System_Sleeping; |
|||
} |
|||
|
|||
uint8_t System_GetSleepTimer(void) |
|||
{ |
|||
return System_SleepTimer; |
|||
} |
|||
|
|||
void System_SetLockControls(bool value) |
|||
{ |
|||
System_LockControls = value; |
|||
} |
|||
|
|||
void System_ToggleLockControls(void) |
|||
{ |
|||
System_LockControls = !System_LockControls; |
|||
|
|||
if (System_LockControls) |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorAllButtonsLocked), LOGLEVEL_NOTICE); |
|||
publishMqtt((char *)FPSTR(topicLockControlsState), "ON", false); |
|||
System_IndicateOk(); |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(modificatorAllButtonsUnlocked), LOGLEVEL_NOTICE); |
|||
publishMqtt((char *)FPSTR(topicLockControlsState), "OFF", false); |
|||
} |
|||
} |
|||
|
|||
bool System_AreControlsLocked(void) |
|||
{ |
|||
return System_LockControls; |
|||
} |
|||
|
|||
void System_IndicateError(void) |
|||
{ |
|||
Led_Indicate(LedIndicatorType::Error); |
|||
} |
|||
void System_IndicateOk(void) |
|||
{ |
|||
Led_Indicate(LedIndicatorType::Ok); |
|||
} |
|||
|
|||
// Writes to NVS, if bluetooth or "normal" mode is desired
|
|||
void System_SetOperationMode(uint8_t opMode) |
|||
{ |
|||
uint8_t currentOperationMode = gPrefsSettings.getUChar("operationMode", OPMODE_NORMAL); |
|||
if (currentOperationMode != opMode) |
|||
{ |
|||
if (gPrefsSettings.putUChar("operationMode", opMode)) |
|||
{ |
|||
ESP.restart(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
uint8_t System_GetOperationMode(void) |
|||
{ |
|||
return System_OperationMode; |
|||
} |
|||
|
|||
// Reads from NVS, if bluetooth or "normal" mode is desired
|
|||
uint8_t System_GetOperationModeFromNvs(void) |
|||
{ |
|||
return gPrefsSettings.getUChar("operationMode", OPMODE_NORMAL); |
|||
} |
|||
|
|||
// Sets deep-sleep-flag if max. inactivity-time is reached
|
|||
void System_SleepHandler(void) |
|||
{ |
|||
unsigned long m = millis(); |
|||
if (m >= System_LastTimeActiveTimestamp && (m - System_LastTimeActiveTimestamp >= (System_MaxInactivityTime * 1000u * 60u))) |
|||
{ |
|||
Log_Println((char *)FPSTR(goToSleepDueToIdle), LOGLEVEL_INFO); |
|||
System_RequestSleep(); |
|||
} |
|||
else if (System_SleepTimerStartTimestamp > 00) |
|||
{ |
|||
if (m - System_SleepTimerStartTimestamp >= (System_SleepTimer * 1000u * 60u)) |
|||
{ |
|||
Log_Println((char *)FPSTR(goToSleepDueToTimer), LOGLEVEL_INFO); |
|||
System_RequestSleep(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Puts uC to deep-sleep if flag is set
|
|||
void System_DeepSleepManager(void) |
|||
{ |
|||
if (System_GoToSleep) |
|||
{ |
|||
if (System_Sleeping) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
System_Sleeping = true; |
|||
Log_Println((char *)FPSTR(goToSleepNow), LOGLEVEL_NOTICE); |
|||
|
|||
Mqtt_Exit(); |
|||
Led_Exit(); |
|||
|
|||
#ifdef USE_LAST_VOLUME_AFTER_REBOOT
|
|||
gPrefsSettings.putUInt("previousVolume", AudioPlayer_GetCurrentVolume()); |
|||
#endif
|
|||
SdCard_Exit(); |
|||
|
|||
Serial.flush(); |
|||
// switch off power
|
|||
digitalWrite(POWER, LOW); |
|||
delay(200); |
|||
Rfid_Exit(); |
|||
Serial.println(F("deep-sleep, good night.......")); |
|||
esp_deep_sleep_start(); |
|||
} |
|||
} |
@ -0,0 +1,25 @@ |
|||
#pragma once |
|||
#include <Preferences.h> |
|||
|
|||
extern Preferences gPrefsRfid; |
|||
extern Preferences gPrefsSettings; |
|||
|
|||
void System_Init(void); |
|||
void System_Cyclic(void); |
|||
void System_UpdateActivityTimer(void); |
|||
void System_RequestSleep(void); |
|||
bool System_IsSleepRequested(void); |
|||
bool System_SetSleepTimer(uint8_t minutes); |
|||
void System_DisableSleepTimer(); |
|||
bool System_IsSleepTimerEnabled(void); |
|||
uint32_t System_GetSleepTimerTimeStamp(void); |
|||
bool System_IsSleepPending(void); |
|||
uint8_t System_GetSleepTimer(void); |
|||
void System_SetLockControls(bool value); |
|||
void System_ToggleLockControls(void); |
|||
bool System_AreControlsLocked(void); |
|||
void System_IndicateError(void); |
|||
void System_IndicateOk(void); |
|||
void System_SetOperationMode(uint8_t opMode); |
|||
uint8_t System_GetOperationMode(void); |
|||
uint8_t System_GetOperationModeFromNvs(void); |
1066
src/Web.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,5 @@ |
|||
#pragma once |
|||
|
|||
void Web_Init(void); |
|||
void Web_Cyclic(void); |
|||
void Web_SendWebsocketData(uint32_t client, uint8_t code); |
@ -0,0 +1,198 @@ |
|||
#include <Arduino.h>
|
|||
#include <WiFi.h>
|
|||
#include <ESPmDNS.h>
|
|||
#include "settings.h"
|
|||
#include "AudioPlayer.h"
|
|||
#include "RotaryEncoder.h"
|
|||
#include "Log.h"
|
|||
#include "System.h"
|
|||
#include "Web.h"
|
|||
|
|||
// Don't change anything here unless you know what you're doing
|
|||
// HELPER //
|
|||
// WiFi
|
|||
unsigned long wifiCheckLastTimestamp = 0; |
|||
bool wifiEnabled; // Current status if wifi is enabled
|
|||
uint32_t wifiStatusToggledTimestamp = 0; |
|||
bool wifiNeedsRestart = false; |
|||
|
|||
// AP-WiFi
|
|||
IPAddress apIP(192, 168, 4, 1); // Access-point's static IP
|
|||
IPAddress apNetmask(255, 255, 255, 0); // Access-point's netmask
|
|||
bool accessPointStarted = false; |
|||
|
|||
void accessPointStart(const char *SSID, IPAddress ip, IPAddress netmask); |
|||
bool getWifiEnableStatusFromNVS(void); |
|||
void writeWifiStatusToNVS(bool wifiStatus); |
|||
|
|||
void Wlan_Init(void) |
|||
{ |
|||
wifiEnabled = getWifiEnableStatusFromNVS(); |
|||
} |
|||
|
|||
void Wlan_Cyclic(void) |
|||
{ |
|||
// If wifi whould not be activated, return instantly
|
|||
if (!wifiEnabled) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
if (!wifiCheckLastTimestamp || wifiNeedsRestart) |
|||
{ |
|||
// Get credentials from NVS
|
|||
String strSSID = gPrefsSettings.getString("SSID", "-1"); |
|||
if (!strSSID.compareTo("-1")) |
|||
{ |
|||
Log_Println((char *)FPSTR(ssidNotFoundInNvs), LOGLEVEL_ERROR); |
|||
} |
|||
String strPassword = gPrefsSettings.getString("Password", "-1"); |
|||
if (!strPassword.compareTo("-1")) |
|||
{ |
|||
Log_Println((char *)FPSTR(wifiPwdNotFoundInNvs), LOGLEVEL_ERROR); |
|||
} |
|||
const char *_ssid = strSSID.c_str(); |
|||
const char *_pwd = strPassword.c_str(); |
|||
|
|||
// Get (optional) hostname-configration from NVS
|
|||
String hostname = gPrefsSettings.getString("Hostname", "-1"); |
|||
if (hostname.compareTo("-1")) |
|||
{ |
|||
//WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
|||
WiFi.setHostname(hostname.c_str()); |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s: %s", (char *)FPSTR(restoredHostnameFromNvs), hostname.c_str()); |
|||
Log_Println(Log_Buffer, LOGLEVEL_INFO); |
|||
} |
|||
else |
|||
{ |
|||
Log_Println((char *)FPSTR(wifiHostnameNotSet), LOGLEVEL_INFO); |
|||
} |
|||
|
|||
// Add configration of static IP (if requested)
|
|||
#ifdef STATIC_IP_ENABLE
|
|||
snprintf(Log_Buffer, Log_BufferLength, "%s", (char *)FPSTR(tryStaticIpConfig)); |
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
if (!WiFi.config(IPAddress(LOCAL_IP), IPAddress(GATEWAY_IP), IPAddress(SUBNET_IP), IPAddress(DNS_IP))) |
|||
{ |
|||
snprintf(Log_Buffer, Log_BufferLength, "%s", (char *)FPSTR(staticIPConfigFailed)); |
|||
Log_Println(Log_Buffer, LOGLEVEL_ERROR); |
|||
} |
|||
#endif
|
|||
|
|||
// Try to join local WiFi. If not successful, an access-point is opened
|
|||
WiFi.begin(_ssid, _pwd); |
|||
|
|||
uint8_t tryCount = 0; |
|||
while (WiFi.status() != WL_CONNECTED && tryCount <= 4) |
|||
{ |
|||
delay(500); |
|||
Serial.print(F(".")); |
|||
tryCount++; |
|||
wifiCheckLastTimestamp = millis(); |
|||
if (tryCount >= 4 && WiFi.status() == WL_CONNECT_FAILED) |
|||
{ |
|||
WiFi.begin(_ssid, _pwd); // ESP32-workaround (otherwise WiFi-connection sometimes fails)
|
|||
} |
|||
} |
|||
|
|||
if (WiFi.status() == WL_CONNECTED) |
|||
{ |
|||
IPAddress myIP = WiFi.localIP(); |
|||
#if (LANGUAGE == 1)
|
|||
snprintf(Log_Buffer, Log_BufferLength, "Aktuelle IP: %d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]); |
|||
#else
|
|||
snprintf(Log_Buffer, Log_BufferLength, "Current IP: %d.%d.%d.%d", myIP[0], myIP[1], myIP[2], myIP[3]); |
|||
#endif
|
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
} |
|||
else |
|||
{ // Starts AP if WiFi-connect wasn't successful
|
|||
accessPointStart((char *)FPSTR(accessPointNetworkSSID), apIP, apNetmask); |
|||
} |
|||
|
|||
#ifdef MDNS_ENABLE
|
|||
// zero conf, make device available as <hostname>.local
|
|||
if (MDNS.begin(hostname.c_str())) |
|||
{ |
|||
MDNS.addService("http", "tcp", 80); |
|||
} |
|||
#endif
|
|||
|
|||
wifiNeedsRestart = false; |
|||
} |
|||
} |
|||
|
|||
void Wlan_ToggleEnable(void) |
|||
{ |
|||
writeWifiStatusToNVS(!getWifiEnableStatusFromNVS()); |
|||
} |
|||
|
|||
String Wlan_GetIpAddress(void) |
|||
{ |
|||
return WiFi.localIP().toString(); |
|||
} |
|||
|
|||
// Initialize soft access-point
|
|||
void accessPointStart(const char *SSID, IPAddress ip, IPAddress netmask) |
|||
{ |
|||
WiFi.mode(WIFI_AP); |
|||
WiFi.softAPConfig(ip, ip, netmask); |
|||
WiFi.softAP(SSID); |
|||
delay(500); |
|||
|
|||
Log_Println((char *)FPSTR(apReady), LOGLEVEL_NOTICE); |
|||
snprintf(Log_Buffer, Log_BufferLength, "IP-Adresse: %d.%d.%d.%d", apIP[0], apIP[1], apIP[2], apIP[3]); |
|||
Log_Println(Log_Buffer, LOGLEVEL_NOTICE); |
|||
|
|||
Web_Init(); |
|||
|
|||
accessPointStarted = true; |
|||
} |
|||
|
|||
// Reads stored WiFi-status from NVS
|
|||
bool getWifiEnableStatusFromNVS(void) |
|||
{ |
|||
uint32_t wifiStatus = gPrefsSettings.getUInt("enableWifi", 99); |
|||
|
|||
// if not set so far, preseed with 1 (enable)
|
|||
if (wifiStatus == 99) |
|||
{ |
|||
gPrefsSettings.putUInt("enableWifi", 1); |
|||
wifiStatus = 1; |
|||
} |
|||
|
|||
return wifiStatus; |
|||
} |
|||
|
|||
// Writes to NVS whether WiFi should be activated
|
|||
void writeWifiStatusToNVS(bool wifiStatus) |
|||
{ |
|||
if (!wifiStatus) |
|||
{ |
|||
if (gPrefsSettings.putUInt("enableWifi", 0)) |
|||
{ // disable
|
|||
Log_Println((char *)FPSTR(wifiDisabledAfterRestart), LOGLEVEL_NOTICE); |
|||
if (gPlayProperties.playMode == WEBSTREAM) |
|||
{ |
|||
AudioPlayer_TrackControlToQueueSender(STOP); |
|||
} |
|||
delay(300); |
|||
WiFi.mode(WIFI_OFF); |
|||
wifiEnabled = false; |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
if (gPrefsSettings.putUInt("enableWifi", 1)) |
|||
{ // enable
|
|||
Log_Println((char *)FPSTR(wifiEnabledAfterRestart), LOGLEVEL_NOTICE); |
|||
wifiNeedsRestart = true; |
|||
wifiEnabled = true; |
|||
} |
|||
} |
|||
} |
|||
|
|||
bool Wlan_IsConnected(void) |
|||
{ |
|||
return (WiFi.status() == WL_CONNECTED); |
|||
} |
@ -0,0 +1,7 @@ |
|||
#pragma once |
|||
|
|||
void Wlan_Init(void); |
|||
void Wlan_Cyclic(void); |
|||
bool Wlan_IsConnected(void); |
|||
boolean Wlan_ToggleEnable(void); |
|||
String Wlan_GetIpAddress(void); |
@ -1,181 +1,183 @@ |
|||
static const char stillOnlineMqtt[] PROGMEM = "MQTT: Bin noch online."; |
|||
static const char tryConnectMqttS[] PROGMEM = "Versuche Verbindung zu MQTT-Broker aufzubauen"; |
|||
static const char mqttOk[] PROGMEM = "MQTT-Session aufgebaut."; |
|||
static const char sleepTimerEOP[] PROGMEM = "Sleep-Timer: Nach dem letzten Track der Playlist."; |
|||
static const char sleepTimerEOT[] PROGMEM = "Sleep-Timer: Nach dem Ende des laufenden Tracks."; |
|||
static const char sleepTimerStop[] PROGMEM = "Sleep-Timer wurde deaktiviert."; |
|||
static const char sleepTimerEO5[] PROGMEM = "Sleep Timer: Nach Ende des Titels oder, wenn früher, Ende der Playlist"; |
|||
static const char sleepTimerAlreadyStopped[] PROGMEM = "Sleep-Timer ist bereits deaktiviert."; |
|||
static const char sleepTimerSetTo[] PROGMEM = "Sleep-Timer gesetzt auf"; |
|||
static const char allowButtons[] PROGMEM = "Alle Tasten werden freigegeben."; |
|||
static const char lockButtons[] PROGMEM = "Alle Tasten werden gesperrt."; |
|||
static const char noPlaylistNotAllowedMqtt[] PROGMEM = "Playmode kann nicht auf 'Keine Playlist' gesetzt werden via MQTT."; |
|||
static const char playmodeChangedMQtt[] PROGMEM = "Playmode per MQTT angepasst."; |
|||
static const char noPlaymodeChangeIfIdle[] PROGMEM = "Playmode kann nicht verändert werden, wenn keine Playlist aktiv ist."; |
|||
static const char noValidTopic[] PROGMEM = "Kein gültiges Topic"; |
|||
static const char freePtr[] PROGMEM = "Ptr-Freigabe"; |
|||
static const char freeMemory[] PROGMEM = "Freier Speicher"; |
|||
static const char writeEntryToNvs[] PROGMEM = "Schreibe Eintrag in NVS"; |
|||
static const char freeMemoryAfterFree[] PROGMEM = "Freier Speicher nach Aufräumen"; |
|||
static const char releaseMemoryOfOldPlaylist[] PROGMEM = "Gebe Speicher der alten Playlist frei."; |
|||
static const char dirOrFileDoesNotExist[] PROGMEM = "Datei oder Verzeichnis existiert nicht "; |
|||
static const char unableToAllocateMemForPlaylist[] PROGMEM = "Speicher für Playlist konnte nicht allokiert werden!"; |
|||
static const char unableToAllocateMem[] PROGMEM = "Speicher konnte nicht allokiert werden!"; |
|||
static const char fileModeDetected[] PROGMEM = "Dateimodus erkannt."; |
|||
static const char nameOfFileFound[] PROGMEM = "Gefundenes File"; |
|||
static const char reallocCalled[] PROGMEM = "Speicher reallokiert."; |
|||
static const char unableToAllocateMemForLinearPlaylist[] PROGMEM = "Speicher für lineare Playlist konnte nicht allokiert werden!"; |
|||
static const char numberOfValidFiles[] PROGMEM = "Anzahl gültiger Files"; |
|||
static const char newLoudnessReceivedQueue[] PROGMEM = "Neue Lautstärke empfangen via Queue"; |
|||
static const char newCntrlReceivedQueue[] PROGMEM = "Kontroll-Kommando empfangen via Queue"; |
|||
static const char newPlaylistReceived[] PROGMEM = "Neue Playlist empfangen"; |
|||
static const char repeatTrackDueToPlaymode[] PROGMEM = "Wiederhole Titel aufgrund von Playmode."; |
|||
static const char repeatPlaylistDueToPlaymode[] PROGMEM = "Wiederhole Playlist aufgrund von Playmode."; |
|||
static const char cmndStop[] PROGMEM = "Kommando: Stop"; |
|||
static const char cmndPause[] PROGMEM = "Kommando: Pause"; |
|||
static const char cmndNextTrack[] PROGMEM = "Kommando: Nächster Titel"; |
|||
static const char cmndPrevTrack[] PROGMEM = "Kommando: Vorheriger Titel"; |
|||
static const char cmndFirstTrack[] PROGMEM = "Kommando: Erster Titel von Playlist"; |
|||
static const char cmndLastTrack[] PROGMEM = "Kommando: Letzter Titel von Playlist"; |
|||
static const char cmndDoesNotExist[] PROGMEM = "Dieses Kommando existiert nicht."; |
|||
static const char lastTrackAlreadyActive[] PROGMEM = "Es wird bereits der letzte Track gespielt."; |
|||
static const char firstTrackAlreadyActive[] PROGMEM = "Es wird bereits der erste Track gespielt."; |
|||
static const char trackStartAudiobook[] PROGMEM = "Titel wird im Hörspielmodus von vorne gespielt."; |
|||
static const char trackStart[] PROGMEM = "Titel wird von vorne gespielt."; |
|||
static const char trackChangeWebstream[] PROGMEM = "Im Webradio-Modus kann nicht an den Anfang gesprungen werden."; |
|||
static const char endOfPlaylistReached[] PROGMEM = "Ende der Playlist erreicht."; |
|||
static const char trackStartatPos[] PROGMEM = "Titel wird abgespielt ab Position"; |
|||
static const char rfidScannerReady[] PROGMEM = "RFID-Tags koennen jetzt gescannt werden..."; |
|||
static const char rfidTagDetected[] PROGMEM = "RFID-Karte erkannt: "; |
|||
static const char rfid15693TagDetected[] PROGMEM = "RFID-Karte (ISO-15693) erkannt: "; |
|||
static const char rfidTagReceived[] PROGMEM = "RFID-Karte empfangen"; |
|||
static const char rfidTagUnknownInNvs[] PROGMEM = "RFID-Karte ist im NVS nicht hinterlegt."; |
|||
static const char goToSleepDueToIdle[] PROGMEM = "Gehe in Deep Sleep wegen Inaktivität..."; |
|||
static const char goToSleepDueToTimer[] PROGMEM = "Gehe in Deep Sleep wegen Sleep Timer..."; |
|||
static const char goToSleepNow[] PROGMEM = "Gehe jetzt in Deep Sleep!"; |
|||
static const char maxLoudnessReached[] PROGMEM = "Maximale Lautstärke bereits erreicht!"; |
|||
static const char minLoudnessReached[] PROGMEM = "Minimale Lautstärke bereits erreicht!"; |
|||
static const char errorOccured[] PROGMEM = "Fehler aufgetreten!"; |
|||
static const char noMp3FilesInDir[] PROGMEM = "Verzeichnis beinhaltet keine mp3-Files."; |
|||
static const char modeSingleTrack[] PROGMEM = "Modus: Einzelner Track"; |
|||
static const char modeSingleTrackLoop[] PROGMEM = "Modus: Einzelner Track in Endlosschleife"; |
|||
static const char modeSingleAudiobook[] PROGMEM = "Modus: Hoerspiel"; |
|||
static const char modeSingleAudiobookLoop[] PROGMEM = "Modus: Hoerspiel in Endlosschleife"; |
|||
static const char modeAllTrackAlphSorted[] PROGMEM = "Modus: Spiele alle Tracks (alphabetisch sortiert) des Ordners"; |
|||
static const char modeAllTrackRandom[] PROGMEM = "Modus: Alle Tracks eines Ordners zufällig"; |
|||
static const char modeAllTrackAlphSortedLoop[] PROGMEM = "Modus: Alle Tracks eines Ordners sortiert (alphabetisch) in Endlosschleife"; |
|||
static const char modeAllTrackRandomLoop[] PROGMEM = "Modus: Alle Tracks eines Ordners zufällig in Endlosschleife"; |
|||
static const char modeWebstream[] PROGMEM = "Modus: Webstream"; |
|||
static const char webstreamNotAvailable[] PROGMEM = "Aktuell kein Webstream möglich, da keine WLAN-Verbindung vorhanden!"; |
|||
static const char modeDoesNotExist[] PROGMEM = "Abspielmodus existiert nicht!"; |
|||
static const char modeRepeatNone[] PROGMEM = "Repeatmodus: Kein Repeat"; |
|||
static const char modeRepeatTrack[] PROGMEM = "Repeatmodus: Aktueller Titel"; |
|||
static const char modeRepeatPlaylist[] PROGMEM = "Repeatmodus: Gesamte Playlist"; |
|||
static const char modeRepeatTracknPlaylist[] PROGMEM = "Repeatmodus: Track und Playlist"; |
|||
static const char modificatorAllButtonsLocked[] PROGMEM = "Modifikator: Alle Tasten werden per RFID gesperrt."; |
|||
static const char modificatorAllButtonsUnlocked[] PROGMEM = "Modifikator: Alle Tasten werden per RFID freigegeben."; |
|||
static const char modificatorSleepd[] PROGMEM = "Modifikator: Sleep-Timer wieder deaktiviert."; |
|||
static const char modificatorSleepTimer15[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (15 Minuten)."; |
|||
static const char modificatorSleepTimer30[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (30 Minuten)."; |
|||
static const char modificatorSleepTimer60[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (60 Minuten)."; |
|||
static const char modificatorSleepTimer120[] PROGMEM = "Modifikator: Sleep-Timer per RFID aktiviert (2 Stunden)."; |
|||
static const char ledsDimmedToNightmode[] PROGMEM = "LEDs wurden auf Nachtmodus gedimmt."; |
|||
static const char modificatorNotallowedWhenIdle[] PROGMEM = "Modifikator kann bei nicht aktivierter Playlist nicht angewendet werden."; |
|||
static const char modificatorSleepAtEOT[] PROGMEM = "Modifikator: Sleep-Timer am Ende des Titels aktiviert."; |
|||
static const char modificatorSleepAtEOTd[] PROGMEM = "Modifikator: Sleep-Timer am Ende des Titels deaktiviert."; |
|||
static const char modificatorSleepAtEOP[] PROGMEM = "Modifikator: Sleep-Timer am Ende der Playlist aktiviert."; |
|||
static const char modificatorSleepAtEOPd[] PROGMEM = "Modifikator: Sleep-Timer am Ende der Playlist deaktiviert."; |
|||
static const char modificatorAllTrackAlphSortedLoop[] PROGMEM = "Modifikator: Alle Titel (alphabetisch sortiert) in Endlosschleife."; |
|||
static const char modificatorAllTrackRandomLoop[] PROGMEM = "Modifikator: Alle Titel (zufällige Reihenfolge) in Endlosschleife."; |
|||
static const char modificatorCurTrackLoop[] PROGMEM = "Modifikator: Aktueller Titel in Endlosschleife."; |
|||
static const char modificatorCurAudiobookLoop[] PROGMEM = "Modifikator: Aktuelles Hörspiel in Endlosschleife."; |
|||
static const char modificatorPlaylistLoopActive[] PROGMEM = "Modifikator: Alle Titel in Endlosschleife aktiviert."; |
|||
static const char modificatorPlaylistLoopDeactive[] PROGMEM = "Modifikator: Alle Titel in Endlosschleife deaktiviert."; |
|||
static const char modificatorTrackActive[] PROGMEM = "Modifikator: Titel in Endlosschleife aktiviert."; |
|||
static const char modificatorTrackDeactive[] PROGMEM = "Modifikator: Titel in Endlosschleife deaktiviert."; |
|||
static const char modificatorNotAllowed[] PROGMEM = "Modifikator konnte nicht angewendet werden."; |
|||
static const char modificatorLoopRev[] PROGMEM = "Modifikator: Endlosschleife beendet."; |
|||
static const char modificatorDoesNotExist[] PROGMEM = "Ein Karten-Modifikator existiert nicht vom Typ"; |
|||
static const char errorOccuredNvs[] PROGMEM = "Es ist ein Fehler aufgetreten beim Lesen aus dem NVS!"; |
|||
static const char statementsReceivedByServer[] PROGMEM = "Vom Server wurde Folgendes empfangen"; |
|||
static const char savedSsidInNvs[] PROGMEM = "Speichere SSID in NVS"; |
|||
static const char savedWifiPwdInNvs[] PROGMEM = "Speichere WLAN-Password in NVS"; |
|||
static const char apReady[] PROGMEM = "Access-Point geöffnet"; |
|||
static const char httpReady[] PROGMEM = "HTTP-Server gestartet."; |
|||
static const char unableToMountSd[] PROGMEM = "SD-Karte konnte nicht gemountet werden."; |
|||
static const char unableToCreateVolQ[] PROGMEM = "Konnte Volume-Queue nicht anlegen."; |
|||
static const char unableToCreateRfidQ[] PROGMEM = "Konnte RFID-Queue nicht anlegen."; |
|||
static const char unableToCreateMgmtQ[] PROGMEM = "Konnte Play-Management-Queue nicht anlegen."; |
|||
static const char unableToCreatePlayQ[] PROGMEM = "Konnte Track-Queue nicht anlegen.."; |
|||
static const char initialBrightnessfromNvs[] PROGMEM = "Initiale LED-Helligkeit wurde aus NVS geladen"; |
|||
static const char wroteInitialBrightnessToNvs[] PROGMEM = "Initiale LED-Helligkeit wurde ins NVS geschrieben."; |
|||
static const char restoredInitialBrightnessForNmFromNvs[] PROGMEM = "LED-Helligkeit für Nachtmodus wurde aus NVS geladen"; |
|||
static const char wroteNmBrightnessToNvs[] PROGMEM = "LED-Helligkeit für Nachtmodus wurde ins NVS geschrieben."; |
|||
static const char wroteFtpUserToNvs[] PROGMEM = "FTP-User wurde ins NVS geschrieben."; |
|||
static const char restoredFtpUserFromNvs[] PROGMEM = "FTP-User wurde aus NVS geladen"; |
|||
static const char wroteFtpPwdToNvs[] PROGMEM = "FTP-Passwort wurde ins NVS geschrieben."; |
|||
static const char restoredFtpPwdFromNvs[] PROGMEM = "FTP-Passwort wurde aus NVS geladen"; |
|||
static const char restoredMaxInactivityFromNvs[] PROGMEM = "Maximale Inaktivitätszeit wurde aus NVS geladen"; |
|||
static const char wroteMaxInactivityToNvs[] PROGMEM = "Maximale Inaktivitätszeit wurde ins NVS geschrieben."; |
|||
static const char restoredInitialLoudnessFromNvs[] PROGMEM = "Initiale Lautstärke wurde aus NVS geladen"; |
|||
static const char wroteInitialLoudnessToNvs[] PROGMEM = "Initiale Lautstärke wurde ins NVS geschrieben."; |
|||
static const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Maximale Lautstärke für Lautsprecher wurde aus NVS geladen"; |
|||
static const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde aus NVS geladen"; |
|||
static const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Maximale Lautstärke für Lautsprecher wurde ins NVS geschrieben."; |
|||
static const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Maximale Lautstärke für Kopfhörer wurde ins NVS geschrieben."; |
|||
static const char maxVolumeSet[] PROGMEM = "Maximale Lautstärke wurde gesetzt auf"; |
|||
static const char wroteMqttFlagToNvs[] PROGMEM = "MQTT-Flag wurde ins NVS geschrieben."; |
|||
static const char restoredMqttActiveFromNvs[] PROGMEM = "MQTT-Flag (aktiviert) wurde aus NVS geladen"; |
|||
static const char restoredMqttDeactiveFromNvs[] PROGMEM = "MQTT-Flag (deaktiviert) wurde aus NVS geladen"; |
|||
static const char wroteMqttServerToNvs[] PROGMEM = "MQTT-Server wurde ins NVS geschrieben."; |
|||
static const char restoredMqttServerFromNvs[] PROGMEM = "MQTT-Server wurde aus NVS geladen"; |
|||
static const char wroteMqttUserToNvs[] PROGMEM = "MQTT-User wurde ins NVS geschrieben."; |
|||
static const char restoredMqttUserFromNvs[] PROGMEM = "MQTT-User wurde aus NVS geladen"; |
|||
static const char wroteMqttPwdToNvs[] PROGMEM = "MQTT-Passwort wurde ins NVS geschrieben."; |
|||
static const char restoredMqttPwdFromNvs[] PROGMEM = "MQTT-Passwort wurde aus NVS geladen"; |
|||
static const char restoredMqttPortFromNvs[] PROGMEM = "MQTT-Port wurde aus NVS geladen"; |
|||
static const char mqttWithPwd[] PROGMEM = "Verbinde zu MQTT-Server mit User und Passwort"; |
|||
static const char mqttWithoutPwd[] PROGMEM = "Verbinde zu MQTT-Server ohne User und Passwort"; |
|||
static const char ssidNotFoundInNvs[] PROGMEM = "SSID wurde im NVS nicht gefunden."; |
|||
static const char wifiPwdNotFoundInNvs[] PROGMEM = "WLAN-Passwort wurde im NVS nicht gefunden."; |
|||
static const char wifiStaticIpConfigNotFoundInNvs[] PROGMEM = "Statische WLAN-IP-Konfiguration wurde im NVS nicht gefunden."; |
|||
static const char wifiHostnameNotSet[] PROGMEM = "Keine Hostname-Konfiguration im NVS gefunden."; |
|||
static const char mqttConnFailed[] PROGMEM = "Verbindung fehlgeschlagen, versuche in Kürze erneut"; |
|||
static const char restoredHostnameFromNvs[] PROGMEM = "Hostname aus NVS geladen"; |
|||
static const char currentVoltageMsg[] PROGMEM = "Aktuelle Batteriespannung"; |
|||
static const char voltageTooLow[] PROGMEM = "Batteriespannung niedrig"; |
|||
static const char sdBootFailedDeepsleep[] PROGMEM = "Bootgang wegen SD fehlgeschlagen. Gehe in Deepsleep..."; |
|||
static const char wifiEnabledAfterRestart[] PROGMEM = "WLAN wird aktiviert."; |
|||
static const char wifiDisabledAfterRestart[] PROGMEM = "WLAN wird deaktiviert."; |
|||
static const char voltageIndicatorLowFromNVS[] PROGMEM = "Unterer Spannungslevel (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
static const char voltageIndicatorHighFromNVS[] PROGMEM = "Oberer Spannungslevel (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
static const char voltageCheckIntervalFromNVS[] PROGMEM = "Zyklus für Spannungsmessung (Batterie) fuer Neopixel-Anzeige aus NVS geladen"; |
|||
static const char warningLowVoltageFromNVS[] PROGMEM = "Spannungslevel (Batterie) fuer Warnung via Neopixel aus NVS geladen"; |
|||
static const char unableToRestoreLastRfidFromNVS[] PROGMEM = "Letzte RFID konnte nicht aus NVS geladen werden"; |
|||
static const char restoredLastRfidFromNVS[] PROGMEM = "Letzte RFID wurde aus NVS geladen"; |
|||
static const char failedOpenFileForWrite[] PROGMEM = "Öffnen der Datei für den Schreibvorgang fehlgeschlagen"; |
|||
static const char fileWritten[] PROGMEM = "Datei geschrieben"; |
|||
static const char writeFailed[] PROGMEM = "Schreibvorgang fehlgeschlagen"; |
|||
static const char writingFile[] PROGMEM = "Schreibe Datei"; |
|||
static const char failedToOpenFileForAppending[] PROGMEM = "Öffnen der Datei zum Schreiben der JSON-Datei fehlgeschlagen"; |
|||
static const char listingDirectory[] PROGMEM = "Verzeichnisinhalt anzeigen"; |
|||
static const char failedToOpenDirectory[] PROGMEM = "Öffnen des Verzeichnisses fehlgeschlagen"; |
|||
static const char notADirectory[] PROGMEM = "Kein Verzeichnis"; |
|||
static const char sdMountedMmc1BitMode[] PROGMEM = "Versuche SD-Karte wird im SD_MMC-Modus (1 Bit) zu mounten..."; |
|||
static const char sdMountedSpiMode[] PROGMEM = "Versuche SD-Karte wird im SPI-Modus zu mounten..."; |
|||
static const char backupRecoveryWebsite[] PROGMEM = "<p>Das Backup-File wird eingespielt...<br />Zur letzten Seite <a href=\"javascript:history.back()\">zurückkehren</a>.</p>"; |
|||
static const char restartWebsite[] PROGMEM = "<p>Der ESPuino wird neu gestartet...<br />Zur letzten Seite <a href=\"javascript:history.back()\">zurückkehren</a>.</p>"; |
|||
static const char shutdownWebsite[] PROGMEM = "<p>Der ESPuino wird ausgeschaltet...</p>"; |
|||
static const char mqttMsgReceived[] PROGMEM = "MQTT-Nachricht empfangen"; |
|||
static const char trackPausedAtPos[] PROGMEM = "Titel pausiert bei Position"; |
|||
static const char freeHeapWithoutFtp[] PROGMEM = "Freier Heap-Speicher vor FTP-Instanzierung"; |
|||
static const char freeHeapWithFtp[] PROGMEM = "Freier Heap-Speicher nach FTP-Instanzierung"; |
|||
static const char freeHeapAfterSetup[] PROGMEM = "Freier Heap-Speicher nach Setup-Routine"; |
|||
static const char tryStaticIpConfig[] PROGMEM = "Statische IP-Konfiguration wird durchgeführt..."; |
|||
static const char staticIPConfigFailed[] PROGMEM = "Statische IP-Konfiguration fehlgeschlagen"; |
|||
static const char wakeUpRfidNoIso14443[] PROGMEM = "ESP32 wurde vom Kartenleser aus dem Deepsleep aufgeweckt. Allerdings wurde keine ISO-14443-Karte gefunden. Gehe zurück in den Deepsleep..."; |
|||
static const char lowPowerCardSuccess[] PROGMEM = "Kartenerkennung via 'low power' erfolgreich durchgeführt"; |
|||
static const char rememberLastVolume[] PROGMEM = "Lautstärke vor dem letzten Shutdown wird wiederhergestellt. Dies überschreibt die Einstellung der initialen Lautstärke aus der GUI."; |
|||
static const char unableToStartFtpServer[] PROGMEM = "Der FTP-Server konnte nicht gestartet werden. Entweder weil er ist bereits gestartet oder kein WLAN verfügbar ist."; |
|||
static const char newPlayModeStereo[] PROGMEM = "Neuer Modus: stereo"; |
|||
static const char newPlayModeMono[] PROGMEM = "Neuer Modus: mono"; |
|||
#pragma once |
|||
|
|||
extern const char stillOnlineMqtt[]; |
|||
extern const char tryConnectMqttS[]; |
|||
extern const char mqttOk[]; |
|||
extern const char sleepTimerEOP[]; |
|||
extern const char sleepTimerEOT[]; |
|||
extern const char sleepTimerStop[]; |
|||
extern const char sleepTimerEO5[]; |
|||
extern const char sleepTimerAlreadyStopped[]; |
|||
extern const char sleepTimerSetTo[]; |
|||
extern const char allowButtons[]; |
|||
extern const char lockButtons[]; |
|||
extern const char noPlaylistNotAllowedMqtt[]; |
|||
extern const char playmodeChangedMQtt[]; |
|||
extern const char noPlaymodeChangeIfIdle[]; |
|||
extern const char noValidTopic[]; |
|||
extern const char freePtr[]; |
|||
extern const char freeMemory[]; |
|||
extern const char writeEntryToNvs[]; |
|||
extern const char freeMemoryAfterFree[]; |
|||
extern const char releaseMemoryOfOldPlaylist[]; |
|||
extern const char dirOrFileDoesNotExist[]; |
|||
extern const char unableToAllocateMemForPlaylist[]; |
|||
extern const char unableToAllocateMem[]; |
|||
extern const char fileModeDetected[]; |
|||
extern const char nameOfFileFound[]; |
|||
extern const char reallocCalled[]; |
|||
extern const char unableToAllocateMemForLinearPlaylist[]; |
|||
extern const char numberOfValidFiles[]; |
|||
extern const char newLoudnessReceivedQueue[]; |
|||
extern const char newCntrlReceivedQueue[]; |
|||
extern const char newPlaylistReceived[]; |
|||
extern const char repeatTrackDueToPlaymode[]; |
|||
extern const char repeatPlaylistDueToPlaymode[]; |
|||
extern const char cmndStop[]; |
|||
extern const char cmndPause[]; |
|||
extern const char cmndNextTrack[]; |
|||
extern const char cmndPrevTrack[]; |
|||
extern const char cmndFirstTrack[]; |
|||
extern const char cmndLastTrack[]; |
|||
extern const char cmndDoesNotExist[]; |
|||
extern const char lastTrackAlreadyActive[]; |
|||
extern const char firstTrackAlreadyActive[]; |
|||
extern const char trackStartAudiobook[]; |
|||
extern const char trackStart[]; |
|||
extern const char trackChangeWebstream[]; |
|||
extern const char endOfPlaylistReached[]; |
|||
extern const char trackStartatPos[]; |
|||
extern const char rfidScannerReady[]; |
|||
extern const char rfidTagDetected[]; |
|||
extern const char rfid15693TagDetected[]; |
|||
extern const char rfidTagReceived[]; |
|||
extern const char rfidTagUnknownInNvs[]; |
|||
extern const char goToSleepDueToIdle[]; |
|||
extern const char goToSleepDueToTimer[]; |
|||
extern const char goToSleepNow[]; |
|||
extern const char maxLoudnessReached[]; |
|||
extern const char minLoudnessReached[]; |
|||
extern const char errorOccured[]; |
|||
extern const char noMp3FilesInDir[]; |
|||
extern const char modeSingleTrack[]; |
|||
extern const char modeSingleTrackLoop[]; |
|||
extern const char modeSingleAudiobook[]; |
|||
extern const char modeSingleAudiobookLoop[]; |
|||
extern const char modeAllTrackAlphSorted[]; |
|||
extern const char modeAllTrackRandom[]; |
|||
extern const char modeAllTrackAlphSortedLoop[]; |
|||
extern const char modeAllTrackRandomLoop[]; |
|||
extern const char modeWebstream[]; |
|||
extern const char webstreamNotAvailable[]; |
|||
extern const char modeDoesNotExist[]; |
|||
extern const char modeRepeatNone[]; |
|||
extern const char modeRepeatTrack[]; |
|||
extern const char modeRepeatPlaylist[]; |
|||
extern const char modeRepeatTracknPlaylist[]; |
|||
extern const char modificatorAllButtonsLocked[]; |
|||
extern const char modificatorAllButtonsUnlocked[]; |
|||
extern const char modificatorSleepd[]; |
|||
extern const char modificatorSleepTimer15[]; |
|||
extern const char modificatorSleepTimer30[]; |
|||
extern const char modificatorSleepTimer60[]; |
|||
extern const char modificatorSleepTimer120[]; |
|||
extern const char ledsDimmedToNightmode[]; |
|||
extern const char modificatorNotallowedWhenIdle[]; |
|||
extern const char modificatorSleepAtEOT[]; |
|||
extern const char modificatorSleepAtEOTd[]; |
|||
extern const char modificatorSleepAtEOP[]; |
|||
extern const char modificatorSleepAtEOPd[]; |
|||
extern const char modificatorAllTrackAlphSortedLoop[]; |
|||
extern const char modificatorAllTrackRandomLoop[]; |
|||
extern const char modificatorCurTrackLoop[]; |
|||
extern const char modificatorCurAudiobookLoop[]; |
|||
extern const char modificatorPlaylistLoopActive[]; |
|||
extern const char modificatorPlaylistLoopDeactive[]; |
|||
extern const char modificatorTrackActive[]; |
|||
extern const char modificatorTrackDeactive[]; |
|||
extern const char modificatorNotAllowed[]; |
|||
extern const char modificatorLoopRev[]; |
|||
extern const char modificatorDoesNotExist[]; |
|||
extern const char errorOccuredNvs[]; |
|||
extern const char statementsReceivedByServer[]; |
|||
extern const char savedSsidInNvs[]; |
|||
extern const char savedWifiPwdInNvs[]; |
|||
extern const char apReady[]; |
|||
extern const char httpReady[]; |
|||
extern const char unableToMountSd[]; |
|||
extern const char unableToCreateVolQ[]; |
|||
extern const char unableToCreateRfidQ[]; |
|||
extern const char unableToCreateMgmtQ[]; |
|||
extern const char unableToCreatePlayQ[]; |
|||
extern const char initialBrightnessfromNvs[]; |
|||
extern const char wroteInitialBrightnessToNvs[]; |
|||
extern const char restoredInitialBrightnessForNmFromNvs[]; |
|||
extern const char wroteNmBrightnessToNvs[]; |
|||
extern const char wroteFtpUserToNvs[]; |
|||
extern const char restoredFtpUserFromNvs[]; |
|||
extern const char wroteFtpPwdToNvs[]; |
|||
extern const char restoredFtpPwdFromNvs[]; |
|||
extern const char restoredMaxInactivityFromNvs[]; |
|||
extern const char wroteMaxInactivityToNvs[]; |
|||
extern const char restoredInitialLoudnessFromNvs[]; |
|||
extern const char wroteInitialLoudnessToNvs[]; |
|||
extern const char restoredMaxLoudnessForSpeakerFromNvs[]; |
|||
extern const char restoredMaxLoudnessForHeadphoneFromNvs[]; |
|||
extern const char wroteMaxLoudnessForSpeakerToNvs[]; |
|||
extern const char wroteMaxLoudnessForHeadphoneToNvs[]; |
|||
extern const char maxVolumeSet[]; |
|||
extern const char wroteMqttFlagToNvs[]; |
|||
extern const char restoredMqttActiveFromNvs[]; |
|||
extern const char restoredMqttDeactiveFromNvs[]; |
|||
extern const char wroteMqttServerToNvs[]; |
|||
extern const char restoredMqttServerFromNvs[]; |
|||
extern const char wroteMqttUserToNvs[]; |
|||
extern const char restoredMqttUserFromNvs[]; |
|||
extern const char wroteMqttPwdToNvs[]; |
|||
extern const char restoredMqttPwdFromNvs[]; |
|||
extern const char restoredMqttPortFromNvs[]; |
|||
extern const char mqttWithPwd[]; |
|||
extern const char mqttWithoutPwd[]; |
|||
extern const char ssidNotFoundInNvs[]; |
|||
extern const char wifiPwdNotFoundInNvs[]; |
|||
extern const char wifiStaticIpConfigNotFoundInNvs[]; |
|||
extern const char wifiHostnameNotSet[]; |
|||
extern const char mqttConnFailed[]; |
|||
extern const char restoredHostnameFromNvs[]; |
|||
extern const char currentVoltageMsg[]; |
|||
extern const char voltageTooLow[]; |
|||
extern const char sdBootFailedDeepsleep[]; |
|||
extern const char wifiEnabledAfterRestart[]; |
|||
extern const char wifiDisabledAfterRestart[]; |
|||
extern const char voltageIndicatorLowFromNVS[]; |
|||
extern const char voltageIndicatorHighFromNVS[]; |
|||
extern const char voltageCheckIntervalFromNVS[]; |
|||
extern const char warningLowVoltageFromNVS[]; |
|||
extern const char unableToRestoreLastRfidFromNVS[]; |
|||
extern const char restoredLastRfidFromNVS[]; |
|||
extern const char failedOpenFileForWrite[]; |
|||
extern const char fileWritten[]; |
|||
extern const char writeFailed[]; |
|||
extern const char writingFile[]; |
|||
extern const char failedToOpenFileForAppending[]; |
|||
extern const char listingDirectory[]; |
|||
extern const char failedToOpenDirectory[]; |
|||
extern const char notADirectory[]; |
|||
extern const char sdMountedMmc1BitMode[]; |
|||
extern const char sdMountedSpiMode[]; |
|||
extern const char backupRecoveryWebsite[]; |
|||
extern const char restartWebsite[]; |
|||
extern const char shutdownWebsite[]; |
|||
extern const char mqttMsgReceived[]; |
|||
extern const char trackPausedAtPos[]; |
|||
extern const char freeHeapWithoutFtp[]; |
|||
extern const char freeHeapWithFtp[]; |
|||
extern const char freeHeapAfterSetup[]; |
|||
extern const char tryStaticIpConfig[]; |
|||
extern const char staticIPConfigFailed[]; |
|||
extern const char wakeUpRfidNoIso14443[]; |
|||
extern const char lowPowerCardSuccess[]; |
|||
extern const char rememberLastVolume[]; |
|||
extern const char unableToStartFtpServer[]; |
|||
extern const char newPlayModeStereo[]; |
|||
extern const char newPlayModeMono[]; |
@ -1,181 +0,0 @@ |
|||
static const char stillOnlineMqtt[] PROGMEM = "MQTT: still online."; |
|||
static const char tryConnectMqttS[] PROGMEM = "Trying to connect to MQTT-broker"; |
|||
static const char mqttOk[] PROGMEM = "MQTT-connection established."; |
|||
static const char sleepTimerEOP[] PROGMEM = "Sleep-timer: after last track of playlist."; |
|||
static const char sleepTimerEOT[] PROGMEM = "Sleep-timer: after end of current track."; |
|||
static const char sleepTimerStop[] PROGMEM = "Sleep-timer has been disabled."; |
|||
static const char sleepTimerEO5[] PROGMEM = "Sleep-timer: after five track or end of playlist - whatever is reached first"; |
|||
static const char sleepTimerAlreadyStopped[] PROGMEM = "sleep-timer is already disabled."; |
|||
static const char sleepTimerSetTo[] PROGMEM = "sleep-timer adjusted to"; |
|||
static const char allowButtons[] PROGMEM = "Unlocking all keys."; |
|||
static const char lockButtons[] PROGMEM = "Locking all keys."; |
|||
static const char noPlaylistNotAllowedMqtt[] PROGMEM = "Playmode cannot be adjusted to 'no playlist' via MQTT."; |
|||
static const char playmodeChangedMQtt[] PROGMEM = "Playlist adjusted via MQTT."; |
|||
static const char noPlaymodeChangeIfIdle[] PROGMEM = "Playlist cannot be adjusted while no playlist is active."; |
|||
static const char noValidTopic[] PROGMEM = "No valid MQTT-topic"; |
|||
static const char freePtr[] PROGMEM = "Releasing Pointer"; |
|||
static const char freeMemory[] PROGMEM = "Free memory"; |
|||
static const char writeEntryToNvs[] PROGMEM = "Storing data to NVS"; |
|||
static const char freeMemoryAfterFree[] PROGMEM = "Free memory after cleaning"; |
|||
static const char releaseMemoryOfOldPlaylist[] PROGMEM = "Releasing memory of old playlist."; |
|||
static const char dirOrFileDoesNotExist[] PROGMEM = "File of directory does not exist"; |
|||
static const char unableToAllocateMemForPlaylist[] PROGMEM = "Unable to allocate memory for playlist!"; |
|||
static const char unableToAllocateMem[] PROGMEM = "Unable to allocate memory!"; |
|||
static const char fileModeDetected[] PROGMEM = "File-mode detected."; |
|||
static const char nameOfFileFound[] PROGMEM = "File found"; |
|||
static const char reallocCalled[] PROGMEM = "Reallocated memory."; |
|||
static const char unableToAllocateMemForLinearPlaylist[] PROGMEM = "Unable to allocate memory for linear playlist!"; |
|||
static const char numberOfValidFiles[] PROGMEM = "Number of valid files"; |
|||
static const char newLoudnessReceivedQueue[] PROGMEM = "New volume received via queue"; |
|||
static const char newCntrlReceivedQueue[] PROGMEM = "Control-command received via queue"; |
|||
static const char newPlaylistReceived[] PROGMEM = "New playlist received"; |
|||
static const char repeatTrackDueToPlaymode[] PROGMEM = "Repeating track due to playmode configured."; |
|||
static const char repeatPlaylistDueToPlaymode[] PROGMEM = "Repeating playlist due to playmode configured."; |
|||
static const char cmndStop[] PROGMEM = "Command: stop"; |
|||
static const char cmndPause[] PROGMEM = "Command: pause"; |
|||
static const char cmndNextTrack[] PROGMEM = "Command: next track"; |
|||
static const char cmndPrevTrack[] PROGMEM = "Command: previous track"; |
|||
static const char cmndFirstTrack[] PROGMEM = "Command: first track of playlist"; |
|||
static const char cmndLastTrack[] PROGMEM = "Command: last track of playlist"; |
|||
static const char cmndDoesNotExist[] PROGMEM = "Command requested does not exist."; |
|||
static const char lastTrackAlreadyActive[] PROGMEM = "Already playing last track."; |
|||
static const char firstTrackAlreadyActive[] PROGMEM = "Already playing first track."; |
|||
static const char trackStartAudiobook[] PROGMEM = "Starting track in playmode from the very beginning."; |
|||
static const char trackStart[] PROGMEM = "Starting track from the very beginning."; |
|||
static const char trackChangeWebstream[] PROGMEM = "Playing from the very beginning is not possible while webradio-mode is active."; |
|||
static const char endOfPlaylistReached[] PROGMEM = "Reached end of playlist."; |
|||
static const char trackStartatPos[] PROGMEM = "Starting track at position"; |
|||
static const char rfidScannerReady[] PROGMEM = "RFID-tags can now be applied..."; |
|||
static const char rfidTagDetected[] PROGMEM = "RFID-tag detected: "; |
|||
static const char rfid15693TagDetected[] PROGMEM = "RFID-ta (ISO-15693) detected: "; |
|||
static const char rfidTagReceived[] PROGMEM = "RFID-tag received"; |
|||
static const char rfidTagUnknownInNvs[] PROGMEM = "RFID-tag is unkown to NVS."; |
|||
static const char goToSleepDueToIdle[] PROGMEM = "Going to deepsleep due to inactivity-timer..."; |
|||
static const char goToSleepDueToTimer[] PROGMEM = "Going to deepsleep due to sleep timer..."; |
|||
static const char goToSleepNow[] PROGMEM = "Going to deepsleep now!"; |
|||
static const char maxLoudnessReached[] PROGMEM = "Already reached max volume!"; |
|||
static const char minLoudnessReached[] PROGMEM = "Already reached min volume!"; |
|||
static const char errorOccured[] PROGMEM = "Error occured!"; |
|||
static const char noMp3FilesInDir[] PROGMEM = "Directory does not contain mp3-files."; |
|||
static const char modeSingleTrack[] PROGMEM = "Mode: Single track"; |
|||
static const char modeSingleTrackLoop[] PROGMEM = "Mode: single track as infinite loop"; |
|||
static const char modeSingleAudiobook[] PROGMEM = "Mode: audiobook"; |
|||
static const char modeSingleAudiobookLoop[] PROGMEM = "Mode: audiobook as infinite loop"; |
|||
static const char modeAllTrackAlphSorted[] PROGMEM = "Mode: all tracks (in alph. order) of directory"; |
|||
static const char modeAllTrackRandom[] PROGMEM = "Mode: all tracks (in random. order) of directory"; |
|||
static const char modeAllTrackAlphSortedLoop[] PROGMEM = "Mode: all tracks (in alph. order) of directory as infinite loop"; |
|||
static const char modeAllTrackRandomLoop[] PROGMEM = "Mode: all tracks (in random order) of directory as infinite loop"; |
|||
static const char modeWebstream[] PROGMEM = "Mode: webstream"; |
|||
static const char webstreamNotAvailable[] PROGMEM = "Unable to access webstream as no wifi-connection is available!"; |
|||
static const char modeDoesNotExist[] PROGMEM = "Playmode does not exist!"; |
|||
static const char modeRepeatNone[] PROGMEM = "Repeatmode: no repeat"; |
|||
static const char modeRepeatTrack[] PROGMEM = "Repeatmode: current track"; |
|||
static const char modeRepeatPlaylist[] PROGMEM = "Repeatmode: whole playlist"; |
|||
static const char modeRepeatTracknPlaylist[] PROGMEM = "Repeatmode: track and playlist"; |
|||
static const char modificatorAllButtonsLocked[] PROGMEM = "Modificator: locking all keys via RFID-tag."; |
|||
static const char modificatorAllButtonsUnlocked[] PROGMEM = "Modificator: unlocking all keys via RFID-tag."; |
|||
static const char modificatorSleepd[] PROGMEM = "Modificator: sleep-Timer deactivated."; |
|||
static const char modificatorSleepTimer15[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (15 minutes)."; |
|||
static const char modificatorSleepTimer30[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (30 minutes)."; |
|||
static const char modificatorSleepTimer60[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (60 minutes)."; |
|||
static const char modificatorSleepTimer120[] PROGMEM = "Modificator: sleep-Timer enabled via RFID (2 hours)."; |
|||
static const char ledsDimmedToNightmode[] PROGMEM = "Dimmed LEDs to nightmode."; |
|||
static const char modificatorNotallowedWhenIdle[] PROGMEM = "Modificator cannot be applied while playlist is inactive."; |
|||
static const char modificatorSleepAtEOT[] PROGMEM = "Modificator: adjusted sleep-timer to after end of current track."; |
|||
static const char modificatorSleepAtEOTd[] PROGMEM = "Modificator: disabled sleep-timer after end of current track."; |
|||
static const char modificatorSleepAtEOP[] PROGMEM = "Modificator: adjusted sleep-timer to after end of playlist."; |
|||
static const char modificatorSleepAtEOPd[] PROGMEM = "Modificator: disabled sleep-timer after end of playlist."; |
|||
static const char modificatorAllTrackAlphSortedLoop[] PROGMEM = "Modificator: adjusted to all tracks (in alph. order) as infinite loop."; |
|||
static const char modificatorAllTrackRandomLoop[] PROGMEM = "Modificator: adjusted to all tracks (in random order) as infinite loop."; |
|||
static const char modificatorCurTrackLoop[] PROGMEM = "Modificator: adjusted to current track as infinite loop."; |
|||
static const char modificatorCurAudiobookLoop[] PROGMEM = "Modificator: adjusted to current audiobook as infinite loop."; |
|||
static const char modificatorPlaylistLoopActive[] PROGMEM = "Modificator: adjusted to all tracks as infinite loop."; |
|||
static const char modificatorPlaylistLoopDeactive[] PROGMEM = "Modificator: disabled all tracks as infinite loop."; |
|||
static const char modificatorTrackActive[] PROGMEM = "Modificator: adjusted to current track as infinite loop."; |
|||
static const char modificatorTrackDeactive[] PROGMEM = "Modificator: disabled current track as infinite loop."; |
|||
static const char modificatorNotAllowed[] PROGMEM = "Unable to apply modificator."; |
|||
static const char modificatorLoopRev[] PROGMEM = "Modificator: infinite loop ended."; |
|||
static const char modificatorDoesNotExist[] PROGMEM = "This type of card-modificator does not exist"; |
|||
static const char errorOccuredNvs[] PROGMEM = "Error occured while reading from NVS!"; |
|||
static const char statementsReceivedByServer[] PROGMEM = "Data received from server"; |
|||
static const char savedSsidInNvs[] PROGMEM = "Storing SSID to NVS"; |
|||
static const char savedWifiPwdInNvs[] PROGMEM = "Storing wifi-password to NVS"; |
|||
static const char apReady[] PROGMEM = "Started wifi-access-point"; |
|||
static const char httpReady[] PROGMEM = "Started HTTP-server."; |
|||
static const char unableToMountSd[] PROGMEM = "Unable to mount sd-card."; |
|||
static const char unableToCreateVolQ[] PROGMEM = "Unable to create volume-queue."; |
|||
static const char unableToCreateRfidQ[] PROGMEM = "Unable to create RFID-queue."; |
|||
static const char unableToCreateMgmtQ[] PROGMEM = "Unable to play-management-queue."; |
|||
static const char unableToCreatePlayQ[] PROGMEM = "Unable to create track-queue.."; |
|||
static const char initialBrightnessfromNvs[] PROGMEM = "Restoring initial LED-brightness from NVS"; |
|||
static const char wroteInitialBrightnessToNvs[] PROGMEM = "Storing initial LED-brightness to NVS."; |
|||
static const char restoredInitialBrightnessForNmFromNvs[] PROGMEM = "Restored LED-brightness for nightmode from NVS"; |
|||
static const char wroteNmBrightnessToNvs[] PROGMEM = "Stored LED-brightness for nightmode to NVS."; |
|||
static const char wroteFtpUserToNvs[] PROGMEM = "Stored FTP-user to NVS."; |
|||
static const char restoredFtpUserFromNvs[] PROGMEM = "Restored FTP-user from NVS"; |
|||
static const char wroteFtpPwdToNvs[] PROGMEM = "Stored FTP-password to NVS."; |
|||
static const char restoredFtpPwdFromNvs[] PROGMEM = "Restored FTP-password from NVS"; |
|||
static const char restoredMaxInactivityFromNvs[] PROGMEM = "Restored maximum inactivity-time from NVS."; |
|||
static const char wroteMaxInactivityToNvs[] PROGMEM = "Stored maximum inactivity-time to NVS."; |
|||
static const char restoredInitialLoudnessFromNvs[] PROGMEM = "Restored initial volume from NVS"; |
|||
static const char wroteInitialLoudnessToNvs[] PROGMEM = "Stored initial volume to NVS."; |
|||
static const char restoredMaxLoudnessForSpeakerFromNvs[] PROGMEM = "Restored maximum volume for speaker from NVS"; |
|||
static const char restoredMaxLoudnessForHeadphoneFromNvs[] PROGMEM = "Restored maximum volume for headphone from NVS"; |
|||
static const char wroteMaxLoudnessForSpeakerToNvs[] PROGMEM = "Wrote maximum volume for speaker to NVS."; |
|||
static const char wroteMaxLoudnessForHeadphoneToNvs[] PROGMEM = "Wrote maximum volume for headphone to NVS."; |
|||
static const char maxVolumeSet[] PROGMEM = "Maximum volume set to"; |
|||
static const char wroteMqttFlagToNvs[] PROGMEM = "Stored MQTT-flag to NVS."; |
|||
static const char restoredMqttActiveFromNvs[] PROGMEM = "Restored MQTT-flag (enabled) from NVS"; |
|||
static const char restoredMqttDeactiveFromNvs[] PROGMEM = "Restored MQTT-flag (disabled) from NVS"; |
|||
static const char wroteMqttServerToNvs[] PROGMEM = "Stored MQTT-server to NVS."; |
|||
static const char restoredMqttServerFromNvs[] PROGMEM = "Restored MQTT-Server from NVS"; |
|||
static const char wroteMqttUserToNvs[] PROGMEM = "Stored MQTT-user to NVS."; |
|||
static const char restoredMqttUserFromNvs[] PROGMEM = "Restored MQTT-user from NVS"; |
|||
static const char wroteMqttPwdToNvs[] PROGMEM = "Stored MQTT-password to NVS."; |
|||
static const char restoredMqttPwdFromNvs[] PROGMEM = "Restored MQTT-password from NVS"; |
|||
static const char restoredMqttPortFromNvs[] PROGMEM = "Restored MQTT-port from NVS"; |
|||
static const char mqttWithPwd[] PROGMEM = "Try to connect to MQTT-server with user und password"; |
|||
static const char mqttWithoutPwd[] PROGMEM = "Try to connect to MQTT-server without user und password"; |
|||
static const char ssidNotFoundInNvs[] PROGMEM = "Unable to find SSID to NVS."; |
|||
static const char wifiPwdNotFoundInNvs[] PROGMEM = "Unable to find wifi-password to NVS."; |
|||
static const char wifiStaticIpConfigNotFoundInNvs[] PROGMEM = "Unable to find static wifi-ip-configuration to NVS."; |
|||
static const char wifiHostnameNotSet[] PROGMEM = "Unable to find hostname-configuration to NVS."; |
|||
static const char mqttConnFailed[] PROGMEM = "Unable to establish mqtt-connection, trying again..."; |
|||
static const char restoredHostnameFromNvs[] PROGMEM = "Restored hostname from NVS"; |
|||
static const char currentVoltageMsg[] PROGMEM = "Current battery-voltage"; |
|||
static const char voltageTooLow[] PROGMEM = "Low battery-voltage"; |
|||
static const char sdBootFailedDeepsleep[] PROGMEM = "Failed to boot due to SD. Will go to deepsleep..."; |
|||
static const char wifiEnabledAfterRestart[] PROGMEM = "WiFi will be enabled."; |
|||
static const char wifiDisabledAfterRestart[] PROGMEM = "WiFi will be disabled ."; |
|||
static const char voltageIndicatorLowFromNVS[] PROGMEM = "Restored lower voltage-level for Neopixel-display from NVS"; |
|||
static const char voltageIndicatorHighFromNVS[] PROGMEM = "Restored upper voltage-level for Neopixel-display from NVS"; |
|||
static const char voltageCheckIntervalFromNVS[] PROGMEM = "Restored interval of battery-measurement or Neopixel-display from NVS"; |
|||
static const char warningLowVoltageFromNVS[] PROGMEM = "Restored battery-voltage-level for warning via Neopixel from NVS"; |
|||
static const char unableToRestoreLastRfidFromNVS[] PROGMEM = "Unable to restore last RFID from NVS"; |
|||
static const char restoredLastRfidFromNVS[] PROGMEM = "Restored last RFID from NVS"; |
|||
static const char failedOpenFileForWrite[] PROGMEM = "Failed to open file for writing"; |
|||
static const char fileWritten[] PROGMEM = "File written"; |
|||
static const char writeFailed[] PROGMEM = "Write failed"; |
|||
static const char writingFile[] PROGMEM = "Writing file"; |
|||
static const char failedToOpenFileForAppending[] PROGMEM = "Failed to open file for appending"; |
|||
static const char listingDirectory[] PROGMEM = "Listing directory"; |
|||
static const char failedToOpenDirectory[] PROGMEM = "Failed to open directory"; |
|||
static const char notADirectory[] PROGMEM = "Not a directory"; |
|||
static const char sdMountedMmc1BitMode[] PROGMEM = "SD card mounted in SPI-mode configured..."; |
|||
static const char sdMountedSpiMode[] PROGMEM = "Mounting SD card in SPI-mode..."; |
|||
static const char backupRecoveryWebsite[] PROGMEM = "<p>Backup-file is being applied...<br />Back to <a href=\"javascript:history.back()\">last page</a>.</p>"; |
|||
static const char restartWebsite[] PROGMEM = "<p>ESPuino is being restarted...<br />Back to <a href=\"javascript:history.back()\">last page</a>.</p>"; |
|||
static const char shutdownWebsite[] PROGMEM = "<p>Der ESPuino is being shutdown...</p>"; |
|||
static const char mqttMsgReceived[] PROGMEM = "MQTT-message received"; |
|||
static const char trackPausedAtPos[] PROGMEM = "Track paused at position"; |
|||
static const char freeHeapWithoutFtp[] PROGMEM = "Free heap before FTP-allocation"; |
|||
static const char freeHeapWithFtp[] PROGMEM = "Free heap after FTP-allocation"; |
|||
static const char freeHeapAfterSetup[] PROGMEM = "Free heap after setup"; |
|||
static const char tryStaticIpConfig[] PROGMEM = "Performing static IP-configuration..."; |
|||
static const char staticIPConfigFailed[] PROGMEM = "Static IP-configuration failed"; |
|||
static const char wakeUpRfidNoIso14443[] PROGMEM = "Wakeup caused by low power card-detection. RF-field changed but no ISO-14443 card on reader was found. So I'll return back to sleep now..."; |
|||
static const char lowPowerCardSuccess[] PROGMEM = "Switch to low power card-detection: success"; |
|||
static const char rememberLastVolume[] PROGMEM = "Restored volume used before last shutdown. This overwrites the initial volume configured via webgui."; |
|||
static const char unableToStartFtpServer[] PROGMEM = "FTP-server cannot be started. This is because FTP-service is already active of because WiFi is unavailable."; |
|||
static const char newPlayModeStereo[] PROGMEM = "New mode: stereo"; |
|||
static const char newPlayModeMono[] PROGMEM = "New mode: mono"; |
5329
src/main.cpp
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue