diff --git a/html/index.html b/html/index.html index 40dc24113..e21f91340 100644 --- a/html/index.html +++ b/html/index.html @@ -252,7 +252,7 @@ Last Error: - + @@ -279,7 +279,7 @@ Last Error: - + @@ -302,7 +302,7 @@ Last Error: - + @@ -330,10 +330,6 @@ Time Remaining: - - Last Error: - - diff --git a/html/script.js b/html/script.js index dfff51ba1..2fd8ce2dd 100644 --- a/html/script.js +++ b/html/script.js @@ -2213,7 +2213,7 @@ function ProcessReceivedJsonStatusMessage(JsonStat) { $('#fppremoteFilePlayerFilename').text(FPPDstatus.current_sequence); $('#fppremoteFilePlayerTimeElapsed').text(FPPDstatus.time_elapsed); $('#fppremoteFilePlayerTimeRemaining').text(FPPDstatus.time_remaining); - $('#fppremotelasterror').text(FPPDstatus.errors); + $('#fppremoteFilePlayerlasterror').text(FPPDstatus.errors); } else { $('#FPPRemoteStatus').addClass("hidden") @@ -2226,6 +2226,7 @@ function ProcessReceivedJsonStatusMessage(JsonStat) { $('#localFilePlayerFilename').text(FilePlayerStatus.current_sequence); $('#localFilePlayerTimeElapsed').text(FilePlayerStatus.time_elapsed); $('#localFilePlayerTimeRemaining').text(FilePlayerStatus.time_remaining); + $('#localFilePlayerlasterror').text(FilePlayerStatus.errors); } else { $('#LocalFilePlayerStatus').addClass("hidden"); diff --git a/include/ConstNames.hpp b/include/ConstNames.hpp index e6c0a055c..de8452ccf 100644 --- a/include/ConstNames.hpp +++ b/include/ConstNames.hpp @@ -92,6 +92,7 @@ extern const CN_PROGMEM char CN_Effect []; extern const CN_PROGMEM char CN_effects []; extern const CN_PROGMEM char CN_en []; extern const CN_PROGMEM char CN_enabled []; +extern const CN_PROGMEM char CN_entry []; extern const CN_PROGMEM char CN_errors []; extern const CN_PROGMEM char CN_ESP32 []; extern const CN_PROGMEM char CN_ESP8266 []; diff --git a/include/ESPixelStick.h b/include/ESPixelStick.h index 7b9243dc6..335949454 100644 --- a/include/ESPixelStick.h +++ b/include/ESPixelStick.h @@ -92,9 +92,9 @@ bool setFromJSON (T& OutValue, JsonObject & Json, N Name) { bool HasBeenModified = false; - if (Json[Name].template is()) + if (Json[(char*)Name].template is()) { - T temp = Json[Name]; + T temp = Json[(char*)Name]; if (temp != OutValue) { OutValue = temp; @@ -115,9 +115,9 @@ bool setFromJSON (T& OutValue, JsonVariant & Json, N Name) { bool HasBeenModified = false; - if (Json[Name].template is()) + if (Json[(char*)Name].template is()) { - T temp = Json[Name]; + T temp = Json[(char*)Name]; if (temp != OutValue) { OutValue = temp; @@ -133,6 +133,8 @@ bool setFromJSON (T& OutValue, JsonVariant & Json, N Name) return HasBeenModified; }; +#define JsonWrite(j, n, v) (j)[(char*)(n)] = (v) + #define logcon(msg) \ { \ String DN; \ diff --git a/include/input/InputAlexa.h b/include/input/InputAlexa.h index fa24cae88..7e2294020 100644 --- a/include/input/InputAlexa.h +++ b/include/input/InputAlexa.h @@ -37,7 +37,7 @@ class c_InputAlexa : public c_InputCommon bool SetConfig (JsonObject& jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject& jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject& jsonStatus); - void Process (bool StayDark); + void Process (); void GetDriverName (String& sDriverName) { sDriverName = "Alexa"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); diff --git a/include/input/InputArtnet.hpp b/include/input/InputArtnet.hpp index c58545188..5240c943e 100644 --- a/include/input/InputArtnet.hpp +++ b/include/input/InputArtnet.hpp @@ -3,7 +3,7 @@ * ArtnetInput.h - Code to wrap ESPAsyncArtnet for input * * Project: ESPixelStick - An ESP8266 / ESP32 and Artnet based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -79,6 +79,6 @@ class c_InputArtnet : public c_InputCommon void SetBufferInfo (uint32_t BufferSize); void NetworkStateChanged (bool IsConnected); // used by poorly designed rx functions bool isShutDownRebootNeeded () { return HasBeenInitialized; } - virtual void Process (bool StayDark) {} ///< Call from loop(), renders Input data + virtual void Process () {} ///< Call from loop(), renders Input data }; diff --git a/include/input/InputCommon.hpp b/include/input/InputCommon.hpp index 0d980ec06..db129741a 100644 --- a/include/input/InputCommon.hpp +++ b/include/input/InputCommon.hpp @@ -3,7 +3,7 @@ * InputCommon.hpp - Input base class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -36,7 +36,7 @@ class c_InputCommon virtual bool SetConfig (ArduinoJson::JsonObject & jsonConfig) = 0; ///< Set a new config in the driver virtual void GetConfig (ArduinoJson::JsonObject & jsonConfig) = 0; ///< Get the current config used by the driver virtual void GetStatus (JsonObject & jsonStatus) = 0; - virtual void Process (bool StayDark) = 0; ///< Call from loop(), renders Input data + virtual void Process (void) = 0; ///< Call from loop(), renders Input data virtual void GetDriverName (String & sDriverName) = 0; ///< get the name for the instantiated driver virtual void SetBufferInfo (uint32_t BufferSize) = 0; virtual void SetOperationalState (bool ActiveFlag) { IsInputChannelActive = ActiveFlag; } @@ -49,7 +49,7 @@ class c_InputCommon protected: bool HasBeenInitialized = false; - uint32_t InputDataBufferSize = 0; + uint32_t InputDataBufferSize = 0; bool IsInputChannelActive = true; c_InputMgr::e_InputChannelIds InputChannelId = c_InputMgr::e_InputChannelIds::InputChannelId_ALL; c_InputMgr::e_InputType ChannelType = c_InputMgr::e_InputType::InputType_Disabled; diff --git a/include/input/InputDDP.h b/include/input/InputDDP.h index 480a5f4d0..0782331c5 100644 --- a/include/input/InputDDP.h +++ b/include/input/InputDDP.h @@ -137,7 +137,7 @@ class c_InputDDP : public c_InputCommon bool SetConfig (JsonObject& jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject& jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject& jsonStatus); - void Process (bool StayDark); ///< Call from loop(), renders Input data + void Process (); ///< Call from loop(), renders Input data void GetDriverName (String& sDriverName) { sDriverName = "DDP"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); bool isShutDownRebootNeeded () { return HasBeenInitialized; } diff --git a/include/input/InputDisabled.hpp b/include/input/InputDisabled.hpp index 85ee765d1..855898a19 100644 --- a/include/input/InputDisabled.hpp +++ b/include/input/InputDisabled.hpp @@ -38,7 +38,7 @@ class c_InputDisabled : public c_InputCommon bool SetConfig (JsonObject & jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject & jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject & jsonStatus); - void Process (bool StayDark); + void Process (); void GetDriverName (String& sDriverName) { sDriverName = "Disabled"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize) {} diff --git a/include/input/InputE131.hpp b/include/input/InputE131.hpp index a9312ffea..9d48bc6f1 100644 --- a/include/input/InputE131.hpp +++ b/include/input/InputE131.hpp @@ -69,7 +69,7 @@ class c_InputE131 : public c_InputCommon bool SetConfig (JsonObject & jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject & jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject & jsonStatus); - void Process (bool StayDark); + void Process (); void GetDriverName (String & sDriverName) { sDriverName = "E1.31"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); void NetworkStateChanged (bool IsConnected); // used by poorly designed rx functions diff --git a/include/input/InputEffectEngine.hpp b/include/input/InputEffectEngine.hpp index e5742b37c..5b46cd626 100644 --- a/include/input/InputEffectEngine.hpp +++ b/include/input/InputEffectEngine.hpp @@ -102,7 +102,7 @@ class c_InputEffectEngine : public c_InputCommon void GetMqttConfig (MQTTConfiguration_s& mqttConfig); ///< Get the current config used by the driver void GetMqttEffectList (JsonObject& jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject& jsonStatus); - void Process (bool StayDark); + void Process (); void Poll (); ///< Call from loop(), renders Input data void GetDriverName (String & sDriverName) { sDriverName = "Effects"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); diff --git a/include/input/InputFPPRemote.h b/include/input/InputFPPRemote.h index dbfb2fab9..e10c8f361 100644 --- a/include/input/InputFPPRemote.h +++ b/include/input/InputFPPRemote.h @@ -38,23 +38,20 @@ class c_InputFPPRemote : public c_InputCommon bool SetConfig (JsonObject& jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject& jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject& jsonStatus); - void Process (bool StayDark); - void TaskProcess (); ///< Call from loop(), renders Input data + void Process (); void GetDriverName (String& sDriverName) { sDriverName = "FPP Remote"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); void ProcessButtonActions(c_ExternalInput::InputValue_t value); + void SetOperationalState (bool ActiveFlag); protected: # define No_LocalFileToPlay "..." -# define FPP_REMOTE_TASK_PRIORITY 5 c_InputFPPRemotePlayItem * pInputFPPRemotePlayItem = nullptr; int32_t GetSyncOffsetMS () { return SyncOffsetMS; } - bool GetSendFppSync () { return SendFppSync; } + bool GetSendFppSync () { return SendFppSync; } String StatusType; - bool StayDark = false; - bool Disabled = false; private: diff --git a/include/input/InputFPPRemotePlayEffect.hpp b/include/input/InputFPPRemotePlayEffect.hpp index d669ae93e..8d404d7a5 100644 --- a/include/input/InputFPPRemotePlayEffect.hpp +++ b/include/input/InputFPPRemotePlayEffect.hpp @@ -33,7 +33,7 @@ class c_InputFPPRemotePlayEffect : public c_InputFPPRemotePlayItem virtual void Start (String & FileName, float duration, uint32_t PlayCount); virtual void Stop (); virtual void Sync (String & FileName, float SecondsElapsed); - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void GetStatus (JsonObject & jsonStatus); virtual bool IsIdle () { return (pCurrentFsmState == &fsm_PlayEffect_state_Idle_imp); } diff --git a/include/input/InputFPPRemotePlayEffectFsm.hpp b/include/input/InputFPPRemotePlayEffectFsm.hpp index 2ae6ca18d..eefce94f9 100644 --- a/include/input/InputFPPRemotePlayEffectFsm.hpp +++ b/include/input/InputFPPRemotePlayEffectFsm.hpp @@ -35,7 +35,7 @@ class fsm_PlayEffect_state fsm_PlayEffect_state() {} virtual ~fsm_PlayEffect_state() {} - virtual bool Poll (bool StayDark) = 0; + virtual bool Poll () = 0; virtual void Init (c_InputFPPRemotePlayEffect * Parent) = 0; virtual void GetStateName (String & sName) = 0; virtual void Start (String & FileName, float SecondsElapsed) = 0; @@ -56,7 +56,7 @@ class fsm_PlayEffect_state_Idle : public fsm_PlayEffect_state fsm_PlayEffect_state_Idle() {} virtual ~fsm_PlayEffect_state_Idle() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayEffect* Parent); virtual void GetStateName (String & sName) { sName = CN_Idle; } virtual void Start (String & FileName, float SecondsElapsed); @@ -73,7 +73,7 @@ class fsm_PlayEffect_state_PlayingEffect : public fsm_PlayEffect_state fsm_PlayEffect_state_PlayingEffect() {} virtual ~fsm_PlayEffect_state_PlayingEffect() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayEffect* Parent); virtual void GetStateName (String & sName) { sName = CN_Effect; } virtual void Start (String & FileName, float SecondsElapsed); diff --git a/include/input/InputFPPRemotePlayFile.hpp b/include/input/InputFPPRemotePlayFile.hpp index 19006ef8c..f878bd778 100644 --- a/include/input/InputFPPRemotePlayFile.hpp +++ b/include/input/InputFPPRemotePlayFile.hpp @@ -23,13 +23,11 @@ #include "InputFPPRemotePlayItem.hpp" #include "InputFPPRemotePlayFileFsm.hpp" #include "service/fseq.h" -#include #ifdef ARDUINO_ARCH_ESP32 #include #endif // def ARDUINO_ARCH_ESP32 - class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem { public: @@ -39,11 +37,10 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (); virtual void Sync (String& FileName, float SecondsElapsed); - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void GetStatus (JsonObject & jsonStatus); virtual bool IsIdle () { return (pCurrentFsmState == &fsm_PlayFile_state_Idle_imp); } - void TimerPoll (); #ifdef ARDUINO_ARCH_ESP32 TaskHandle_t GetTaskHandle () { return TimerPollTaskHandle; } volatile bool TimerPollInProgress = false; @@ -52,7 +49,7 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem private: #define ELAPSED_PLAY_TIMER_INTERVAL_MS 10 - void ClearFileInfo (); + void ClearFileInfo (); friend class fsm_PlayFile_state_Idle; friend class fsm_PlayFile_state_Starting; @@ -69,18 +66,6 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem fsm_PlayFile_state * pCurrentFsmState = &fsm_PlayFile_state_Idle_imp; - c_FileMgr::FileId FileHandleForFileBeingPlayed = c_FileMgr::INVALID_FILE_HANDLE; - - struct FrameControl_t - { - uint32_t DataOffset = 0; - uint32_t ChannelsPerFrame = 0; - uint32_t FrameStepTimeMS = 1; - uint32_t TotalNumberOfFramesInSequence = 0; - uint32_t ElapsedPlayTimeMS = 0; - - } FrameControl; - struct SyncControl_t { uint32_t SyncCount = 0; @@ -88,24 +73,15 @@ class c_InputFPPRemotePlayFile : public c_InputFPPRemotePlayItem float LastRcvdElapsedSeconds = 0.0; } SyncControl; -# define FPP_TICKER_PERIOD_MS 25 -// # define FPP_TICKER_PERIOD_MS 1000 - Ticker MsTicker; - uint32_t LastIsrTimeStampMS = 0; uint32_t PlayedFileCount = 0; - // Logic to detect if polls have stopped coming in. - // This is part of the blanking logic. - int PollDetectionCounter = 0; - static const int PollDetectionCounterLimit = 5; - #define MAX_NUM_SPARSE_RANGES 5 FSEQParsedRangeEntry SparseRanges[MAX_NUM_SPARSE_RANGES]; void UpdateElapsedPlayTimeMS (); uint32_t CalculateFrameId (uint32_t ElapsedMS, int32_t SyncOffsetMS); bool ParseFseqFile (); - uint32_t ReadFile(uint32_t DestinationIntensityId, uint32_t NumBytesToRead, uint32_t FileOffset); + uint32_t ReadFile(uint32_t DestinationIntensityId, uint32_t NumBytesToRead, uint32_t FileOffset); String LastFailedPlayStatusMsg; diff --git a/include/input/InputFPPRemotePlayFileFsm.hpp b/include/input/InputFPPRemotePlayFileFsm.hpp index e601a3e20..e95cbf9a6 100644 --- a/include/input/InputFPPRemotePlayFileFsm.hpp +++ b/include/input/InputFPPRemotePlayFileFsm.hpp @@ -36,14 +36,13 @@ class fsm_PlayFile_state fsm_PlayFile_state() {} virtual ~fsm_PlayFile_state() {} - virtual bool Poll (bool StayDark) = 0; + virtual IRAM_ATTR bool Poll () = 0; virtual void Init (c_InputFPPRemotePlayFile * Parent) = 0; virtual void GetStateName (String & sName) = 0; virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount) = 0; virtual void Stop (void) = 0; virtual bool Sync (String& FileName, float SecondsElapsed) = 0; void GetDriverName (String& Name) { Name = "InputMgr"; } - virtual IRAM_ATTR void TimerPoll () = 0; protected: c_InputFPPRemotePlayFile * p_Parent = nullptr; @@ -57,13 +56,12 @@ class fsm_PlayFile_state_Idle : public fsm_PlayFile_state fsm_PlayFile_state_Idle() {} virtual ~fsm_PlayFile_state_Idle() {} - virtual bool Poll (bool StayDark); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String & sName) { sName = CN_Idle; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); }; // fsm_PlayFile_state_Idle @@ -74,13 +72,12 @@ class fsm_PlayFile_state_Starting : public fsm_PlayFile_state fsm_PlayFile_state_Starting() {} virtual ~fsm_PlayFile_state_Starting() {} - virtual bool Poll (bool StayDark); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F ("Starting"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); }; // fsm_PlayFile_state_Starting @@ -91,13 +88,12 @@ class fsm_PlayFile_state_PlayingFile : public fsm_PlayFile_state fsm_PlayFile_state_PlayingFile() {} virtual ~fsm_PlayFile_state_PlayingFile() {} - virtual bool Poll (bool StayDark); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String & sName) { sName = CN_File; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String & FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: struct SparseRange @@ -105,7 +101,7 @@ class fsm_PlayFile_state_PlayingFile : public fsm_PlayFile_state uint32_t DataOffset; uint32_t ChannelCount; }; - uint32_t LastPlayedFrameId = 0; + // uint32_t LastPlayedFrameId = 0; }; // fsm_PlayFile_state_PlayingFile @@ -116,18 +112,14 @@ class fsm_PlayFile_state_Stopping : public fsm_PlayFile_state fsm_PlayFile_state_Stopping() {} virtual ~fsm_PlayFile_state_Stopping() {} - virtual bool Poll (bool StayDark); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F("Stopping"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: - String FileName = ""; - uint32_t StartingElapsedTime = 0.0; - uint32_t PlayCount = 0; }; // fsm_PlayFile_state_Stopping @@ -138,13 +130,12 @@ class fsm_PlayFile_state_Error : public fsm_PlayFile_state fsm_PlayFile_state_Error() {} virtual ~fsm_PlayFile_state_Error() {} - virtual bool Poll (bool StayDark); + virtual IRAM_ATTR bool Poll (); virtual void Init (c_InputFPPRemotePlayFile* Parent); virtual void GetStateName (String& sName) { sName = F ("Error"); } virtual void Start (String& FileName, float SecondsElapsed, uint32_t RemainingPlayCount); virtual void Stop (void); virtual bool Sync (String& FileName, float SecondsElapsed); - virtual IRAM_ATTR void TimerPoll (); private: diff --git a/include/input/InputFPPRemotePlayItem.hpp b/include/input/InputFPPRemotePlayItem.hpp index 05a3b1e12..5be34eb74 100644 --- a/include/input/InputFPPRemotePlayItem.hpp +++ b/include/input/InputFPPRemotePlayItem.hpp @@ -24,32 +24,52 @@ class c_InputFPPRemotePlayItem { +protected: + time_t PlayDurationSec = 0; + bool SendFppSync = false; + +private: + bool InputPaused = false; + int32_t SyncOffsetMS = 0; + c_InputMgr::e_InputChannelIds InputChannelId = c_InputMgr::e_InputChannelIds::InputChannelId_ALL; + public: c_InputFPPRemotePlayItem (c_InputMgr::e_InputChannelIds InputChannelId); virtual ~c_InputFPPRemotePlayItem (); - virtual bool Poll (bool StayDark) = 0; + struct FileControl_t + { + String FileName; + c_FileMgr::FileId FileHandleForFileBeingPlayed = c_FileMgr::INVALID_FILE_HANDLE; + uint32_t RemainingPlayCount = 0; + uint32_t DataOffset = 0; + uint32_t ChannelsPerFrame = 0; + uint32_t FrameStepTimeMS = 25; + uint32_t TotalNumberOfFramesInSequence = 0; + uint32_t ElapsedPlayTimeMS = 0; + uint32_t StartingTimeMS = 0; + uint32_t LastPollTimeMS = 0; + uint32_t LastPlayedFrameId = 0; + } FileControl[2]; + #define CurrentFile 0 + #define NextFile 1 + + virtual bool Poll () = 0; virtual void Start (String & FileName, float SecondsElapsed, uint32_t RemainingPlayCount) = 0; virtual void Stop () = 0; + virtual void SetPauseState (bool _PauseInput) {InputPaused = _PauseInput;} virtual void Sync (String & FileName, float SecondsElapsed) = 0; virtual void GetStatus (JsonObject & jsonStatus) = 0; virtual bool IsIdle () = 0; - String GetFileName () { return PlayItemName; } - uint32_t GetRepeatCount () { return RemainingPlayCount; } + String GetFileName () { return FileControl[CurrentFile].FileName; } + uint32_t GetRepeatCount () { return FileControl[CurrentFile].RemainingPlayCount; } void SetDuration (time_t value) { PlayDurationSec = value; } void GetDriverName (String& Name) { Name = "InputMgr"; } int32_t GetSyncOffsetMS () { return SyncOffsetMS; } void SetSyncOffsetMS (int32_t value) { SyncOffsetMS = value; } void SetSendFppSync (bool value) { SendFppSync = value; } c_InputMgr::e_InputChannelIds GetInputChannelId () { return InputChannelId; } -protected: - String PlayItemName; - uint32_t RemainingPlayCount = 0; - time_t PlayDurationSec = 0; - bool SendFppSync = false; - -private: - int32_t SyncOffsetMS = 0; - c_InputMgr::e_InputChannelIds InputChannelId = c_InputMgr::e_InputChannelIds::InputChannelId_ALL; + bool InputIsPaused () { return InputPaused; } + void SetOperationalState (bool ActiveFlag) {InputPaused = !ActiveFlag;} }; // c_InputFPPRemotePlayItem diff --git a/include/input/InputFPPRemotePlayList.hpp b/include/input/InputFPPRemotePlayList.hpp index bda8a63e9..d0f08ab04 100644 --- a/include/input/InputFPPRemotePlayList.hpp +++ b/include/input/InputFPPRemotePlayList.hpp @@ -34,7 +34,7 @@ class c_InputFPPRemotePlayList : public c_InputFPPRemotePlayItem virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); virtual void Stop (); virtual void Sync (String & FileName, float SecondsElapsed); - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void GetStatus (JsonObject & jsonStatus); virtual bool IsIdle () { return (pCurrentFsmState == &fsm_PlayList_state_Idle_imp); } diff --git a/include/input/InputFPPRemotePlayListFsm.hpp b/include/input/InputFPPRemotePlayListFsm.hpp index 89d455bce..1c3a05d5a 100644 --- a/include/input/InputFPPRemotePlayListFsm.hpp +++ b/include/input/InputFPPRemotePlayListFsm.hpp @@ -35,7 +35,7 @@ class fsm_PlayList_state fsm_PlayList_state() {} virtual ~fsm_PlayList_state() {} - virtual bool Poll (bool StayDark) = 0; + virtual bool Poll () = 0; virtual void Init (c_InputFPPRemotePlayList * Parent) = 0; virtual void GetStateName (String & sName) = 0; virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount) = 0; @@ -56,7 +56,7 @@ class fsm_PlayList_state_WaitForStart : public fsm_PlayList_state fsm_PlayList_state_WaitForStart() {} virtual ~fsm_PlayList_state_WaitForStart() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayList* Parent); virtual void GetStateName (String & sName) { sName = CN_Idle; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); @@ -72,7 +72,7 @@ class fsm_PlayList_state_Idle : public fsm_PlayList_state fsm_PlayList_state_Idle() {} virtual ~fsm_PlayList_state_Idle() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayList* Parent); virtual void GetStateName (String & sName) { sName = CN_Idle; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); @@ -88,7 +88,7 @@ class fsm_PlayList_state_PlayingFile : public fsm_PlayList_state fsm_PlayList_state_PlayingFile() {} virtual ~fsm_PlayList_state_PlayingFile() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayList* Parent); virtual void GetStateName (String & sName) { sName = CN_File; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); @@ -104,7 +104,7 @@ class fsm_PlayList_state_PlayingEffect : public fsm_PlayList_state fsm_PlayList_state_PlayingEffect() {} virtual ~fsm_PlayList_state_PlayingEffect() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayList* Parent); virtual void GetStateName (String & sName) { sName = CN_Effect; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); @@ -120,7 +120,7 @@ class fsm_PlayList_state_Paused : public fsm_PlayList_state fsm_PlayList_state_Paused() {} virtual ~fsm_PlayList_state_Paused() {} - virtual bool Poll (bool StayDark); + virtual bool Poll (); virtual void Init (c_InputFPPRemotePlayList* Parent); virtual void GetStateName (String & sName) { sName = CN_Paused; } virtual void Start (String & FileName, float SecondsElapsed, uint32_t PlayCount); diff --git a/include/input/InputMQTT.h b/include/input/InputMQTT.h index 46c77f665..775944f96 100644 --- a/include/input/InputMQTT.h +++ b/include/input/InputMQTT.h @@ -41,7 +41,7 @@ class c_InputMQTT : public c_InputCommon bool SetConfig (JsonObject& jsonConfig); ///< Set a new config in the driver void GetConfig (JsonObject& jsonConfig); ///< Get the current config used by the driver void GetStatus (JsonObject& jsonStatus); - void Process (bool StayDark); + void Process (); void GetDriverName (String& sDriverName) { sDriverName = "MQTT"; } ///< get the name for the instantiated driver void SetBufferInfo (uint32_t BufferSize); void NetworkStateChanged (bool IsConnected); // used by poorly designed rx functions diff --git a/include/input/InputMgr.hpp b/include/input/InputMgr.hpp index 908d2d76b..8942d1549 100644 --- a/include/input/InputMgr.hpp +++ b/include/input/InputMgr.hpp @@ -3,7 +3,7 @@ * InputMgr.hpp - Input Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -27,6 +27,7 @@ #include "output/OutputMgr.hpp" #include "externalInput.h" #include +#include class c_InputCommon; ///< forward declaration to the pure virtual Input class that will be defined later. @@ -94,6 +95,7 @@ class c_InputMgr }; #define NO_CONFIG_NEEDED time_t(-1) + #define INPUTMGR_TASK_PRIORITY 5 DriverInfo_t InputChannelDrivers[InputChannelId_End]; ///< pointer(s) to the current active Input driver uint32_t InputDataBufferSize = 0; @@ -103,6 +105,7 @@ class c_InputMgr bool IsConnected = false; bool configInProgress = false; time_t ConfigLoadNeeded = NO_CONFIG_NEEDED; + bool PauseProcessing = false; // configuration parameter names for the channel manager within the config file # define IM_EffectsControlButtonName F ("ecb") @@ -118,6 +121,10 @@ class c_InputMgr FastTimer BlankEndTime[InputChannelId_End]; +# define FPP_TICKER_PERIOD_MS 25 + Ticker MsTicker; + uint32_t LastTickerTimeStampMS = 0; + }; // c_InputMgr extern c_InputMgr InputMgr; diff --git a/include/input/externalInput.h b/include/input/externalInput.h index cb848b772..409674db8 100644 --- a/include/input/externalInput.h +++ b/include/input/externalInput.h @@ -42,7 +42,7 @@ class c_ExternalInput final }; void Init (uint32_t iInputId, uint32_t iPinId, Polarity_t Poliarity, String & sName); - void Poll (bool StayDark); + void Poll (void); void GetConfig (JsonObject JsonData); void GetStatistics (JsonObject JsonData); void ProcessConfig (JsonObject JsonData); diff --git a/include/output/OutputMgr.hpp b/include/output/OutputMgr.hpp index c8e449447..59cd30dff 100644 --- a/include/output/OutputMgr.hpp +++ b/include/output/OutputMgr.hpp @@ -3,7 +3,7 @@ * OutputMgr.hpp - Output Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -238,7 +238,7 @@ class c_OutputMgr bool HasBeenInitialized = false; time_t ConfigLoadNeeded = NO_CONFIG_NEEDED; bool ConfigInProgress = false; - bool IsOutputPaused = false; + bool OutputIsPaused = false; bool BuildingNewConfig = false; bool ProcessJsonConfig (JsonDocument & jsonConfig); diff --git a/include/platforms/GPIO_Defs_ESP32_D1_MINI.hpp b/include/platforms/GPIO_Defs_ESP32_D1_MINI.hpp index bb2f64886..c7e6453cf 100644 --- a/include/platforms/GPIO_Defs_ESP32_D1_MINI.hpp +++ b/include/platforms/GPIO_Defs_ESP32_D1_MINI.hpp @@ -3,7 +3,7 @@ * GPIO_Defs_ESP32_D1_MINI.hpp - Output Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2024 Shelby Merrick +* Copyright (c) 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -22,9 +22,9 @@ #define DEFAULT_RMT_0_GPIO gpio_num_t::GPIO_NUM_2 #define DEFAULT_RMT_1_GPIO gpio_num_t::GPIO_NUM_4 -#define DEFAULT_RMT_2_GPIO gpio_num_t::GPIO_NUM_0 -#define DEFAULT_RMT_3_GPIO gpio_num_t::GPIO_NUM_5 -#define DEFAULT_RMT_4_GPIO gpio_num_t::GPIO_NUM_16 +#define DEFAULT_RMT_2_GPIO gpio_num_t::GPIO_NUM_12 +#define DEFAULT_RMT_3_GPIO gpio_num_t::GPIO_NUM_14 +#define DEFAULT_RMT_4_GPIO gpio_num_t::GPIO_NUM_16 // SPI Output #define SUPPORT_SPI_OUTPUT diff --git a/include/platforms/GPIO_Defs_ESP32_D1_MINI_ETH.hpp b/include/platforms/GPIO_Defs_ESP32_D1_MINI_ETH.hpp index 18dc02ab8..60f0e1d86 100644 --- a/include/platforms/GPIO_Defs_ESP32_D1_MINI_ETH.hpp +++ b/include/platforms/GPIO_Defs_ESP32_D1_MINI_ETH.hpp @@ -3,7 +3,7 @@ * GPIO_Defs_ESP32_D1_MINI_ETH.hpp - Output Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021 Shelby Merrick +* Copyright (c) 2021 - 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -23,9 +23,9 @@ //Output Manager #define DEFAULT_RMT_0_GPIO gpio_num_t::GPIO_NUM_2 #define DEFAULT_RMT_1_GPIO gpio_num_t::GPIO_NUM_4 -#define DEFAULT_RMT_2_GPIO gpio_num_t::GPIO_NUM_0 -#define DEFAULT_RMT_3_GPIO gpio_num_t::GPIO_NUM_5 -#define DEFAULT_RMT_4_GPIO gpio_num_t::GPIO_NUM_16 +#define DEFAULT_RMT_2_GPIO gpio_num_t::GPIO_NUM_12 +#define DEFAULT_RMT_3_GPIO gpio_num_t::GPIO_NUM_14 +#define DEFAULT_RMT_4_GPIO gpio_num_t::GPIO_NUM_16 #define DEFAULT_I2C_SDA gpio_num_t::GPIO_NUM_21 #define DEFAULT_I2C_SCL gpio_num_t::GPIO_NUM_22 diff --git a/include/service/FPPDiscovery.h b/include/service/FPPDiscovery.h index c81ab10c0..926125311 100644 --- a/include/service/FPPDiscovery.h +++ b/include/service/FPPDiscovery.h @@ -3,7 +3,7 @@ * c_FPPDiscovery.h * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2018, 2022 Shelby Merrick +* Copyright (c) 2018, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -46,9 +46,11 @@ class c_FPPDiscovery bool PlayingFile (); bool inFileUpload = false; + bool writeFailed = false; bool hasBeenInitialized = false; bool IsEnabled = false; bool BlankOnStop = false; + bool StopInProgress = false; String UploadFileName; IPAddress FppRemoteIp = IPAddress (uint32_t(0)); c_InputFPPRemotePlayFile * InputFPPRemotePlayFile = nullptr; @@ -114,24 +116,25 @@ SystemDebugStats_t SystemDebugStats; void begin (); - void ProcessFPPJson (AsyncWebServerRequest* request); - void ProcessFPPDJson (AsyncWebServerRequest* request); - void ProcessGET (AsyncWebServerRequest* request); - void ProcessPOST (AsyncWebServerRequest* request); - void ProcessFile (AsyncWebServerRequest* request, String filename, uint32_t index, uint8_t* data, uint32_t len, bool final, uint32_t contentLength = 0); - void ProcessBody (AsyncWebServerRequest* request, uint8_t* data, uint32_t len, uint32_t index, uint32_t total); - void sendPingPacket (IPAddress destination = IPAddress(255, 255, 255, 255)); - void PlayFile (String & FileToPlay); - void Enable (void); - void Disable (void); - void GetStatus (JsonObject& jsonStatus); + void ProcessFPPJson (AsyncWebServerRequest* request); + void ProcessFPPDJson (AsyncWebServerRequest* request); + void ProcessGET (AsyncWebServerRequest* request); + void ProcessPOST (AsyncWebServerRequest* request); + void ProcessFile (AsyncWebServerRequest* request, String filename, uint32_t index, uint8_t* data, uint32_t len, bool final, uint32_t contentLength = 0); + void ProcessBody (AsyncWebServerRequest* request, uint8_t* data, uint32_t len, uint32_t index, uint32_t total); + void sendPingPacket (IPAddress destination = IPAddress(255, 255, 255, 255)); + void PlayFile (String & FileToPlay); + void Enable (void); + void Disable (void); + void GetStatus (JsonObject& jsonStatus); void NetworkStateChanged (bool NewNetworkState); + void SetOperationalState (bool ActiveFlag); - void SetBlankOnStop (bool value) {BlankOnStop = value;} - bool GetBlankOnStop (void) {return BlankOnStop;} - void SetInputFPPRemotePlayFile (c_InputFPPRemotePlayFile * value); + void SetBlankOnStop (bool value) {BlankOnStop = value;} + bool GetBlankOnStop (void) {return BlankOnStop;} + void SetInputFPPRemotePlayFile (c_InputFPPRemotePlayFile * value); void ForgetInputFPPRemotePlayFile (); - void GenerateFppSyncMsg (uint8_t Action, const String & FileName, uint32_t CurrentFrame, const float & ElpsedTime); + void GenerateFppSyncMsg (uint8_t Action, const String & FileName, uint32_t CurrentFrame, const float & ElpsedTime); # define SYNC_PKT_START 0 # define SYNC_PKT_STOP 1 diff --git a/platformio.ini b/platformio.ini index f9b628640..f3b88f282 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,7 +23,7 @@ upload_speed = 921600 lib_compat_mode = strict lib_deps = adafruit/Adafruit PWM Servo Driver Library @ ^2.4.0 - bblanchon/ArduinoJson @ ^7.2.0 + bblanchon/ArduinoJson @ 7.3.0 djgrrr/Int64String @ ^1.1.1 forkineye/ESPAsyncE131 @ ^1.0.5 greiman/SdFat @ ^2.2.3 diff --git a/src/ConstNames.cpp b/src/ConstNames.cpp index 043940ae0..d8cf21ef3 100644 --- a/src/ConstNames.cpp +++ b/src/ConstNames.cpp @@ -83,6 +83,7 @@ const CN_PROGMEM char CN_Effect [] = "Effect"; const CN_PROGMEM char CN_effects [] = "effects"; const CN_PROGMEM char CN_en [] = "en"; const CN_PROGMEM char CN_enabled [] = "enabled"; +const CN_PROGMEM char CN_entry [] = "entry"; const CN_PROGMEM char CN_errors [] = "errors"; const CN_PROGMEM char CN_ESP32 [] = "ESP32"; const CN_PROGMEM char CN_ESP8266 [] = "ESP8266"; diff --git a/src/FileMgr.cpp b/src/FileMgr.cpp index 5048e7f72..1118d552d 100644 --- a/src/FileMgr.cpp +++ b/src/FileMgr.cpp @@ -2,7 +2,7 @@ * FileMgr.cpp - Output Management class * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2024 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -228,7 +228,7 @@ bool c_FileMgr::SetConfig (JsonObject & json) // DEBUG_START; bool ConfigChanged = false; - JsonObject JsonDeviceConfig = json[CN_device]; + JsonObject JsonDeviceConfig = json[(char*)CN_device].as(); if (JsonDeviceConfig) { // PrettyPrint (JsonDeviceConfig, "c_FileMgr"); @@ -280,15 +280,15 @@ void c_FileMgr::GetConfig (JsonObject& json) { // DEBUG_START; - json[CN_miso_pin] = miso_pin; - json[CN_mosi_pin] = mosi_pin; - json[CN_clock_pin] = clk_pin; - json[CN_cs_pin] = cs_pin; - json[CN_sdspeed] = MaxSdSpeed; + JsonWrite(json, CN_miso_pin, miso_pin); + JsonWrite(json, CN_mosi_pin, mosi_pin); + JsonWrite(json, CN_clock_pin, clk_pin); + JsonWrite(json, CN_cs_pin, cs_pin); + JsonWrite(json, CN_sdspeed, MaxSdSpeed); - json[CN_user] = FtpUserName; - json[CN_password] = FtpPassword; - json[CN_enabled] = FtpEnabled; + JsonWrite(json, CN_user, FtpUserName); + JsonWrite(json, CN_password, FtpPassword); + JsonWrite(json, CN_enabled, FtpEnabled); // DEBUG_END; @@ -1457,9 +1457,15 @@ void c_FileMgr::CloseSdFile (FileId& FileHandle, bool LockStatus) { if(!FileList[FileListIndex].Paused) { + // DEBUG_V("Close the file"); delay(10); FileList[FileListIndex].fsFile.close (); } + else + { + // DEBUG_V("File is paused. Not closing"); + } + FileList[FileListIndex].IsOpen = false; FileList[FileListIndex].handle = INVALID_FILE_HANDLE; FileList[FileListIndex].Paused = false; @@ -1468,6 +1474,7 @@ void c_FileMgr::CloseSdFile (FileId& FileHandle, bool LockStatus) { if(FileList[FileListIndex].buffer.DataBuffer != OutputMgr.GetBufferAddress()) { + // only free the buffer if it is not malloc'd free(FileList[FileListIndex].buffer.DataBuffer); } } @@ -1581,12 +1588,12 @@ size_t c_FileMgr::WriteSdFileBuf (const FileId& FileHandle, byte* FileData, size // DEBUG_V(String(" Offset: ") + String(FileList[FileListIndex].buffer.offset)); if(WontFit || WriteRemainder) { - delay(10); + delay(20); FeedWDT(); // DEBUG_V("Buffer cant hold this data. Write out the buffer"); - size_t bufferWriteSize = FileList[FileListIndex].fsFile.write(FileData, FileList[FileListIndex].buffer.offset); + size_t bufferWriteSize = FileList[FileListIndex].fsFile.write(FileList[FileListIndex].buffer.DataBuffer, FileList[FileListIndex].buffer.offset); FileList[FileListIndex].fsFile.flush(); - delay(20); + delay(30); FeedWDT(); if(FileList[FileListIndex].buffer.offset != bufferWriteSize) { @@ -1601,8 +1608,8 @@ size_t c_FileMgr::WriteSdFileBuf (const FileId& FileHandle, byte* FileData, size } // End buffer cant take the new data // DEBUG_V(String("Writing ") + String(NumBytesToWrite) + " bytes to the buffer"); - memcpy(&FileList[FileListIndex].buffer.DataBuffer[FileList[FileListIndex].buffer.offset], - FileData, NumBytesToWrite); + memcpy(&(FileList[FileListIndex].buffer.DataBuffer[FileList[FileListIndex].buffer.offset]), FileData, NumBytesToWrite); + FileList[FileListIndex].buffer.offset += NumBytesToWrite; NumBytesWritten = NumBytesToWrite; } @@ -1708,19 +1715,19 @@ void c_FileMgr::BuildFseqList(bool LockStatus) ESP_SD.chdir(); // Set to sd root if(!InputFile.open ("/", O_READ)) { - logcon(F("ERROR: Could not open SD card.")); + logcon(F("ERROR: Could not open SD card for Reading FSEQ List.")); break; } // open output file, erase old data ESP_SD.chdir(); // Set to sd root - DeleteSdFile(String(FSEQFILELIST), true); + DeleteSdFile(String(F(FSEQFILELIST)), true); FsFile OutputFile; if(!OutputFile.open (String(F(FSEQFILELIST)).c_str(), O_WRITE | O_CREAT)) { InputFile.close(); - logcon(F("ERROR: Could not Open SD file list.")); + logcon(F("ERROR: Could not open SD card for writting FSEQ List.")); break; } OutputFile.print("{"); @@ -1864,6 +1871,7 @@ bool c_FileMgr::handleFileUpload ( // DEBUG_V("New File"); handleFileUploadNewFile (filename); expectedIndex = 0; + LOG_PORT.println("."); } if (index != expectedIndex) @@ -1875,6 +1883,7 @@ bool c_FileMgr::handleFileUpload ( CloseSdFile(fsUploadFileHandle, false); DeleteSdFile (fsUploadFileName, false); fsUploadFileHandle = INVALID_FILE_HANDLE; + delay(1000); BuildFseqList(false); expectedIndex = 0; fsUploadFileName = emptyString; @@ -1894,7 +1903,8 @@ bool c_FileMgr::handleFileUpload ( // DEBUG_V ("UploadWrite: " + String (len) + String (" bytes")); bytesWritten = WriteSdFileBuf (fsUploadFileHandle, data, len, false); // DEBUG_V (String ("Writing bytes: ") + String (index)); - // LOG_PORT.print ("."); + LOG_PORT.println(String("\033[Fprogress: ") + String(expectedIndex)); + LOG_PORT.flush(); } // PauseSdFile(fsUploadFile); @@ -1904,6 +1914,7 @@ bool c_FileMgr::handleFileUpload ( CloseSdFile(fsUploadFileHandle, false); DeleteSdFile (fsUploadFileName, false); fsUploadFileHandle = INVALID_FILE_HANDLE; + delay(1000); BuildFseqList(false); expectedIndex = 0; fsUploadFileName = emptyString; @@ -1927,7 +1938,11 @@ bool c_FileMgr::handleFileUpload ( F(" Bytes out of ") + String(totalLen) + F(" bytes. FileLen: ") + GetSdFileSize(filename, false)); + delay(1000); + FeedWDT(); + expectedIndex = 0; + delay(1000); BuildFseqList(false); // DEBUG_V(String("Expected: ") + String(totalLen)); diff --git a/src/WebMgr.cpp b/src/WebMgr.cpp index 1c2dd644c..e3ae68a72 100644 --- a/src/WebMgr.cpp +++ b/src/WebMgr.cpp @@ -628,16 +628,16 @@ void c_WebMgr::CreateAdminInfoFile () JsonDocument AdminJsonDoc; JsonObject jsonAdmin = AdminJsonDoc[F ("admin")].to (); - jsonAdmin[CN_version] = VERSION; - jsonAdmin["built"] = BUILD_DATE; - jsonAdmin["realflashsize"] = String (ESP.getFlashChipSize ()); - jsonAdmin["BoardName"] = String(BOARD_NAME); + JsonWrite(jsonAdmin, CN_version, VERSION); + JsonWrite(jsonAdmin, "built", BUILD_DATE); + JsonWrite(jsonAdmin, "realflashsize", String (ESP.getFlashChipSize ())); + JsonWrite(jsonAdmin, "BoardName", String(BOARD_NAME)); #ifdef ARDUINO_ARCH_ESP8266 - jsonAdmin["arch"] = CN_ESP8266; - jsonAdmin["flashchipid"] = String (ESP.getChipId (), HEX); + JsonWrite(jsonAdmin, "arch", String(CN_ESP8266)); + JsonWrite(jsonAdmin, "flashchipid", String (ESP.getChipId (), HEX)); #elif defined (ARDUINO_ARCH_ESP32) - jsonAdmin["arch"] = CN_ESP32; - jsonAdmin["flashchipid"] = int64String (ESP.getEfuseMac (), HEX); + JsonWrite(jsonAdmin, "arch", String(CN_ESP32)); + JsonWrite(jsonAdmin, "flashchipid", int64String (ESP.getEfuseMac (), HEX)); #endif // write to json file @@ -701,6 +701,7 @@ size_t c_WebMgr::GetFseqFileListChunk(uint8_t *buffer, size_t maxlen, size_t ind { logcon(F("ERROR: Could not open List of Fseq files for reading")); response = FileMgr.GetDefaultFseqFileList(buffer, maxlen); + delay(500); FileMgr.BuildFseqList(); break; @@ -764,14 +765,14 @@ void c_WebMgr::ProcessXJRequest (AsyncWebServerRequest* client) JsonDocument WebJsonDoc; WebJsonDoc.clear (); - JsonObject status = WebJsonDoc[CN_status].to (); - JsonObject system = status[CN_system].to (); - - system[F ("freeheap")] = ESP.getFreeHeap (); - system[F ("uptime")] = millis (); - system[F ("currenttime")] = now (); - system[F ("SDinstalled")] = FileMgr.SdCardIsInstalled (); - system[F ("DiscardedRxData")] = DiscardedRxData; + JsonObject status = WebJsonDoc[(char*)CN_status].to (); + JsonObject system = status[(char*)CN_system].to (); + + JsonWrite(system, F ("freeheap"), ESP.getFreeHeap ()); + JsonWrite(system, F ("uptime"), millis ()); + JsonWrite(system, F ("currenttime"), now ()); + JsonWrite(system, F ("SDinstalled"), FileMgr.SdCardIsInstalled ()); + JsonWrite(system, F ("DiscardedRxData"), DiscardedRxData); // Ask WiFi Stats // DEBUG_V ("NetworkMgr.GetStatus"); diff --git a/src/input/InputAlexa.cpp b/src/input/InputAlexa.cpp index c86623d17..20989d4bf 100644 --- a/src/input/InputAlexa.cpp +++ b/src/input/InputAlexa.cpp @@ -100,12 +100,12 @@ void c_InputAlexa::GetStatus (JsonObject& /* jsonStatus */) } // GetStatus //----------------------------------------------------------------------------- -void c_InputAlexa::Process (bool StayDark) +void c_InputAlexa::Process () { // DEBUG_START; if (IsInputChannelActive) { - pEffectsEngine->Process (StayDark); + pEffectsEngine->Process (); } // DEBUG_END; @@ -167,15 +167,15 @@ void c_InputAlexa::onMessage(EspalexaDevice * pDevice) // DEBUG_V (String ("pDevice->getB: ") + String (pDevice->getB ())); JsonDocument JsonConfigDoc; - JsonObject JsonConfig = JsonConfigDoc[CN_config].to (); - - JsonConfig[CN_EffectSpeed] = 1; - JsonConfig[CN_EffectReverse] = false; - JsonConfig[CN_EffectMirror] = false; - JsonConfig[CN_EffectAllLeds] = true; - JsonConfig[CN_EffectBrightness] = map (pDevice->getValue (), 0, 255, 0, 100); - JsonConfig[CN_currenteffect] = F ("Solid"); - JsonConfig[CN_EffectColor] = HexColor; + JsonObject JsonConfig = JsonConfigDoc[(char*)CN_config].to (); + + JsonWrite(JsonConfig, CN_EffectSpeed, 1); + JsonWrite(JsonConfig, CN_EffectReverse, false); + JsonWrite(JsonConfig, CN_EffectMirror, false); + JsonWrite(JsonConfig, CN_EffectAllLeds, true); + JsonWrite(JsonConfig, CN_EffectBrightness, map (pDevice->getValue (), 0, 255, 0, 100)); + JsonWrite(JsonConfig, CN_currenteffect, F ("Solid")); + JsonWrite(JsonConfig, CN_EffectColor, HexColor); // DEBUG_V (String ("CN_EffectBrightness: ") + String (pDevice->getValue ())); // DEBUG_V (String ("getState: ") + String (pDevice->getState ())); diff --git a/src/input/InputArtnet.cpp b/src/input/InputArtnet.cpp index f72e3cbb3..5c65a8851 100644 --- a/src/input/InputArtnet.cpp +++ b/src/input/InputArtnet.cpp @@ -2,7 +2,7 @@ * ArtnetInput.cpp - Code to wrap ESPAsyncArtnet for input * * Project: ESPixelStick - An ESP8266 / ESP32 and Artnet based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -73,9 +73,9 @@ void c_InputArtnet::GetConfig (JsonObject & jsonConfig) { // DEBUG_START; - jsonConfig[CN_universe] = startUniverse; - jsonConfig[CN_universe_limit] = ChannelsPerUniverse; - jsonConfig[CN_universe_start] = FirstUniverseChannelOffset; + JsonWrite(jsonConfig, CN_universe, startUniverse); + JsonWrite(jsonConfig, CN_universe_limit, ChannelsPerUniverse); + JsonWrite(jsonConfig, CN_universe_start, FirstUniverseChannelOffset); // DEBUG_END; @@ -87,25 +87,25 @@ void c_InputArtnet::GetStatus (JsonObject & jsonStatus) // DEBUG_START; JsonObject ArtnetStatus = jsonStatus[F ("Artnet")].to (); - ArtnetStatus[CN_unifirst] = startUniverse; - ArtnetStatus[CN_unilast] = LastUniverse; - ArtnetStatus[CN_unichanlim] = ChannelsPerUniverse; + JsonWrite(ArtnetStatus, CN_unifirst, startUniverse); + JsonWrite(ArtnetStatus, CN_unilast, LastUniverse); + JsonWrite(ArtnetStatus, CN_unichanlim, ChannelsPerUniverse); // DEBUG_V (""); - ArtnetStatus[F ("lastData")] = lastData; - ArtnetStatus[CN_num_packets] = num_packets; - ArtnetStatus[CN_packet_errors] = packet_errors; - ArtnetStatus[CN_last_clientIP] = pArtnet->getRemoteIP().toString (); - ArtnetStatus[CN_PollCounter] = PollCounter; + JsonWrite(ArtnetStatus, F ("lastData"), lastData); + JsonWrite(ArtnetStatus, CN_num_packets, num_packets); + JsonWrite(ArtnetStatus, CN_packet_errors, packet_errors); + JsonWrite(ArtnetStatus, CN_last_clientIP, pArtnet->getRemoteIP().toString ()); + JsonWrite(ArtnetStatus, CN_PollCounter, PollCounter); - JsonArray ArtnetUniverseStatus = ArtnetStatus[CN_channels].to (); + JsonArray ArtnetUniverseStatus = ArtnetStatus[(char*)CN_channels].to (); for (auto & CurrentUniverse : UniverseArray) { JsonObject ArtnetCurrentUniverseStatus = ArtnetUniverseStatus.add (); - ArtnetCurrentUniverseStatus[CN_errors] = CurrentUniverse.SequenceErrorCounter; - ArtnetCurrentUniverseStatus[CN_num_packets] = CurrentUniverse.num_packets; + JsonWrite(ArtnetCurrentUniverseStatus, CN_errors, CurrentUniverse.SequenceErrorCounter); + JsonWrite(ArtnetCurrentUniverseStatus, CN_num_packets, CurrentUniverse.num_packets); } // DEBUG_END; @@ -120,8 +120,9 @@ void c_InputArtnet::onDmxFrame (uint16_t CurrentUniverseId, IPAddress remoteIP) { // DEBUG_START; - - if ((startUniverse <= CurrentUniverseId) && (LastUniverse >= CurrentUniverseId)) + if(!IsInputChannelActive) + {} + else if ((startUniverse <= CurrentUniverseId) && (LastUniverse >= CurrentUniverseId)) { // Universe offset and sequence tracking Universe_t & CurrentUniverse = UniverseArray[CurrentUniverseId - startUniverse]; diff --git a/src/input/InputDDP.cpp b/src/input/InputDDP.cpp index a0790a690..b6076146d 100644 --- a/src/input/InputDDP.cpp +++ b/src/input/InputDDP.cpp @@ -92,11 +92,11 @@ void c_InputDDP::GetStatus (JsonObject& jsonStatus) JsonObject ddpStatus = jsonStatus[F ("ddp")].to (); // DEBUG_V (""); - ddpStatus["packetsreceived"] = stats.packetsReceived; - ddpStatus["bytesreceived"] = float(stats.bytesReceived) / 1024.0; - ddpStatus[CN_errors] = stats.errors; - ddpStatus[CN_id] = InputChannelId; - ddpStatus["lastError"] = lastError; + JsonWrite(ddpStatus, F("packetsreceived"), stats.packetsReceived); + JsonWrite(ddpStatus, F("bytesreceived"), float(stats.bytesReceived) / 1024.0); + JsonWrite(ddpStatus, CN_errors, stats.errors); + JsonWrite(ddpStatus, CN_id, InputChannelId); + JsonWrite(ddpStatus, F("lastError"), lastError); // DEBUG_END; @@ -192,13 +192,13 @@ void c_InputDDP::ProcessReceivedUdpPacket(AsyncUDPPacket ReceivedPacket) } // ProcessReceivedUdpPacket //----------------------------------------------------------------------------- -void c_InputDDP::Process (bool StayDark) +void c_InputDDP::Process () { // DEBUG_START; do // once { - if(!IsInputChannelActive || StayDark) + if(!IsInputChannelActive) { break; } @@ -323,21 +323,21 @@ void c_InputDDP::ProcessReceivedQuery () // DEBUG_V ("DDP_ID_CONFIG query"); JsonDocument JsonConfigDoc; - JsonObject JsonConfig = JsonConfigDoc[CN_config].to (); + JsonObject JsonConfig = JsonConfigDoc[(char*)CN_config].to (); String hostname; NetworkMgr.GetHostname (hostname); - JsonConfig[CN_hostname] = hostname; - JsonConfig[CN_id] = config.id; - JsonConfig[CN_ip] = NetworkMgr.GetlocalIP ().toString (); - JsonConfig[CN_version] = VERSION; - JsonConfig["hardwareType"] = FPP_VARIANT_NAME; - JsonConfig[CN_type] = FPP_TYPE_ID; - JsonConfig[CN_num_chan] = InputDataBufferSize; + JsonWrite(JsonConfig, CN_hostname, hostname); + JsonWrite(JsonConfig, CN_id, config.id); + JsonWrite(JsonConfig, CN_ip, NetworkMgr.GetlocalIP ().toString ()); + JsonWrite(JsonConfig, CN_version, VERSION); + JsonWrite(JsonConfig, F("hardwareType"), FPP_VARIANT_NAME); + JsonWrite(JsonConfig, CN_type, FPP_TYPE_ID); + JsonWrite(JsonConfig, CN_num_chan, InputDataBufferSize); uint16_t PixelPortCount; uint16_t SerialPortCount; OutputMgr.GetPortCounts (PixelPortCount, SerialPortCount); - JsonConfig["NumPixelPort"] = PixelPortCount; - JsonConfig["NumSerialPort"] = SerialPortCount; + JsonWrite(JsonConfig, F("NumPixelPort"), PixelPortCount); + JsonWrite(JsonConfig, F("NumSerialPort"), SerialPortCount); String JsonResponse; serializeJson (JsonConfigDoc, JsonResponse); diff --git a/src/input/InputDisabled.cpp b/src/input/InputDisabled.cpp index 80d7c0c13..c6fb39932 100644 --- a/src/input/InputDisabled.cpp +++ b/src/input/InputDisabled.cpp @@ -58,7 +58,7 @@ void c_InputDisabled::GetStatus (JsonObject & jsonStatus) // DEBUG_START; JsonObject Status = jsonStatus[F ("disabled")].to (); - Status[CN_id] = InputChannelId; + JsonWrite(Status, CN_id, InputChannelId); // DEBUG_END; @@ -92,7 +92,7 @@ void c_InputDisabled::GetConfig(ArduinoJson::JsonObject & jsonConfig) } // GetConfig //---------------------------------------------------------------------------- -void c_InputDisabled::Process(bool /* StayDark */) +void c_InputDisabled::Process() { // DEBUG_START; diff --git a/src/input/InputE131.cpp b/src/input/InputE131.cpp index d4d22abfb..f44c153cf 100644 --- a/src/input/InputE131.cpp +++ b/src/input/InputE131.cpp @@ -78,10 +78,10 @@ void c_InputE131::GetConfig (JsonObject & jsonConfig) { // DEBUG_START; - jsonConfig[CN_universe] = startUniverse; - jsonConfig[CN_universe_limit] = ChannelsPerUniverse; - jsonConfig[CN_universe_start] = FirstUniverseChannelOffset; - jsonConfig[CN_port] = PortId; + JsonWrite(jsonConfig, CN_universe, startUniverse); + JsonWrite(jsonConfig, CN_universe_limit, ChannelsPerUniverse); + JsonWrite(jsonConfig, CN_universe_start, FirstUniverseChannelOffset); + JsonWrite(jsonConfig, CN_port, PortId); // DEBUG_END; @@ -92,34 +92,34 @@ void c_InputE131::GetStatus (JsonObject & jsonStatus) { // DEBUG_START; - JsonObject e131Status = jsonStatus[F ("e131")].to (); - e131Status[CN_id] = InputChannelId; - e131Status[CN_unifirst] = startUniverse; - e131Status[CN_unilast ] = LastUniverse; - e131Status[CN_unichanlim] = ChannelsPerUniverse; + JsonObject e131Status = jsonStatus[(char*)F ("e131")].to (); + JsonWrite(e131Status, CN_id, InputChannelId); + JsonWrite(e131Status, CN_unifirst, startUniverse); + JsonWrite(e131Status, CN_unilast, LastUniverse); + JsonWrite(e131Status, CN_unichanlim, ChannelsPerUniverse); - e131Status[CN_num_packets] = e131->stats.num_packets; - e131Status[CN_last_clientIP] = uint32_t(e131->stats.last_clientIP); + JsonWrite(e131Status, CN_num_packets, e131->stats.num_packets); + JsonWrite(e131Status, CN_last_clientIP, uint32_t(e131->stats.last_clientIP)); // DEBUG_V (""); - JsonArray e131UniverseStatus = e131Status[CN_channels].to (); + JsonArray e131UniverseStatus = e131Status[(char*)CN_channels].to (); uint32_t TotalErrors = 0; // e131->stats.packet_errors; for (auto & CurrentUniverse : UniverseArray) { JsonObject e131CurrentUniverseStatus = e131UniverseStatus.add (); - e131CurrentUniverseStatus[CN_errors] = CurrentUniverse.SequenceErrorCounter; + JsonWrite(e131CurrentUniverseStatus, CN_errors, CurrentUniverse.SequenceErrorCounter); TotalErrors += CurrentUniverse.SequenceErrorCounter; } - e131Status[CN_packet_errors] = TotalErrors; + JsonWrite(e131Status, CN_packet_errors, TotalErrors); // DEBUG_END; } // GetStatus //----------------------------------------------------------------------------- -void c_InputE131::Process (bool /* StayDark */) +void c_InputE131::Process () { // DEBUG_START; @@ -137,7 +137,7 @@ void c_InputE131::ProcessIncomingE131Data (e131_packet_t * packet) do // once { - if (0 == InputDataBufferSize) + if ((0 == InputDataBufferSize) || !IsInputChannelActive) { // no place to put any data break; diff --git a/src/input/InputEffectEngine.cpp b/src/input/InputEffectEngine.cpp index 7d12b7873..ca795bda5 100644 --- a/src/input/InputEffectEngine.cpp +++ b/src/input/InputEffectEngine.cpp @@ -2,7 +2,7 @@ * InputEffectEngine.cpp - Code to wrap ESPAsyncE131 for input * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2021, 2022 Shelby Merrick +* Copyright (c) 2021, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -76,42 +76,6 @@ static std::vector MarqueueGroupTable = {5, {255, 255, 255}, 100, 0}, }; // MarqueueGroupTable -#ifdef ARDUINO_ARCH_ESP32 -static TaskHandle_t PollTaskHandle = NULL; -static c_InputEffectEngine *pEffectsInstance = nullptr; -//---------------------------------------------------------------------------- -void EffectsTask (void *arg) -{ - uint32_t PollStartTime = millis(); - uint32_t PollEndTime = PollStartTime; - uint32_t PollTime = pdMS_TO_TICKS(25); - const uint32_t MinPollTimeMs = 25; - - while(1) - { - uint32_t DeltaTime = PollEndTime - PollStartTime; - - if (DeltaTime < MinPollTimeMs) - { - PollTime = pdMS_TO_TICKS(MinPollTimeMs - DeltaTime); - } - else - { - // handle time wrap and long frames - PollTime = pdMS_TO_TICKS(1); - } - vTaskDelay(PollTime); - - PollStartTime = millis(); - - pEffectsInstance->Poll(); - - // record the loop end time - PollEndTime = millis(); - } -} // EffectsTask -#endif // def ARDUINO_ARCH_ESP32 - //----------------------------------------------------------------------------- c_InputEffectEngine::c_InputEffectEngine (c_InputMgr::e_InputChannelIds NewInputChannelId, c_InputMgr::e_InputType NewChannelType, @@ -149,14 +113,6 @@ c_InputEffectEngine::c_InputEffectEngine () : //----------------------------------------------------------------------------- c_InputEffectEngine::~c_InputEffectEngine () { -#ifdef ARDUINO_ARCH_ESP32 - if(PollTaskHandle) - { - logcon("Stop EffectsTask"); - vTaskDelete(PollTaskHandle); - PollTaskHandle = NULL; - } -#endif // def ARDUINO_ARCH_ESP32 } // ~c_InputEffectEngine @@ -185,59 +141,59 @@ void c_InputEffectEngine::GetConfig (JsonObject& jsonConfig) ESP_ERROR_CHECK(saferRgbToHtmlColorString(HexColor, EffectColor.r, EffectColor.g, EffectColor.b)); // DEBUG_V (""); - jsonConfig[CN_currenteffect] = ActiveEffect->name; - jsonConfig[CN_EffectSpeed] = EffectSpeed; - jsonConfig[CN_EffectReverse] = EffectReverse; - jsonConfig[CN_EffectMirror] = EffectMirror; - jsonConfig[CN_EffectAllLeds] = EffectAllLeds; - jsonConfig[CN_EffectBrightness] = uint32_t(EffectBrightness * 100.0); - jsonConfig[CN_EffectWhiteChannel] = EffectWhiteChannel; - jsonConfig[CN_EffectColor] = HexColor; - jsonConfig[CN_pixel_count] = effectMarqueePixelAdvanceCount; - - jsonConfig["FlashEnable"] = FlashInfo.Enable; - jsonConfig["FlashMinInt"] = FlashInfo.MinIntensity; - jsonConfig["FlashMaxInt"] = FlashInfo.MaxIntensity; - jsonConfig["FlashMinDelay"] = FlashInfo.MinDelayMS; - jsonConfig["FlashMaxDelay"] = FlashInfo.MaxDelayMS; - jsonConfig["FlashMinDur"] = FlashInfo.MinDurationMS; - jsonConfig["FlashMaxDur"] = FlashInfo.MaxDurationMS; - jsonConfig["TransCount"] = TransitionInfo.StepsToTarget; - jsonConfig["TransDelay"] = TransitionInfo.TimeAtTargetMs; + JsonWrite(jsonConfig, CN_currenteffect, ActiveEffect->name); + JsonWrite(jsonConfig, CN_EffectSpeed, EffectSpeed); + JsonWrite(jsonConfig, CN_EffectReverse, EffectReverse); + JsonWrite(jsonConfig, CN_EffectMirror, EffectMirror); + JsonWrite(jsonConfig, CN_EffectAllLeds, EffectAllLeds); + JsonWrite(jsonConfig, CN_EffectBrightness, uint32_t(EffectBrightness * 100.0)); + JsonWrite(jsonConfig, CN_EffectWhiteChannel, EffectWhiteChannel); + JsonWrite(jsonConfig, CN_EffectColor, HexColor); + JsonWrite(jsonConfig, CN_pixel_count, effectMarqueePixelAdvanceCount); + + JsonWrite(jsonConfig, "FlashEnable", FlashInfo.Enable); + JsonWrite(jsonConfig, "FlashMinInt", FlashInfo.MinIntensity); + JsonWrite(jsonConfig, "FlashMaxInt", FlashInfo.MaxIntensity); + JsonWrite(jsonConfig, "FlashMinDelay", FlashInfo.MinDelayMS); + JsonWrite(jsonConfig, "FlashMaxDelay", FlashInfo.MaxDelayMS); + JsonWrite(jsonConfig, "FlashMinDur", FlashInfo.MinDurationMS); + JsonWrite(jsonConfig, "FlashMaxDur", FlashInfo.MaxDurationMS); + JsonWrite(jsonConfig, "TransCount", TransitionInfo.StepsToTarget); + JsonWrite(jsonConfig, "TransDelay", TransitionInfo.TimeAtTargetMs); // DEBUG_V (""); - JsonArray EffectsArray = jsonConfig[CN_effects].to (); + JsonArray EffectsArray = jsonConfig[(char*)CN_effects].to (); // DEBUG_V (""); for (EffectDescriptor_t currentEffect : ListOfEffects) { // DEBUG_V (""); JsonObject currentJsonEntry = EffectsArray.add (); - currentJsonEntry[CN_name] = currentEffect.name; + JsonWrite(currentJsonEntry, CN_name, currentEffect.name); } - JsonArray TransitionsArray = jsonConfig[CN_transitions].to (); + JsonArray TransitionsArray = jsonConfig[(char*)CN_transitions].to (); for (auto currentTransition : TransitionColorTable) { // DEBUG_V (""); JsonObject currentJsonEntry = TransitionsArray.add (); - currentJsonEntry["r"] = currentTransition.r; - currentJsonEntry["g"] = currentTransition.g; - currentJsonEntry["b"] = currentTransition.b; + JsonWrite(currentJsonEntry, CN_r, currentTransition.r); + JsonWrite(currentJsonEntry, CN_g, currentTransition.g); + JsonWrite(currentJsonEntry, CN_b, currentTransition.b); } - JsonArray MarqueeGroupArray = jsonConfig[CN_MarqueeGroups].to (); + JsonArray MarqueeGroupArray = jsonConfig[(char*)CN_MarqueeGroups].to (); for(auto CurrentMarqueeGroup : MarqueueGroupTable) { JsonObject currentJsonEntry = MarqueeGroupArray.add (); - JsonObject currentJsonEntryColor = currentJsonEntry[CN_color].to (); - currentJsonEntryColor["r"] = CurrentMarqueeGroup.Color.r; - currentJsonEntryColor["g"] = CurrentMarqueeGroup.Color.g; - currentJsonEntryColor["b"] = CurrentMarqueeGroup.Color.b; - currentJsonEntry[CN_brightness] = CurrentMarqueeGroup.StartingIntensity; - currentJsonEntry[CN_pixel_count] = CurrentMarqueeGroup.NumPixelsInGroup; - currentJsonEntry[CN_brightnessEnd] = CurrentMarqueeGroup.EndingIntensity; + JsonObject currentJsonEntryColor = currentJsonEntry[(char*)CN_color].to (); + JsonWrite(currentJsonEntryColor, CN_r, CurrentMarqueeGroup.Color.r); + JsonWrite(currentJsonEntryColor, CN_g, CurrentMarqueeGroup.Color.g); + JsonWrite(currentJsonEntryColor, CN_b, CurrentMarqueeGroup.Color.b); + JsonWrite(currentJsonEntry, CN_brightness, CurrentMarqueeGroup.StartingIntensity); + JsonWrite(currentJsonEntry, CN_pixel_count, CurrentMarqueeGroup.NumPixelsInGroup); + JsonWrite(currentJsonEntry, CN_brightnessEnd, CurrentMarqueeGroup.EndingIntensity); } // DEBUG_END; @@ -248,7 +204,7 @@ void c_InputEffectEngine::GetConfig (JsonObject& jsonConfig) void c_InputEffectEngine::GetMqttEffectList (JsonObject& jsonConfig) { // DEBUG_START; - JsonArray EffectsArray = jsonConfig[CN_effect_list].to (); + JsonArray EffectsArray = jsonConfig[(char*)CN_effect_list].to (); for (EffectDescriptor_t currentEffect : ListOfEffects) { @@ -281,9 +237,9 @@ void c_InputEffectEngine::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - JsonObject Status = jsonStatus[F ("effects")].to (); - Status[CN_currenteffect] = ActiveEffect->name; - Status[CN_id] = InputChannelId; + JsonObject Status = jsonStatus[(char*)CN_effects].to (); + JsonWrite(Status, CN_currenteffect, ActiveEffect->name); + JsonWrite(Status, CN_id, InputChannelId); // DEBUG_END; @@ -373,13 +329,12 @@ void c_InputEffectEngine::PollFlash () } // PollFlash //----------------------------------------------------------------------------- -void c_InputEffectEngine::Process (bool _StayDark) +void c_InputEffectEngine::Process () { // DEBUG_START; - Disabled = _StayDark; // DEBUG_V (String ("HasBeenInitialized: ") + HasBeenInitialized); // DEBUG_V (String ("PixelCount: ") + PixelCount); -#ifndef ARDUINO_ARCH_ESP32 + do // once { if (!HasBeenInitialized) @@ -388,7 +343,7 @@ void c_InputEffectEngine::Process (bool _StayDark) } // DEBUG_V ("Init OK"); - if ((0 == PixelCount) || (StayDark)) + if (0 == PixelCount) { break; } @@ -417,16 +372,6 @@ void c_InputEffectEngine::Process (bool _StayDark) } while (false); // DEBUG_END; -#else - if(!PollTaskHandle) - { - logcon("Start EffectsTask"); - pEffectsInstance = this; - xTaskCreatePinnedToCore(EffectsTask, "EffectsTask", 4096, NULL, EFFECTS_TASK_PRIORITY, &PollTaskHandle, 1); - vTaskPrioritySet(PollTaskHandle, EFFECTS_TASK_PRIORITY); - // DEBUG_V("End EffectsTask"); - } -#endif // ndef ARDUINO_ARCH_ESP32 } // process @@ -591,7 +536,7 @@ bool c_InputEffectEngine::SetConfig (ArduinoJson::JsonObject& jsonConfig) FlashInfo.MinIntensity = FlashInfo.MaxIntensity; } - JsonArray TransitionsArray = jsonConfig[CN_transitions]; + JsonArray TransitionsArray = jsonConfig[(char*)CN_transitions]; if(TransitionsArray) { TransitionColorTable.clear(); @@ -612,7 +557,7 @@ bool c_InputEffectEngine::SetConfig (ArduinoJson::JsonObject& jsonConfig) } } - JsonArray MarqueeGroupArray = jsonConfig[CN_MarqueeGroups]; + JsonArray MarqueeGroupArray = jsonConfig[(char*)CN_MarqueeGroups]; if(MarqueeGroupArray) { MarqueueGroupTable.clear(); @@ -622,7 +567,7 @@ bool c_InputEffectEngine::SetConfig (ArduinoJson::JsonObject& jsonConfig) MarqueeGroup NewGroup; JsonObject currentMarqueeGroup = _MarqueeGroup.as(); // DEBUG_V (""); - JsonObject GroupColor = currentMarqueeGroup[CN_color]; + JsonObject GroupColor = currentMarqueeGroup[(char*)CN_color]; setFromJSON (NewGroup.Color.r, GroupColor, "r"); setFromJSON (NewGroup.Color.g, GroupColor, "g"); setFromJSON (NewGroup.Color.b, GroupColor, "b"); diff --git a/src/input/InputFPPRemote.cpp b/src/input/InputFPPRemote.cpp index 2ae889ca4..f8a6bf8c2 100644 --- a/src/input/InputFPPRemote.cpp +++ b/src/input/InputFPPRemote.cpp @@ -24,45 +24,6 @@ #include "input/InputFPPRemotePlayList.hpp" #include -#if defined ARDUINO_ARCH_ESP32 -# include - -static TaskHandle_t PollTaskHandle = NULL; -static c_InputFPPRemote *pFppRemoteInstance = nullptr; -//---------------------------------------------------------------------------- -void FppRemoteTask (void *arg) -{ - uint32_t PollStartTime = millis(); - uint32_t PollEndTime = PollStartTime; - uint32_t PollTime = pdMS_TO_TICKS(25); - const uint32_t MinPollTimeMs = 25; - - while(1) - { - uint32_t DeltaTime = PollEndTime - PollStartTime; - - if (DeltaTime < MinPollTimeMs) - { - PollTime = pdMS_TO_TICKS(MinPollTimeMs - DeltaTime); - } - else - { - // handle time wrap and long frames - PollTime = pdMS_TO_TICKS(1); - } - vTaskDelay(PollTime); - FeedWDT(); - - PollStartTime = millis(); - - pFppRemoteInstance->TaskProcess(); - FeedWDT(); - - // record the loop end time - PollEndTime = millis(); - } -} // FppRemoteTask -#endif // def ARDUINO_ARCH_ESP32 //----------------------------------------------------------------------------- c_InputFPPRemote::c_InputFPPRemote (c_InputMgr::e_InputChannelIds NewInputChannelId, @@ -82,18 +43,10 @@ c_InputFPPRemote::~c_InputFPPRemote () { if (HasBeenInitialized) { + // DEBUG_V(); StopPlaying (); } -#ifdef ARDUINO_ARCH_ESP32 - if(PollTaskHandle) - { - logcon("Stop FPP Remote Task"); - vTaskDelete(PollTaskHandle); - PollTaskHandle = NULL; - } -#endif // def ARDUINO_ARCH_ESP32 - } // ~c_InputFPPRemote //----------------------------------------------------------------------------- @@ -114,15 +67,15 @@ void c_InputFPPRemote::GetConfig (JsonObject& jsonConfig) if (PlayingFile ()) { - jsonConfig[JSON_NAME_FILE_TO_PLAY] = pInputFPPRemotePlayItem->GetFileName (); + JsonWrite(jsonConfig, JSON_NAME_FILE_TO_PLAY, pInputFPPRemotePlayItem->GetFileName ()); } else { - jsonConfig[JSON_NAME_FILE_TO_PLAY] = No_LocalFileToPlay; + JsonWrite(jsonConfig, JSON_NAME_FILE_TO_PLAY, No_LocalFileToPlay); } - jsonConfig[CN_SyncOffset] = SyncOffsetMS; - jsonConfig[CN_SendFppSync] = SendFppSync; - jsonConfig[CN_blankOnStop] = FPPDiscovery.GetBlankOnStop(); + JsonWrite(jsonConfig, CN_SyncOffset, SyncOffsetMS); + JsonWrite(jsonConfig, CN_SendFppSync, SendFppSync); + JsonWrite(jsonConfig, CN_blankOnStop, FPPDiscovery.GetBlankOnStop()); // DEBUG_END; @@ -134,8 +87,8 @@ void c_InputFPPRemote::GetStatus (JsonObject& jsonStatus) // DEBUG_START; JsonObject LocalPlayerStatus = jsonStatus[F ("Player")].to (); - LocalPlayerStatus[CN_id] = InputChannelId; - LocalPlayerStatus[CN_active] = PlayingFile (); + JsonWrite(LocalPlayerStatus, CN_id, InputChannelId); + JsonWrite(LocalPlayerStatus, CN_active, PlayingFile ()); if (PlayingRemoteFile ()) { @@ -234,34 +187,13 @@ void c_InputFPPRemote::PlayNextFile () } // PlayNextFile //----------------------------------------------------------------------------- -void c_InputFPPRemote::Process (bool StayDark) +void c_InputFPPRemote::Process () { // DEBUG_START; - Disabled = StayDark; -#ifndef ARDUINO_ARCH_ESP32 - TaskProcess(); -#else - if(!PollTaskHandle) - { - logcon("Start FPP Remote Task"); - pFppRemoteInstance = this; - xTaskCreatePinnedToCore(FppRemoteTask, "FppRemoteTask", 4096, NULL, FPP_REMOTE_TASK_PRIORITY, &PollTaskHandle, 1); - vTaskPrioritySet(PollTaskHandle, FPP_REMOTE_TASK_PRIORITY); - // DEBUG_V("End FppRemoteTask"); - } -#endif // ndef ARDUINO_ARCH_ESP32 - // DEBUG_END; - -} // process -//----------------------------------------------------------------------------- -void c_InputFPPRemote::TaskProcess () -{ - // DEBUG_START; - if (!IsInputChannelActive || StayDark || Disabled) + if (!IsInputChannelActive) { // DEBUG_V ("dont do anything if the channel is not active"); - StopPlaying (); } else if (PlayingRemoteFile ()) { @@ -281,16 +213,16 @@ void c_InputFPPRemote::TaskProcess () } // DEBUG_END; -} // TaskProcess +} // process //----------------------------------------------------------------------------- bool c_InputFPPRemote::Poll () { // DEBUG_START; bool Response = false; - if(pInputFPPRemotePlayItem) + if(pInputFPPRemotePlayItem && IsInputChannelActive) { - Response = pInputFPPRemotePlayItem->Poll (Disabled); + Response = pInputFPPRemotePlayItem->Poll (); } // DEBUG_END; @@ -305,9 +237,6 @@ void c_InputFPPRemote::ProcessButtonActions(c_ExternalInput::InputValue_t value) if(c_ExternalInput::InputValue_t::longOn == value) { - // DEBUG_V("flip the dark flag"); - StayDark = !StayDark; - // DEBUG_V(String("StayDark: ") + String(StayDark)); } else if(c_ExternalInput::InputValue_t::shortOn == value) { @@ -358,10 +287,26 @@ bool c_InputFPPRemote::SetConfig (JsonObject& jsonConfig) return true; } // SetConfig +//----------------------------------------------------------------------------- +void c_InputFPPRemote::SetOperationalState (bool ActiveFlag) +{ + // DEBUG_START; + + if(pInputFPPRemotePlayItem) + { + pInputFPPRemotePlayItem->SetOperationalState (ActiveFlag); + } + + FPPDiscovery.SetOperationalState(ActiveFlag); + + // DEBUG_END; +} // SetOperationalState + //----------------------------------------------------------------------------- void c_InputFPPRemote::StopPlaying () { // DEBUG_START; + do // once { if (!PlayingFile ()) @@ -370,7 +315,7 @@ void c_InputFPPRemote::StopPlaying () break; } - // handle re entrancy + // handle reentrancy if(Stopping) { // DEBUG_V("already in the process of stopping"); @@ -379,16 +324,19 @@ void c_InputFPPRemote::StopPlaying () Stopping = true; // DEBUG_V ("Disable FPP Discovery"); - FPPDiscovery.Disable (); + // FPPDiscovery.Disable (); FPPDiscovery.ForgetInputFPPRemotePlayFile (); if(PlayingFile()) { + // DEBUG_V(); + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); pInputFPPRemotePlayItem->Stop (); + // DEBUG_V(); while (!pInputFPPRemotePlayItem->IsIdle ()) { - pInputFPPRemotePlayItem->Poll (Disabled); + pInputFPPRemotePlayItem->Poll (); // DEBUG_V(); pInputFPPRemotePlayItem->Stop (); } @@ -396,6 +344,7 @@ void c_InputFPPRemote::StopPlaying () // DEBUG_V("Delete current playing file"); delete pInputFPPRemotePlayItem; pInputFPPRemotePlayItem = nullptr; + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); } Stopping = false; @@ -413,6 +362,11 @@ void c_InputFPPRemote::StartPlaying (String& FileName) do // once { + if(!IsInputChannelActive) + { + break; + } + // DEBUG_V (String ("FileName: '") + FileName + "'"); if ((FileName.isEmpty ()) || (FileName.equals("null"))) @@ -444,7 +398,7 @@ void c_InputFPPRemote::StartPlayingLocalFile (String& FileName) do // once { - // make sure we are stopped (clears pInputFPPRemotePlayItem) + // DEBUG_V("make sure we are stopped (clears pInputFPPRemotePlayItem)"); StopPlaying(); // DEBUG_V ("Start A New File"); @@ -452,13 +406,16 @@ void c_InputFPPRemote::StartPlayingLocalFile (String& FileName) String Last_pl_Text = FileName.substring(Last_dot_pl_Position); if (String(CN_Dotpl) == Last_pl_Text) { - // DEBUG_V ("Start Playlist"); if(pInputFPPRemotePlayItem) { + // DEBUG_V ("Delete existing play item"); delete pInputFPPRemotePlayItem; pInputFPPRemotePlayItem = nullptr; + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); } + // DEBUG_V ("Start a new Local File"); pInputFPPRemotePlayItem = new c_InputFPPRemotePlayList (GetInputChannelId ()); + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); StatusType = F ("PlayList"); } else @@ -475,12 +432,15 @@ void c_InputFPPRemote::StartPlayingLocalFile (String& FileName) if(pInputFPPRemotePlayItem) { + // DEBUG_V ("Delete existing item"); delete pInputFPPRemotePlayItem; pInputFPPRemotePlayItem = nullptr; + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); } // DEBUG_V ("Start Local FSEQ file player"); pInputFPPRemotePlayItem = new c_InputFPPRemotePlayFile (GetInputChannelId ()); StatusType = CN_File; + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); } // DEBUG_V (String ("FileName: '") + FileName + "'"); @@ -509,15 +469,20 @@ void c_InputFPPRemote::StartPlayingRemoteFile (String& FileName) break; } + // DEBUG_V(); StopPlaying (); // DEBUG_V ("Instantiate an FSEQ file player"); if(pInputFPPRemotePlayItem) { + // DEBUG_V ("Delete existing play item"); delete pInputFPPRemotePlayItem; pInputFPPRemotePlayItem = nullptr; + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); } + // DEBUG_V ("Start Local FSEQ file player"); pInputFPPRemotePlayItem = new c_InputFPPRemotePlayFile (GetInputChannelId ()); + // DEBUG_V(String("pInputFPPRemotePlayItem: 0x") + String(uint32_t(pInputFPPRemotePlayItem), HEX)); pInputFPPRemotePlayItem->SetSyncOffsetMS (SyncOffsetMS); pInputFPPRemotePlayItem->SetSendFppSync (SendFppSync); StatusType = CN_File; @@ -543,25 +508,7 @@ void c_InputFPPRemote::validateConfiguration () //----------------------------------------------------------------------------- bool c_InputFPPRemote::PlayingFile () { - // DEBUG_START; - - bool response = false; - - do // once - { - // DEBUG_V(String("pInputFPPRemotePlayItem: ") = String(uint32_t(pInputFPPRemotePlayItem), HEX)); - if (nullptr == pInputFPPRemotePlayItem) - { - // DEBUG_V("Stop processing if the play item pointer is null"); - break; - } - - response = true; - } while (false); - - // DEBUG_END; - return response; - + return (nullptr != pInputFPPRemotePlayItem); } // PlayingFile //----------------------------------------------------------------------------- diff --git a/src/input/InputFPPRemotePlayEffect.cpp b/src/input/InputFPPRemotePlayEffect.cpp index 47e199bd1..44cd67cb7 100644 --- a/src/input/InputFPPRemotePlayEffect.cpp +++ b/src/input/InputFPPRemotePlayEffect.cpp @@ -27,13 +27,10 @@ c_InputFPPRemotePlayEffect::c_InputFPPRemotePlayEffect (c_InputMgr::e_InputChann { // DEBUG_START; - // Tell input manager to not put any data into the input buffer - InputMgr.SetOperationalState (false); - fsm_PlayEffect_state_Idle_imp.Init (this); EffectsEngine.Begin (); - EffectsEngine.SetOperationalState (false); + EffectsEngine.SetOperationalState (!InputIsPaused()); // DEBUG_END; } // c_InputFPPRemotePlayEffect @@ -44,7 +41,6 @@ c_InputFPPRemotePlayEffect::~c_InputFPPRemotePlayEffect () // DEBUG_START; // allow the other input channels to run - InputMgr.SetOperationalState (true); EffectsEngine.SetOperationalState (false); // DEBUG_END; @@ -56,7 +52,10 @@ void c_InputFPPRemotePlayEffect::Start (String & FileName, float duration, uint3 { // DEBUG_START; - pCurrentFsmState->Start (FileName, duration); + if(!InputIsPaused()) + { + pCurrentFsmState->Start (FileName, duration); + } // DEBUG_END; } // Start @@ -66,7 +65,10 @@ void c_InputFPPRemotePlayEffect::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; } // Stop @@ -76,19 +78,29 @@ void c_InputFPPRemotePlayEffect::Sync (String& FileName, float SecondsElapsed) { // DEBUG_START; - pCurrentFsmState->Sync (SecondsElapsed); + if(!InputIsPaused()) + { + pCurrentFsmState->Sync (SecondsElapsed); + } // DEBUG_END; } // Sync //----------------------------------------------------------------------------- -bool c_InputFPPRemotePlayEffect::Poll (bool StayDark) +bool c_InputFPPRemotePlayEffect::Poll () { - // DEBUG_START; + /// DEBUG_START; - return pCurrentFsmState->Poll (StayDark); + bool Response = false; - // DEBUG_END; + if(!InputIsPaused()) + { + // Show that we have received a poll + Response = pCurrentFsmState->Poll (); + } + + /// DEBUG_END; + return Response; } // Poll diff --git a/src/input/InputFPPRemotePlayEffectFsm.cpp b/src/input/InputFPPRemotePlayEffectFsm.cpp index a0ede7350..6010131d2 100644 --- a/src/input/InputFPPRemotePlayEffectFsm.cpp +++ b/src/input/InputFPPRemotePlayEffectFsm.cpp @@ -23,7 +23,7 @@ #include "utility/SaferStringConversion.hpp" //----------------------------------------------------------------------------- -bool fsm_PlayEffect_state_Idle::Poll (bool /* StayDark */) +bool fsm_PlayEffect_state_Idle::Poll () { // DEBUG_START; @@ -109,7 +109,7 @@ void fsm_PlayEffect_state_Idle::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - jsonStatus[CN_TimeRemaining] = F ("00:00"); + JsonWrite(jsonStatus, CN_TimeRemaining, F ("00:00")); // DEBUG_END; @@ -118,12 +118,12 @@ void fsm_PlayEffect_state_Idle::GetStatus (JsonObject& jsonStatus) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayEffect_state_PlayingEffect::Poll (bool StayDark) +bool fsm_PlayEffect_state_PlayingEffect::Poll () { // DEBUG_START; p_InputFPPRemotePlayEffect->EffectsEngine.SetBufferInfo (OutputMgr.GetBufferUsedSize()); - p_InputFPPRemotePlayEffect->EffectsEngine.Process (StayDark); + p_InputFPPRemotePlayEffect->EffectsEngine.Process (); if (p_InputFPPRemotePlayEffect->PlayEffectTimer.IsExpired()) { @@ -198,7 +198,7 @@ void fsm_PlayEffect_state_PlayingEffect::GetStatus (JsonObject& jsonStatus) char buf[12]; ESP_ERROR_CHECK(saferSecondsToFormattedMinutesAndSecondsString(buf, (uint32_t)SecondsRemaining)); - jsonStatus[CN_TimeRemaining] = buf; + JsonWrite(jsonStatus, CN_TimeRemaining, buf); p_InputFPPRemotePlayEffect->EffectsEngine.GetStatus (jsonStatus); diff --git a/src/input/InputFPPRemotePlayFile.cpp b/src/input/InputFPPRemotePlayFile.cpp index 834563f0a..30a55bb96 100644 --- a/src/input/InputFPPRemotePlayFile.cpp +++ b/src/input/InputFPPRemotePlayFile.cpp @@ -23,42 +23,6 @@ #include "service/fseq.h" #include "utility/SaferStringConversion.hpp" -//----------------------------------------------------------------------------- -static void TimerPollHandler (void * p) -{ -#ifdef ARDUINO_ARCH_ESP32 - TaskHandle_t Handle = reinterpret_cast (p)->GetTaskHandle (); - if (Handle) - { - vTaskResume (Handle); - } -#else - reinterpret_cast(p)->TimerPoll (); -#endif // def ARDUINO_ARCH_ESP32 - -} // TimerPollHandler - -#ifdef ARDUINO_ARCH_ESP32 -//---------------------------------------------------------------------------- -static void TimerPollHandlerTask (void* pvParameters) -{ - // DEBUG_START; // Need extra stack space to run this - c_InputFPPRemotePlayFile* InputFpp = reinterpret_cast (pvParameters); - - do - { - // we start suspended - vTaskSuspend (NULL); //Suspend Own Task - InputFpp->TimerPollInProgress = true; - // DEBUG_V (""); - InputFpp->TimerPoll (); - InputFpp->TimerPollInProgress = false; - } while (true); - // DEBUG_END; - -} // TimerPollHandlerTask -#endif // def ARDUINO_ARCH_ESP32 - //----------------------------------------------------------------------------- c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelIds InputChannelId) : c_InputFPPRemotePlayItem (InputChannelId) @@ -67,13 +31,6 @@ c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelId fsm_PlayFile_state_Idle_imp.Init (this); - LastIsrTimeStampMS = millis (); - MsTicker.attach_ms (uint32_t (FPP_TICKER_PERIOD_MS), &TimerPollHandler, (void*)this); // Add ISR Function - -#ifdef ARDUINO_ARCH_ESP32 - xTaskCreate (TimerPollHandlerTask, "FPPTask", TimerPollHandlerTaskStack, this, ESP_TASK_PRIO_MIN + 8, &TimerPollTaskHandle); -#endif // def ARDUINO_ARCH_ESP32 - // DEBUG_END; } // c_InputFPPRemotePlayFile @@ -81,25 +38,13 @@ c_InputFPPRemotePlayFile::c_InputFPPRemotePlayFile (c_InputMgr::e_InputChannelId c_InputFPPRemotePlayFile::~c_InputFPPRemotePlayFile () { // DEBUG_START; - MsTicker.detach (); - -#ifdef ARDUINO_ARCH_ESP32 - if (NULL != TimerPollTaskHandle) - { - // DEBUG_V("wait for the timer task to finish"); - while(TimerPollInProgress == true) {yield();} - - // DEBUG_V("Delete the task"); - vTaskDelete (TimerPollTaskHandle); - TimerPollTaskHandle = NULL; - } -#endif // def ARDUINO_ARCH_ESP32 for (uint32_t LoopCount = 10000; (LoopCount != 0) && (!IsIdle ()); LoopCount--) { Stop (); - Poll (false); + Poll (); } + // DEBUG_END; } // ~c_InputFPPRemotePlayFile @@ -108,13 +53,15 @@ c_InputFPPRemotePlayFile::~c_InputFPPRemotePlayFile () void c_InputFPPRemotePlayFile::Start (String & FileName, float SecondsElapsed, uint32_t PlayCount) { // DEBUG_START; - if (FileMgr.SdCardIsInstalled ()) + + if (!InputIsPaused() && FileMgr.SdCardIsInstalled ()) { + // DEBUG_V("Ask FSM to start the sequence."); pCurrentFsmState->Start (FileName, SecondsElapsed, PlayCount); } else { - // DEBUG_V ("No SD Card installed. Ignore Start request"); + // DEBUG_V ("Paused or No SD Card installed. Ignore Start request"); fsm_PlayFile_state_Idle_imp.Init (this); } @@ -126,7 +73,10 @@ void c_InputFPPRemotePlayFile::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; } // Stop @@ -134,49 +84,38 @@ void c_InputFPPRemotePlayFile::Stop () //----------------------------------------------------------------------------- void c_InputFPPRemotePlayFile::Sync (String & FileName, float SecondsElapsed) { - // DEBUG_START; + // xDEBUG_START; - SyncControl.SyncCount++; - UpdateElapsedPlayTimeMS (); - if (pCurrentFsmState->Sync (FileName, SecondsElapsed)) + if(!InputIsPaused()) { - SyncControl.SyncAdjustmentCount++; + SyncControl.SyncCount++; + UpdateElapsedPlayTimeMS (); + if (pCurrentFsmState->Sync (FileName, SecondsElapsed)) + { + SyncControl.SyncAdjustmentCount++; + } } - // DEBUG_END; - -} // Sync - -//----------------------------------------------------------------------------- -bool c_InputFPPRemotePlayFile::Poll (bool StayDark) -{ - // xDEBUG_START; - - // Show that we have received a poll - PollDetectionCounter = 0; - - // TimerPoll (); - return pCurrentFsmState->Poll (StayDark); - // xDEBUG_END; -} // Poll +} // Sync //----------------------------------------------------------------------------- -void c_InputFPPRemotePlayFile::TimerPoll () +bool c_InputFPPRemotePlayFile::Poll () { // xDEBUG_START; + bool Response = false; - // Are polls still coming in? - if (PollDetectionCounter < PollDetectionCounterLimit) + if(!InputIsPaused()) { - PollDetectionCounter++; - UpdateElapsedPlayTimeMS (); - pCurrentFsmState->TimerPoll (); + // xDEBUG_V("Poll the FSM"); + Response = pCurrentFsmState->Poll (); } + // xDEBUG_END; + return Response; -} // TimerPoll +} // Poll //----------------------------------------------------------------------------- void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) @@ -188,9 +127,9 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) // variables ending in "Rem" reflect remaining play time // File uses milliseconds to store elapsed and total play time - uint32_t mseconds = FrameControl.ElapsedPlayTimeMS; + uint32_t mseconds = FileControl[CurrentFile].ElapsedPlayTimeMS; uint32_t msecondsTotal; - if (__builtin_mul_overflow(FrameControl.FrameStepTimeMS, FrameControl.TotalNumberOfFramesInSequence, &msecondsTotal)) { + if (__builtin_mul_overflow(FileControl[CurrentFile].FrameStepTimeMS, FileControl[CurrentFile].TotalNumberOfFramesInSequence, &msecondsTotal)) { // returned non-zero: there has been an overflow msecondsTotal = MilliSecondsInASecond; // set to one second total when overflow occurs } @@ -204,29 +143,28 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) secsRem = 0; // set to zero remaining seconds when overflow occurs } - JsonStatus[F ("SyncCount")] = SyncControl.SyncCount; - JsonStatus[F ("SyncAdjustmentCount")] = SyncControl.SyncAdjustmentCount; + JsonWrite(JsonStatus, F ("SyncCount"), SyncControl.SyncCount); + JsonWrite(JsonStatus, F ("SyncAdjustmentCount"), SyncControl.SyncAdjustmentCount); String temp = GetFileName (); - JsonStatus[CN_current_sequence] = temp; - JsonStatus[CN_playlist] = temp; - JsonStatus[CN_seconds_elapsed] = String (secs); - JsonStatus[CN_seconds_played] = String (secs); - JsonStatus[CN_seconds_remaining] = String (secsRem); - JsonStatus[CN_sequence_filename] = temp; - JsonStatus[F("PlayedFileCount")] = PlayedFileCount; + JsonWrite(JsonStatus, CN_current_sequence, temp); + JsonWrite(JsonStatus, CN_playlist, temp); + JsonWrite(JsonStatus, CN_seconds_elapsed, String (secs)); + JsonWrite(JsonStatus, CN_seconds_played, String (secs)); + JsonWrite(JsonStatus, CN_seconds_remaining, String (secsRem)); + JsonWrite(JsonStatus, CN_sequence_filename, temp); + JsonWrite(JsonStatus, F("PlayedFileCount"), PlayedFileCount); // After inserting the total seconds and total seconds remaining, // JsonStatus also includes formatted "minutes + seconds" for both - // timeElapsed and timeRemaining + // time Elapsed and time Remaining char buf[12]; ESP_ERROR_CHECK(saferSecondsToFormattedMinutesAndSecondsString(buf, secs)); - JsonStatus[CN_time_elapsed] = buf; + JsonWrite(JsonStatus, CN_time_elapsed, buf); ESP_ERROR_CHECK(saferSecondsToFormattedMinutesAndSecondsString(buf, secsRem)); - JsonStatus[CN_time_remaining] = buf; - - JsonStatus[CN_errors] = LastFailedPlayStatusMsg; + JsonWrite(JsonStatus, CN_time_remaining, buf); + JsonWrite(JsonStatus, CN_errors, LastFailedPlayStatusMsg); // xDEBUG_END; @@ -235,44 +173,44 @@ void c_InputFPPRemotePlayFile::GetStatus (JsonObject& JsonStatus) //----------------------------------------------------------------------------- void c_InputFPPRemotePlayFile::UpdateElapsedPlayTimeMS () { - noInterrupts (); + // noInterrupts (); uint32_t now = millis (); - uint32_t elapsedMS = now - LastIsrTimeStampMS; - if (now < LastIsrTimeStampMS) + uint32_t elapsedMS = now - FileControl[CurrentFile].LastPollTimeMS; + if (now < FileControl[CurrentFile].LastPollTimeMS) { // handle wrap - elapsedMS = (0 - LastIsrTimeStampMS) + now; + elapsedMS = (0 - FileControl[CurrentFile].LastPollTimeMS) + now; } - LastIsrTimeStampMS = now; - FrameControl.ElapsedPlayTimeMS += elapsedMS; + FileControl[CurrentFile].LastPollTimeMS = now; + FileControl[CurrentFile].ElapsedPlayTimeMS += elapsedMS; - interrupts (); + // interrupts (); } // UpdateElapsedPlayTimeMS //----------------------------------------------------------------------------- uint32_t c_InputFPPRemotePlayFile::CalculateFrameId (uint32_t ElapsedMS, int32_t SyncOffsetMS) { - // DEBUG_START; + // xDEBUG_START; uint32_t CurrentFrameId = 0; do // once { uint32_t AdjustedPlayTime = ElapsedMS + SyncOffsetMS; - // DEBUG_V (String ("AdjustedPlayTime: ") + String (AdjustedPlayTime)); + // xDEBUG_V (String ("AdjustedPlayTime: ") + String (AdjustedPlayTime)); if ((0 > SyncOffsetMS) && (ElapsedMS < abs(SyncOffsetMS))) { break; } - CurrentFrameId = (AdjustedPlayTime / FrameControl.FrameStepTimeMS); - // DEBUG_V (String (" CurrentFrameId: ") + String (CurrentFrameId)); + CurrentFrameId = (AdjustedPlayTime / FileControl[CurrentFile].FrameStepTimeMS); + // xDEBUG_V (String (" CurrentFrameId: ") + String (CurrentFrameId)); } while (false); - // DEBUG_END; + // xDEBUG_END; return CurrentFrameId; @@ -289,23 +227,22 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () FSEQRawHeader fsqRawHeader; FSEQParsedHeader fsqParsedHeader; - if(c_FileMgr::INVALID_FILE_HANDLE != FileHandleForFileBeingPlayed) + if(c_FileMgr::INVALID_FILE_HANDLE != FileControl[CurrentFile].FileHandleForFileBeingPlayed) { - // DEBUG_V("Unexpected File Handle at fseq Parse."); - Stop(); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); } - if (false == FileMgr.OpenSdFile (PlayItemName, + if (false == FileMgr.OpenSdFile (FileControl[CurrentFile].FileName, c_FileMgr::FileMode::FileRead, - FileHandleForFileBeingPlayed, -1)) + FileControl[CurrentFile].FileHandleForFileBeingPlayed, -1)) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not open file: filename: '")) + PlayItemName + "'"); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not open file: filename: '")) + FileControl[CurrentFile].FileName + "'"); logcon (LastFailedPlayStatusMsg); break; } - // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (FileHandleForFileBeingPlayed)); - uint32_t BytesRead = FileMgr.ReadSdFile (FileHandleForFileBeingPlayed, + // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (FileControl[CurrentFile].FileHandleForFileBeingPlayed)); + uint32_t BytesRead = FileMgr.ReadSdFile (FileControl[CurrentFile].FileHandleForFileBeingPlayed, (uint8_t*)&fsqRawHeader, sizeof (fsqRawHeader), size_t(0)); // DEBUG_V (String (" BytesRead: ") + String (BytesRead)); @@ -313,9 +250,9 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () if (BytesRead != sizeof (fsqRawHeader)) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not read FSEQ header: filename: '")) + PlayItemName + "'"); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not read FSEQ header: filename: '")) + FileControl[CurrentFile].FileName + "'"); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } @@ -337,62 +274,63 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () // #define DUMP_FSEQ_HEADER #ifdef DUMP_FSEQ_HEADER - DEBUG_V (String (" dataOffset: ") + String (fsqParsedHeader.dataOffset)); - DEBUG_V (String (" minorVersion: ") + String (fsqParsedHeader.minorVersion)); - DEBUG_V (String (" majorVersion: ") + String (fsqParsedHeader.majorVersion)); - DEBUG_V (String (" VariableHdrOffset: ") + String (fsqParsedHeader.VariableHdrOffset)); - DEBUG_V (String (" channelCount: ") + String (fsqParsedHeader.channelCount)); - DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (fsqParsedHeader.TotalNumberOfFramesInSequence)); - DEBUG_V (String (" stepTime: ") + String (fsqParsedHeader.stepTime)); - DEBUG_V (String (" flags: ") + String (fsqParsedHeader.flags)); - DEBUG_V (String (" compressionType: 0x") + String (fsqParsedHeader.compressionType, HEX)); - DEBUG_V (String (" numCompressedBlocks: ") + String (fsqParsedHeader.numCompressedBlocks)); - DEBUG_V (String (" numSparseRanges: ") + String (fsqParsedHeader.numSparseRanges)); - DEBUG_V (String (" flags2: ") + String (fsqParsedHeader.flags2)); - DEBUG_V (String (" id: 0x") + String ((unsigned long)fsqParsedHeader.id, HEX)); + // DEBUG_V (String (" dataOffset: ") + String (fsqParsedHeader.dataOffset)); + // DEBUG_V (String (" minorVersion: ") + String (fsqParsedHeader.minorVersion)); + // DEBUG_V (String (" majorVersion: ") + String (fsqParsedHeader.majorVersion)); + // DEBUG_V (String (" VariableHdrOffset: ") + String (fsqParsedHeader.VariableHdrOffset)); + // DEBUG_V (String (" channelCount: ") + String (fsqParsedHeader.channelCount)); + // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (fsqParsedHeader.TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" stepTime: ") + String (fsqParsedHeader.stepTime)); + // DEBUG_V (String (" flags: ") + String (fsqParsedHeader.flags)); + // DEBUG_V (String (" compressionType: 0x") + String (fsqParsedHeader.compressionType, HEX)); + // DEBUG_V (String (" numCompressedBlocks: ") + String (fsqParsedHeader.numCompressedBlocks)); + // DEBUG_V (String (" numSparseRanges: ") + String (fsqParsedHeader.numSparseRanges)); + // DEBUG_V (String (" flags2: ") + String (fsqParsedHeader.flags2)); + // DEBUG_V (String (" id: 0x") + String ((unsigned long)fsqParsedHeader.id, HEX)); #endif // def DUMP_FSEQ_HEADER if (fsqParsedHeader.majorVersion != 2 || fsqParsedHeader.compressionType != 0) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + PlayItemName + F (" is not a v2 uncompressed sequence")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + FileControl[CurrentFile].FileName + F (" is not a v2 uncompressed sequence")); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } // DEBUG_V (""); - size_t ActualDataSize = FileMgr.GetSdFileSize (FileHandleForFileBeingPlayed) - sizeof(fsqParsedHeader); + size_t ActualDataSize = FileMgr.GetSdFileSize (FileControl[CurrentFile].FileHandleForFileBeingPlayed) - sizeof(fsqParsedHeader); size_t NeededDataSize = fsqParsedHeader.TotalNumberOfFramesInSequence * fsqParsedHeader.channelCount; // DEBUG_V("NeededDataSize: " + String(NeededDataSize)); // DEBUG_V("ActualDataSize: " + String(ActualDataSize)); if (NeededDataSize > ActualDataSize) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start: ")) + PlayItemName + + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start: ")) + FileControl[CurrentFile].FileName + F (" File does not contain enough data to meet the Stated Channel Count * Number of Frames value. Need: ") + String (NeededDataSize) + F (", SD File Size: ") + String (ActualDataSize)); logcon (LastFailedPlayStatusMsg); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } - FrameControl.FrameStepTimeMS = max ((uint8_t)25, fsqParsedHeader.stepTime); - FrameControl.TotalNumberOfFramesInSequence = fsqParsedHeader.TotalNumberOfFramesInSequence; + FileControl[CurrentFile].FrameStepTimeMS = max ((uint8_t)25, fsqParsedHeader.stepTime); + FileControl[CurrentFile].TotalNumberOfFramesInSequence = fsqParsedHeader.TotalNumberOfFramesInSequence; - FrameControl.DataOffset = fsqParsedHeader.dataOffset; - FrameControl.ChannelsPerFrame = fsqParsedHeader.channelCount; + FileControl[CurrentFile].DataOffset = fsqParsedHeader.dataOffset; + FileControl[CurrentFile].ChannelsPerFrame = fsqParsedHeader.channelCount; memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); if (fsqParsedHeader.numSparseRanges) { if (MAX_NUM_SPARSE_RANGES < fsqParsedHeader.numSparseRanges) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + PlayItemName + F (" Too many sparse ranges defined in file header.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Could not start. ")) + FileControl[CurrentFile].FileName + F (" Too many sparse ranges defined in file header.")); logcon (LastFailedPlayStatusMsg); - FileMgr.CloseSdFile(FileHandleForFileBeingPlayed); + FileMgr.CloseSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed); break; } FSEQRawRangeEntry FseqRawRanges[MAX_NUM_SPARSE_RANGES]; - FileMgr.ReadSdFile (FileHandleForFileBeingPlayed, + FileMgr.ReadSdFile (FileControl[CurrentFile].FileHandleForFileBeingPlayed, (uint8_t*)&FseqRawRanges[0], sizeof (FseqRawRanges), sizeof (FSEQRawHeader) + fsqParsedHeader.numCompressedBlocks * 8); @@ -430,7 +368,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () #endif // def DUMP_FSEQ_HEADER if (0 == TotalChannels) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" No channels defined in Sparse Ranges.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" No channels defined in Sparse Ranges.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -438,7 +376,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () else if (TotalChannels > fsqParsedHeader.channelCount) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" Too many channels defined in Sparse Ranges.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" Too many channels defined in Sparse Ranges.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -446,7 +384,7 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () else if (LargestBlock > fsqParsedHeader.channelCount) { - LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + PlayItemName + F (" Sparse Range Frame offset + Num channels is larger than frame size.")); + LastFailedPlayStatusMsg = (String (F ("ParseFseqFile:: Ignoring Range Info. ")) + FileControl[CurrentFile].FileName + F (" Sparse Range Frame offset + Num channels is larger than frame size.")); logcon (LastFailedPlayStatusMsg); memset ((void*)&SparseRanges, 0x00, sizeof (SparseRanges)); SparseRanges[0].ChannelCount = fsqParsedHeader.channelCount; @@ -475,46 +413,49 @@ bool c_InputFPPRemotePlayFile::ParseFseqFile () void c_InputFPPRemotePlayFile::ClearFileInfo() { // DEBUG_START; - PlayItemName = emptyString; - RemainingPlayCount = 0; - SyncControl.LastRcvdElapsedSeconds = 0.0; - FrameControl.ElapsedPlayTimeMS = 0; - FrameControl.DataOffset = 0; - FrameControl.ChannelsPerFrame = 0; - FrameControl.FrameStepTimeMS = 25; - FrameControl.TotalNumberOfFramesInSequence = 0; + FileControl[NextFile].FileName = emptyString; + FileControl[NextFile].FileHandleForFileBeingPlayed = c_FileMgr::INVALID_FILE_HANDLE; + FileControl[NextFile].RemainingPlayCount = 0; + SyncControl.LastRcvdElapsedSeconds = 0.0; + FileControl[NextFile].ElapsedPlayTimeMS = 0; + FileControl[NextFile].DataOffset = 0; + FileControl[NextFile].ChannelsPerFrame = 0; + FileControl[NextFile].FrameStepTimeMS = 25; + FileControl[NextFile].TotalNumberOfFramesInSequence = 0; // DEBUG_END; } // ClearFileInfo +//----------------------------------------------------------------------------- uint32_t c_InputFPPRemotePlayFile::ReadFile(uint32_t DestinationIntensityId, uint32_t NumBytesToRead, uint32_t FileOffset) { - // DEBUG_START; -// #define WRITE_DIRECT_TO_OUTPUT_BUFFER -#ifdef WRITE_DIRECT_TO_OUTPUT_BUFFER - uint32_t NumBytesRead = FileMgr.ReadSdFile(FileHandleForFileBeingPlayed, - OutputMgr.GetBufferAddress(), - min((NumBytesToRead), OutputMgr.GetBufferUsedSize()), - FileOffset); -#else - uint8_t LocalIntensityBuffer[200]; + // xDEBUG_START; uint32_t NumBytesRead = 0; + uint8_t LocalIntensityBuffer[200]; - while (NumBytesRead < NumBytesToRead) + do // once { - uint32_t NumBytesReadThisPass = FileMgr.ReadSdFile(FileHandleForFileBeingPlayed, - LocalIntensityBuffer, - min((NumBytesToRead - NumBytesRead), sizeof(LocalIntensityBuffer)), - FileOffset); + if(c_FileMgr::INVALID_FILE_HANDLE == FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + // DEBUG_V(String("FileHandleForFileBeingPlayed: ") + String(FileControl[CurrentFile].FileHandleForFileBeingPlayed)); + break; + } - OutputMgr.WriteChannelData(DestinationIntensityId, NumBytesReadThisPass, LocalIntensityBuffer); + while (NumBytesRead < NumBytesToRead) + { + uint32_t NumBytesReadThisPass = FileMgr.ReadSdFile(FileControl[CurrentFile].FileHandleForFileBeingPlayed, + LocalIntensityBuffer, + min((NumBytesToRead - NumBytesRead), sizeof(LocalIntensityBuffer)), + FileOffset); - FileOffset += NumBytesReadThisPass; - NumBytesRead += NumBytesReadThisPass; - DestinationIntensityId += NumBytesReadThisPass; - } -#endif // !def WRITE_DIRECT_TO_OUTPUT_BUFFER + OutputMgr.WriteChannelData(DestinationIntensityId, NumBytesReadThisPass, LocalIntensityBuffer); - // DEBUG_END; + FileOffset += NumBytesReadThisPass; + NumBytesRead += NumBytesReadThisPass; + DestinationIntensityId += NumBytesReadThisPass; + } + } while (false); + + // xDEBUG_END; return NumBytesRead; } // ReadFile diff --git a/src/input/InputFPPRemotePlayFileFsm.cpp b/src/input/InputFPPRemotePlayFileFsm.cpp index 133634b14..2aab40bd1 100644 --- a/src/input/InputFPPRemotePlayFileFsm.cpp +++ b/src/input/InputFPPRemotePlayFileFsm.cpp @@ -23,37 +23,32 @@ #include "service/FPPDiscovery.h" //----------------------------------------------------------------------------- -bool fsm_PlayFile_state_Idle::Poll (bool /* StayDark */) +bool fsm_PlayFile_state_Idle::Poll () { - // DEBUG_START; - - // DEBUG_V("fsm_PlayFile_state_Idle::Poll"); + // xDEBUG_START; + // xDEBUG_V("fsm_PlayFile_state_Idle::Poll"); - // do nothing + // is there a new file to play? + if(!p_Parent->FileControl[NextFile].FileName.isEmpty()) + { + p_Parent->fsm_PlayFile_state_Starting_imp.Init (p_Parent); + } - // DEBUG_END; + // xDEBUG_END; return false; } // fsm_PlayFile_state_Idle::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Idle::TimerPoll () -{ - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - -} // fsm_PlayFile_state_Idle::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Idle::Init (c_InputFPPRemotePlayFile* Parent) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Idle::Init"); - // DEBUG_V (String (" Parent: 0x") + String ((uint32_t)Parent, HEX)); + // DEBUG_V (String ("Parent: 0x") + String ((uint32_t)Parent, HEX)); p_Parent = Parent; - p_Parent->pCurrentFsmState = &(p_Parent->fsm_PlayFile_state_Idle_imp); p_Parent->ClearFileInfo (); + p_Parent->pCurrentFsmState = &(p_Parent->fsm_PlayFile_state_Idle_imp); // DEBUG_END; @@ -64,18 +59,19 @@ void fsm_PlayFile_state_Idle::Start (String& FileName, float ElapsedSeconds, uin { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Idle::Start"); - // DEBUG_V (String ("FileName: ") + FileName); - p_Parent->PlayItemName = FileName; - p_Parent->FrameControl.ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000); - p_Parent->RemainingPlayCount = RemainingPlayCount; - - // DEBUG_V (String (" FileName: ") + p_Parent->PlayItemName); - // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FrameControl.ElapsedPlayTimeMS); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; - p_Parent->fsm_PlayFile_state_Starting_imp.Init (p_Parent); + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); // DEBUG_END; @@ -97,7 +93,7 @@ void fsm_PlayFile_state_Idle::Stop (void) bool fsm_PlayFile_state_Idle::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State: Idle"); + // DEBUG_V("fsm_PlayFile_state_Idle::Sync"); Start (FileName, ElapsedSeconds, 1); @@ -110,33 +106,44 @@ bool fsm_PlayFile_state_Idle::Sync (String& FileName, float ElapsedSeconds) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayFile_state_Starting::Poll (bool StayDark) +bool fsm_PlayFile_state_Starting::Poll () { // DEBUG_START; + // DEBUG_V("fsm_PlayFile_state_Starting::Poll"); - if(StayDark) - { - p_Parent->fsm_PlayFile_state_Stopping_imp.Init (p_Parent); - } - else + do // once { + p_Parent->FileControl[CurrentFile] = p_Parent->FileControl[NextFile]; + p_Parent->ClearFileInfo(); + + if (!p_Parent->ParseFseqFile ()) + { + // DEBUG_V("fsm_PlayFile_state_PlayingFile::Poll FSEQ Parse Error"); + break; + } + + p_Parent->FileControl[CurrentFile].RemainingPlayCount --; + p_Parent->FileControl[CurrentFile].LastPollTimeMS = millis(); + p_Parent->FileControl[CurrentFile].StartingTimeMS = p_Parent->FileControl[CurrentFile].LastPollTimeMS - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[CurrentFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[CurrentFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[CurrentFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + // DEBUG_V (String (" LastPlayedFrameId: ") + p_Parent->FileControl[CurrentFile].LastPlayedFrameId); + // DEBUG_V (String ("NumberOfFramesInSequence: ") + p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence); + p_Parent->fsm_PlayFile_state_PlayingFile_imp.Init (p_Parent); - } - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->FrameControl.TotalNumberOfFramesInSequence)); + + } while (false); // DEBUG_END; return true; } // fsm_PlayFile_state_Starting::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Starting::TimerPoll () -{ - // nothing to do - -} // fsm_PlayFile_state_Starting::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Starting::Init (c_InputFPPRemotePlayFile* Parent) { @@ -161,11 +168,19 @@ void fsm_PlayFile_state_Starting::Start (String& FileName, float ElapsedSeconds, // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Starting::Start"); - // DEBUG_V (String ("FileName: ") + FileName); - p_Parent->PlayItemName = FileName; - p_Parent->FrameControl.ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000); - p_Parent->RemainingPlayCount = RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + p_Parent->fsm_PlayFile_state_Stopping_imp.Init(p_Parent); // DEBUG_END; @@ -177,8 +192,8 @@ void fsm_PlayFile_state_Starting::Stop (void) // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Starting::Stop"); - p_Parent->RemainingPlayCount = 0; - p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); + p_Parent->FileControl[CurrentFile].RemainingPlayCount = 0; + p_Parent->fsm_PlayFile_state_Stopping_imp.Init (p_Parent); // DEBUG_END; @@ -188,7 +203,7 @@ void fsm_PlayFile_state_Starting::Stop (void) bool fsm_PlayFile_state_Starting::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State:Starting"); + // DEBUG_V("fsm_PlayFile_state_Starting::Sync"); bool response = false; @@ -202,7 +217,7 @@ bool fsm_PlayFile_state_Starting::Sync (String& FileName, float ElapsedSeconds) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayFile_state_PlayingFile::Poll (bool StayDark) +bool fsm_PlayFile_state_PlayingFile::Poll () { // xDEBUG_START; @@ -210,90 +225,74 @@ bool fsm_PlayFile_state_PlayingFile::Poll (bool StayDark) do // once { - if(!StayDark || (c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileHandleForFileBeingPlayed)) + if(c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) { - // DEBUG_V("Bad FileHandleForFileBeingPlayed"); + // DEBUG_V("Unexpected missing file handle"); Stop(); break; } - // DEBUG_V (String ("LastPlayedFrameId: ") + String (LastPlayedFrameId)); + + p_Parent->UpdateElapsedPlayTimeMS(); + uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // xDEBUG_V (String ("LastPlayedFrameId: ") + String (CurrentFrame)); // have we reached the end of the file? - if (p_Parent->FrameControl.TotalNumberOfFramesInSequence <= LastPlayedFrameId) + if (p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence <= CurrentFrame) { - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - if (0 != p_Parent->RemainingPlayCount) + // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + if (0 != p_Parent->FileControl[CurrentFile].RemainingPlayCount) { - // DEBUG_V (String ("RemainingPlayCount: ") + String (p_Parent->RemainingPlayCount)); + // DEBUG_V (String (" Restart Playing:: FileName: '") + p_Parent->GetFileName () + "'"); + // DEBUG_V (String ("RemainingPlayCount: ") + String (p_Parent->FileControl[CurrentFile].RemainingPlayCount)); // DEBUG_V (String ("Replaying:: FileName: '") + p_Parent->GetFileName () + "'"); - --p_Parent->RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - LastPlayedFrameId = 0; + --p_Parent->FileControl[CurrentFile].RemainingPlayCount; + // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS = 0; + p_Parent->FileControl[CurrentFile].RemainingPlayCount --; + p_Parent->FileControl[CurrentFile].LastPollTimeMS = millis(); + p_Parent->FileControl[CurrentFile].StartingTimeMS = p_Parent->FileControl[CurrentFile].LastPollTimeMS; + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[CurrentFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[CurrentFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[CurrentFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); + // DEBUG_V (String (" LastPlayedFrameId: ") + p_Parent->FileControl[CurrentFile].LastPlayedFrameId); + // DEBUG_V (String ("NumberOfFramesInSequence: ") + p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence); } else { - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String (" Done Playing:: FileName: '") + p_Parent->GetFileName () + "'"); - p_Parent->Stop (); + // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" Done Playing:: FileName: '") + p_Parent->FileControl[CurrentFile].FileName + "'"); + Stop (); Response = true; break; } - } - // DEBUG_V(); - InputMgr.RestartBlankTimer (p_Parent->GetInputChannelId ()); - - } while (false); - - // xDEBUG_END; - return Response; - -} // fsm_PlayFile_state_PlayingFile::Poll - -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () -{ - // xDEBUG_START; - - do // once - { - if(c_FileMgr::INVALID_FILE_HANDLE == p_Parent->FileHandleForFileBeingPlayed) - { - // DEBUG_V("Bad FileHandleForFileBeingPlayed"); - Stop(); - break; - } - - uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FrameControl.ElapsedPlayTimeMS, p_Parent->GetSyncOffsetMS ()); - - // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - - // have we reached the end of the file? - if (p_Parent->FrameControl.TotalNumberOfFramesInSequence <= CurrentFrame) - { - LastPlayedFrameId = CurrentFrame; break; } - if (CurrentFrame == LastPlayedFrameId) + // Do we need to do an update? + if (CurrentFrame == p_Parent->FileControl[CurrentFile].LastPlayedFrameId) { // xDEBUG_V (String ("keep waiting")); break; } + p_Parent->FileControl[CurrentFile].LastPlayedFrameId = CurrentFrame; - uint32_t FilePosition = p_Parent->FrameControl.DataOffset + (p_Parent->FrameControl.ChannelsPerFrame * CurrentFrame); + uint32_t FilePosition = p_Parent->FileControl[CurrentFile].DataOffset + (p_Parent->FileControl[CurrentFile].ChannelsPerFrame * CurrentFrame); uint32_t BufferSize = OutputMgr.GetBufferUsedSize(); - uint32_t MaxBytesToRead = (p_Parent->FrameControl.ChannelsPerFrame > BufferSize) ? BufferSize : p_Parent->FrameControl.ChannelsPerFrame; + uint32_t MaxBytesToRead = (p_Parent->FileControl[CurrentFile].ChannelsPerFrame > BufferSize) ? BufferSize : p_Parent->FileControl[CurrentFile].ChannelsPerFrame; uint32_t CurrentDestination = 0; // xDEBUG_V (String (" MaxBytesToRead: ") + String (MaxBytesToRead)); - LastPlayedFrameId = CurrentFrame; + InputMgr.RestartBlankTimer (p_Parent->GetInputChannelId ()); if(p_Parent->SendFppSync) { - FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_SYNC, p_Parent->GetFileName(), CurrentFrame, float(p_Parent->FrameControl.ElapsedPlayTimeMS) / 1000.0); + FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_SYNC, p_Parent->GetFileName(), CurrentFrame, float(p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS) / 1000.0); } for (auto& CurrentSparseRange : p_Parent->SparseRanges) @@ -307,10 +306,10 @@ IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () uint32_t AdjustedFilePosition = FilePosition + CurrentSparseRange.DataOffset; - /// DEBUG_V (String (" FilePosition: ") + String (FilePosition)); - /// DEBUG_V (String (" AdjustedFilePosition: ") + String (uint32_t(AdjustedFilePosition), HEX)); - /// DEBUG_V (String (" CurrentDestination: ") + String (uint32_t(CurrentDestination), HEX)); - /// DEBUG_V (String (" ActualBytesToRead: ") + String (ActualBytesToRead)); + // xDEBUG_V (String (" FilePosition: ") + String (FilePosition)); + // xDEBUG_V (String (" AdjustedFilePosition: ") + String (uint32_t(AdjustedFilePosition), HEX)); + // xDEBUG_V (String (" CurrentDestination: ") + String (uint32_t(CurrentDestination), HEX)); + // xDEBUG_V (String (" ActualBytesToRead: ") + String (ActualBytesToRead)); uint32_t ActualBytesRead = p_Parent->ReadFile(CurrentDestination, ActualBytesToRead, AdjustedFilePosition); MaxBytesToRead -= ActualBytesRead; @@ -318,24 +317,19 @@ IRAM_ATTR void fsm_PlayFile_state_PlayingFile::TimerPoll () if (ActualBytesRead != ActualBytesToRead) { - // xDEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - + // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->FileControl[CurrentFile].TotalNumberOfFramesInSequence)); + // DEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); // DEBUG_V (F ("File Playback Failed to read enough data")); - p_Parent->Stop (); + Stop (); } } - // xDEBUG_V (String (" DataOffset: ") + String (p_Parent->DataOffset)); - // xDEBUG_V (String (" BufferSize: ") + String (p_Parent->BufferSize)); - // xDEBUG_V (String (" ChannelsPerFrame: ") + String (p_Parent->ChannelsPerFrame)); - // xDEBUG_V (String (" FilePosition: ") + String (FilePosition)); - // xDEBUG_V (String (" MaxBytesToRead: ") + String (MaxBytesToRead)); - // xDEBUG_V (String ("GetInputChannelId: ") + String (p_Parent->GetInputChannelId ())); - } while (false); -} // fsm_PlayFile_state_PlayingFile::TimerPoll + // xDEBUG_END; + return Response; + +} // fsm_PlayFile_state_PlayingFile::Poll //----------------------------------------------------------------------------- void fsm_PlayFile_state_PlayingFile::Init (c_InputFPPRemotePlayFile* Parent) @@ -345,59 +339,35 @@ void fsm_PlayFile_state_PlayingFile::Init (c_InputFPPRemotePlayFile* Parent) p_Parent = Parent; - do // once - { - LastPlayedFrameId = 0; - - // DEBUG_V (String ("FileName: '") + p_Parent->PlayItemName + "'"); - // DEBUG_V (String (" FrameId: '") + p_Parent->LastPlayedFrameId + "'"); - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - if (0 == p_Parent->RemainingPlayCount) - { - // DEBUG_V(); - p_Parent->Stop (); - break; - } - - --p_Parent->RemainingPlayCount; - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - - if (!p_Parent->ParseFseqFile ()) - { - p_Parent->fsm_PlayFile_state_Error_imp.Init (p_Parent); - break; - } - - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String (" StartTimeMS: ") + String (p_Parent->StartTimeMS)); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - - // DEBUG_V (String (F ("Start Playing:: FileName: '")) + p_Parent->PlayItemName + "'"); - - Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_PlayingFile_imp); - Parent->FrameControl.ElapsedPlayTimeMS = 0; - - } while (false); + // LastPlayedFrameId = 0; + Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_PlayingFile_imp); // DEBUG_END; } // fsm_PlayFile_state_PlayingFile::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_PlayingFile::Start (String& FileName, float ElapsedSeconds, uint32_t PlayCount) +void fsm_PlayFile_state_PlayingFile::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_PlayingFile::Start"); - // DEBUG_V (String (" FileName: ") + FileName); - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String ("RemainingPlayCount: ") + p_Parent->RemainingPlayCount); - // DEBUG_V(); - p_Parent->Stop (); - // DEBUG_V(); - p_Parent->Start (FileName, ElapsedSeconds, PlayCount); + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + // DEBUG_V("Stop old file"); + Stop (); // DEBUG_END; @@ -409,16 +379,11 @@ void fsm_PlayFile_state_PlayingFile::Stop (void) // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_PlayingFile::Stop"); - // DEBUG_V (String (F ("Stop Playing:: FileName: '")) + p_Parent->PlayItemName + "'"); - // DEBUG_V (String (" LastPlayedFrameId: ") + String (p_Parent->LastPlayedFrameId)); - // DEBUG_V (String ("TotalNumberOfFramesInSequence: ") + String (p_Parent->TotalNumberOfFramesInSequence)); - // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->RemainingPlayCount); + // DEBUG_V (String (F ("Stop Playing:: FileName: '")) + p_Parent->FileControl[CurrentFile].FileName + "'"); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[CurrentFile].RemainingPlayCount); p_Parent->fsm_PlayFile_state_Stopping_imp.Init (p_Parent); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - LastPlayedFrameId = 0; - // DEBUG_END; } // fsm_PlayFile_state_PlayingFile::Stop @@ -426,7 +391,9 @@ void fsm_PlayFile_state_PlayingFile::Stop (void) //----------------------------------------------------------------------------- bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSeconds) { - // DEBUG_START; + // xDEBUG_START; + // xDEBUG_V("fsm_PlayFile_state_PlayingFile::Sync"); + bool response = false; do // once @@ -434,9 +401,7 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond // are we on the correct file? if (!FileName.equals(p_Parent->GetFileName ())) { - // DEBUG_V ("Sync: Filename change"); - p_Parent->Stop (); - // DEBUG_V(); + // DEBUG_V ("Sync: Filename change: Start"); p_Parent->Start (FileName, ElapsedSeconds, 1); break; } @@ -447,56 +412,57 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond break; } - // DEBUG_V (String ("old LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); + // xDEBUG_V (String ("old LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); p_Parent->SyncControl.LastRcvdElapsedSeconds = ElapsedSeconds; - // DEBUG_V (String ("new LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); - // DEBUG_V (String (" ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V (String ("new LastRcvdElapsedSeconds: ") + String (p_Parent->SyncControl.LastRcvdElapsedSeconds)); + // xDEBUG_V (String (" ElapsedPlayTimeMS: ") + String (p_Parent->FileControl.ElapsedPlayTimeMS)); uint32_t TargetElapsedMS = uint32_t (ElapsedSeconds * 1000); - uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FrameControl.ElapsedPlayTimeMS, 0); + uint32_t CurrentFrame = p_Parent->CalculateFrameId (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS, 0); uint32_t TargetFrameId = p_Parent->CalculateFrameId (TargetElapsedMS, 0); int32_t FrameDiff = TargetFrameId - CurrentFrame; if (2 > abs (FrameDiff)) { - // DEBUG_V ("No Need to adjust the time"); + // xDEBUG_V ("No Need to adjust the time"); break; } - // DEBUG_V ("Need to adjust the start time"); - // DEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V ("Need to adjust the start time"); + // xDEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FileControl.ElapsedPlayTimeMS)); - // DEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); - // DEBUG_V (String (" TargetFrameId: ") + String (TargetFrameId)); - // DEBUG_V (String (" FrameDiff: ") + String (FrameDiff)); + // xDEBUG_V (String (" CurrentFrame: ") + String (CurrentFrame)); + // xDEBUG_V (String (" TargetFrameId: ") + String (TargetFrameId)); + // xDEBUG_V (String (" FrameDiff: ") + String (FrameDiff)); // Adjust the start of the file time to align with the master FPP - noInterrupts (); if (20 < abs (FrameDiff)) { - // DEBUG_V ("Large Setp Adjustment"); - p_Parent->FrameControl.ElapsedPlayTimeMS = TargetElapsedMS; + // xDEBUG_V ("Large Setp Adjustment"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS = TargetElapsedMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - TargetElapsedMS; } else if(CurrentFrame > TargetFrameId) { - // DEBUG_V("go back a frame"); - p_Parent->FrameControl.ElapsedPlayTimeMS -= p_Parent->FrameControl.FrameStepTimeMS; + // xDEBUG_V("go back a frame"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS -= p_Parent->FileControl[CurrentFile].FrameStepTimeMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; } else { - // DEBUG_V("go forward a frame"); - p_Parent->FrameControl.ElapsedPlayTimeMS += p_Parent->FrameControl.FrameStepTimeMS; + // xDEBUG_V("go forward a frame"); + p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS += p_Parent->FileControl[CurrentFile].FrameStepTimeMS; + p_Parent->FileControl[CurrentFile].StartingTimeMS = millis() - p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS; } - interrupts (); response = true; - // DEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FrameControl.ElapsedPlayTimeMS)); + // xDEBUG_V (String ("ElapsedPlayTimeMS: ") + String (p_Parent->FileControl[CurrentFile].ElapsedPlayTimeMS)); } while (false); - // DEBUG_END; + // xDEBUG_END; return response; } // fsm_PlayFile_state_PlayingFile::Sync @@ -504,45 +470,34 @@ bool fsm_PlayFile_state_PlayingFile::Sync (String& FileName, float ElapsedSecond //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayFile_state_Stopping::Poll (bool /* StayDark */) +bool fsm_PlayFile_state_Stopping::Poll () { // DEBUG_START; - // DEBUG_V("fsm_PlayFile_state_Stopping::Poll"); - // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (p_Parent->FileHandleForFileBeingPlayed)); - FileMgr.CloseSdFile (p_Parent->FileHandleForFileBeingPlayed); - p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); + // DEBUG_V (String ("FileHandleForFileBeingPlayed: ") + String (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed)); - StartingElapsedTime = 0.0; - PlayCount = 0; + if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + FileMgr.CloseSdFile (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed); + } + else + { + // DEBUG_V("Unexpected missing file handle"); + } - p_Parent->SyncControl.LastRcvdElapsedSeconds = 0; - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; + p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); if(p_Parent->SendFppSync) { FPPDiscovery.GenerateFppSyncMsg(SYNC_PKT_STOP, emptyString, 0, float(0.0)); } - if (!FileName.equals(emptyString)) - { - // DEBUG_V ("Restarting File"); - p_Parent->Start (FileName, StartingElapsedTime, PlayCount); - } - // DEBUG_END; return true; } // fsm_PlayFile_state_Stopping::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Stopping::TimerPoll () -{ - // nothing to do - -} // fsm_PlayFile_state_Stopping::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Stopping::Init (c_InputFPPRemotePlayFile* Parent) { @@ -557,14 +512,24 @@ void fsm_PlayFile_state_Stopping::Init (c_InputFPPRemotePlayFile* Parent) } // fsm_PlayFile_state_Stopping::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_Stopping::Start (String& _FileName, float ElapsedTime, uint32_t _PlayCount) +void fsm_PlayFile_state_Stopping::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Stopping::Start"); - FileName = _FileName; - StartingElapsedTime = ElapsedTime; - PlayCount = _PlayCount; + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); // DEBUG_END; @@ -584,7 +549,7 @@ void fsm_PlayFile_state_Stopping::Stop (void) bool fsm_PlayFile_state_Stopping::Sync (String&, float) { // DEBUG_START; - // DEBUG_V("State:Stopping"); + // DEBUG_V("fsm_PlayFile_state_Stopping::Sync"); // DEBUG_END; return false; @@ -594,32 +559,28 @@ bool fsm_PlayFile_state_Stopping::Sync (String&, float) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayFile_state_Error::Poll (bool /* StayDark */) +bool fsm_PlayFile_state_Error::Poll () { - // xDEBUG_START; + // DEBUG_START; + // DEBUG_V("fsm_PlayFile_state_Error::Poll"); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; + if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed) + { + // DEBUG_V("Unexpected file handle in Error handler."); + FileMgr.CloseSdFile (p_Parent->FileControl[CurrentFile].FileHandleForFileBeingPlayed); + } + else + { + // DEBUG_V("Unexpected missing file handle"); + } - // xDEBUG_END; + p_Parent->FileControl[CurrentFile].FileName.clear(); + + // DEBUG_END; return false; } // fsm_PlayFile_state_Error::Poll -//----------------------------------------------------------------------------- -IRAM_ATTR void fsm_PlayFile_state_Error::TimerPoll () -{ - // xDEBUG_START; - - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - - // xDEBUG_END; - -} // fsm_PlayFile_state_Error::TimerPoll - //----------------------------------------------------------------------------- void fsm_PlayFile_state_Error::Init (c_InputFPPRemotePlayFile* Parent) { @@ -629,30 +590,31 @@ void fsm_PlayFile_state_Error::Init (c_InputFPPRemotePlayFile* Parent) p_Parent = Parent; Parent->pCurrentFsmState = &(Parent->fsm_PlayFile_state_Error_imp); - p_Parent->FrameControl.ElapsedPlayTimeMS = 0; - p_Parent->FrameControl.FrameStepTimeMS = 0; - p_Parent->FrameControl.TotalNumberOfFramesInSequence = 0; - - if(c_FileMgr::INVALID_FILE_HANDLE != p_Parent->FileHandleForFileBeingPlayed) - { - // DEBUG_V("Unexpected File Handle at error init."); - FileMgr.CloseSdFile(p_Parent->FileHandleForFileBeingPlayed); - } - // DEBUG_END; } // fsm_PlayFile_state_Error::Init //----------------------------------------------------------------------------- -void fsm_PlayFile_state_Error::Start (String& FileName, float ElapsedSeconds, uint32_t PlayCount) +void fsm_PlayFile_state_Error::Start (String& FileName, float ElapsedSeconds, uint32_t RemainingPlayCount) { // DEBUG_START; // DEBUG_V("fsm_PlayFile_state_Error::Start"); - if (!FileName.equals(p_Parent->GetFileName ())) - { - p_Parent->fsm_PlayFile_state_Idle_imp.Start (FileName, ElapsedSeconds, PlayCount); - } + // DEBUG_V("Set up a next file"); + + p_Parent->FileControl[NextFile].FileName = FileName; + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS = uint32_t (ElapsedSeconds * 1000.0); + p_Parent->FileControl[NextFile].LastPollTimeMS = millis(); + p_Parent->FileControl[NextFile].StartingTimeMS = p_Parent->FileControl[NextFile].LastPollTimeMS - p_Parent->FileControl[NextFile].ElapsedPlayTimeMS; + p_Parent->FileControl[NextFile].RemainingPlayCount = RemainingPlayCount; + + // DEBUG_V (String (" FileName: ") + p_Parent->FileControl[NextFile].FileName); + // DEBUG_V (String (" ElapsedPlayTimeMS: ") + p_Parent->FileControl[NextFile].ElapsedPlayTimeMS); + // DEBUG_V (String (" LastPollTimeMS: ") + p_Parent->FileControl[NextFile].LastPollTimeMS); + // DEBUG_V (String (" StartingTimeMS: ") + p_Parent->FileControl[NextFile].StartingTimeMS); + // DEBUG_V (String (" RemainingPlayCount: ") + p_Parent->FileControl[NextFile].RemainingPlayCount); + + p_Parent->fsm_PlayFile_state_Idle_imp.Init (p_Parent); // DEBUG_END @@ -674,12 +636,9 @@ void fsm_PlayFile_state_Error::Stop (void) bool fsm_PlayFile_state_Error::Sync (String& FileName, float ElapsedSeconds) { // DEBUG_START; - // DEBUG_V("State:Error"); + // DEBUG_V("fsm_PlayFile_state_Error::Sync"); - if (!FileName.equals(p_Parent->GetFileName ())) - { - p_Parent->fsm_PlayFile_state_Idle_imp.Start (FileName, ElapsedSeconds, 1); - } + Start(FileName, ElapsedSeconds, 1); // DEBUG_END; return false; diff --git a/src/input/InputFPPRemotePlayList.cpp b/src/input/InputFPPRemotePlayList.cpp index 9289b6a32..c5f94ef3f 100644 --- a/src/input/InputFPPRemotePlayList.cpp +++ b/src/input/InputFPPRemotePlayList.cpp @@ -48,7 +48,10 @@ void c_InputFPPRemotePlayList::Start (String & FileName, float ElapsedSeconds, u { // DEBUG_START; - pCurrentFsmState->Start (FileName, ElapsedSeconds, PlayCount); + if(!InputIsPaused()) + { + pCurrentFsmState->Start (FileName, ElapsedSeconds, PlayCount); + } // DEBUG_END; @@ -59,7 +62,10 @@ void c_InputFPPRemotePlayList::Stop () { // DEBUG_START; - pCurrentFsmState->Stop (); + if(!InputIsPaused()) + { + pCurrentFsmState->Stop (); + } // DEBUG_END; @@ -70,20 +76,28 @@ void c_InputFPPRemotePlayList::Sync (String & FileName, float ElapsedSeconds) { // DEBUG_START; - pCurrentFsmState->Sync (FileName, ElapsedSeconds); + if(!InputIsPaused()) + { + pCurrentFsmState->Sync (FileName, ElapsedSeconds); + } // DEBUG_END; } // Sync //----------------------------------------------------------------------------- -bool c_InputFPPRemotePlayList::Poll (bool StayDark) +bool c_InputFPPRemotePlayList::Poll () { // DEBUG_START; + bool Response = false; + if(!InputIsPaused()) + { + // Show that we have received a poll + Response = pCurrentFsmState->Poll (); + } - return pCurrentFsmState->Poll (StayDark); - - // DEBUG_END; + // xDEBUG_END; + return Response; } // Poll @@ -92,9 +106,9 @@ void c_InputFPPRemotePlayList::GetStatus (JsonObject & jsonStatus) { // DEBUG_START; - jsonStatus[CN_name] = GetFileName (); - jsonStatus[F ("entry")] = PlayListEntryId; - jsonStatus[CN_count] = PlayListRepeatCount; + JsonWrite(jsonStatus, CN_name, GetFileName ()); + JsonWrite(jsonStatus, CN_entry, PlayListEntryId); + JsonWrite(jsonStatus, CN_count, PlayListRepeatCount); pCurrentFsmState->GetStatus (jsonStatus); @@ -119,11 +133,11 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () // Get the playlist file String FileData; - if (0 == FileMgr.ReadSdFile (PlayItemName, FileData)) + if (0 == FileMgr.ReadSdFile (FileControl[CurrentFile].FileName, FileData)) { - logcon (String (F ("Could not read Playlist file: '")) + PlayItemName + "'"); + logcon (String (F ("Could not read Playlist file: '")) + FileControl[CurrentFile].FileName + "'"); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, 1); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, 1); break; } // DEBUG_V (""); @@ -133,12 +147,12 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () // DEBUG_V ("Error Check"); if (error) { - String CfgFileMessagePrefix = String (F ("SD file: '")) + PlayItemName + "' "; + String CfgFileMessagePrefix = String (F ("SD file: '")) + FileControl[CurrentFile].FileName + "' "; logcon (CN_Heap_colon + String (ESP.getFreeHeap ())); logcon (CfgFileMessagePrefix + String (F ("Deserialzation Error. Error code = ")) + error.c_str ()); logcon (String (F ("++++")) + FileData + String (F ("----"))); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); break; } @@ -164,7 +178,7 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () PauseDelayTimer.StartTimer(1000, false); fsm_PlayList_state_Paused_imp.Init (this); - pCurrentFsmState->Start (PlayItemName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); + pCurrentFsmState->Start (FileControl[CurrentFile].FileName, PauseDelayTimer.GetTimeRemaining() / 1000, PlayCount); break; } @@ -192,7 +206,7 @@ bool c_InputFPPRemotePlayList::ProcessPlayListEntry () else if (String (CN_effect) == PlayListEntryType) { - JsonObject EffectConfig = JsonPlayListArrayEntry[CN_config]; + JsonObject EffectConfig = JsonPlayListArrayEntry[(char*)CN_config].to(); serializeJson (EffectConfig, PlayListEntryName); FrameId = 10; diff --git a/src/input/InputFPPRemotePlayListFsm.cpp b/src/input/InputFPPRemotePlayListFsm.cpp index d16a5f70c..aeb4401d4 100644 --- a/src/input/InputFPPRemotePlayListFsm.cpp +++ b/src/input/InputFPPRemotePlayListFsm.cpp @@ -25,7 +25,7 @@ #include "input/InputFPPRemotePlayEffect.hpp" //----------------------------------------------------------------------------- -bool fsm_PlayList_state_WaitForStart::Poll (bool /* StayDark */) +bool fsm_PlayList_state_WaitForStart::Poll () { // DEBUG_START; @@ -55,13 +55,13 @@ void fsm_PlayList_state_WaitForStart::Start (String & FileName, float, uint32_t) do // once { - pInputFPPRemotePlayList->PlayItemName = FileName; + pInputFPPRemotePlayList->FileControl[CurrentFile].FileName = FileName; pInputFPPRemotePlayList->PlayListEntryId = 0; // DEBUG_V (String ("PlayItemName: '") + pInputFPPRemotePlayList->PlayItemName + "'"); pInputFPPRemotePlayList->fsm_PlayList_state_Idle_imp.Init (pInputFPPRemotePlayList); - + } while (false); // DEBUG_END; @@ -84,7 +84,7 @@ void fsm_PlayList_state_WaitForStart::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - // JsonObject FileStatus = jsonStatus[CN_Idle].to (); + // JsonObject FileStatus = jsonStatus[(char*)CN_Idle].to (); // DEBUG_END; @@ -94,7 +94,7 @@ void fsm_PlayList_state_WaitForStart::GetStatus (JsonObject& jsonStatus) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayList_state_Idle::Poll (bool /* StayDark */) +bool fsm_PlayList_state_Idle::Poll () { // DEBUG_START; @@ -144,7 +144,7 @@ void fsm_PlayList_state_Idle::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - // JsonObject FileStatus = jsonStatus[CN_Idle].to (); + // JsonObject FileStatus = jsonStatus[(char*)CN_Idle].to (); // DEBUG_END; @@ -153,11 +153,11 @@ void fsm_PlayList_state_Idle::GetStatus (JsonObject& jsonStatus) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayList_state_PlayingFile::Poll (bool StayDark) +bool fsm_PlayList_state_PlayingFile::Poll () { // xDEBUG_START; - bool Response = pInputFPPRemotePlayList->pInputFPPRemotePlayItem->Poll (StayDark); + bool Response = pInputFPPRemotePlayList->pInputFPPRemotePlayItem->Poll (); if (pInputFPPRemotePlayList->pInputFPPRemotePlayItem->IsIdle ()) { @@ -220,7 +220,7 @@ void fsm_PlayList_state_PlayingFile::GetStatus (JsonObject& jsonStatus) jsonStatus[F ("repeat")] = pInputFPPRemotePlayList->pInputFPPRemotePlayItem->GetRepeatCount (); - JsonObject FileStatus = jsonStatus[CN_File].to (); + JsonObject FileStatus = jsonStatus[(char*)CN_File].to (); pInputFPPRemotePlayList->pInputFPPRemotePlayItem->GetStatus (FileStatus); // DEBUG_END; @@ -230,11 +230,11 @@ void fsm_PlayList_state_PlayingFile::GetStatus (JsonObject& jsonStatus) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayList_state_PlayingEffect::Poll (bool StayDark) +bool fsm_PlayList_state_PlayingEffect::Poll () { // DEBUG_START; - pInputFPPRemotePlayList->pInputFPPRemotePlayItem->Poll (StayDark); + pInputFPPRemotePlayList->pInputFPPRemotePlayItem->Poll (); if (pInputFPPRemotePlayList->pInputFPPRemotePlayItem->IsIdle ()) { @@ -299,7 +299,7 @@ void fsm_PlayList_state_PlayingEffect::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - JsonObject EffectStatus = jsonStatus[CN_Effect].to (); + JsonObject EffectStatus = jsonStatus[(char*)CN_Effect].to (); pInputFPPRemotePlayList->pInputFPPRemotePlayItem->GetStatus (EffectStatus); // DEBUG_END; @@ -309,7 +309,7 @@ void fsm_PlayList_state_PlayingEffect::GetStatus (JsonObject& jsonStatus) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -bool fsm_PlayList_state_Paused::Poll (bool /* StayDark */) +bool fsm_PlayList_state_Paused::Poll () { // DEBUG_START; @@ -363,7 +363,7 @@ void fsm_PlayList_state_Paused::GetStatus (JsonObject& jsonStatus) { // DEBUG_START; - JsonObject PauseStatus = jsonStatus[CN_Paused].to (); + JsonObject PauseStatus = jsonStatus[(char*)CN_Paused].to (); time_t SecondsRemaining = pInputFPPRemotePlayList->PauseDelayTimer.GetTimeRemaining() / 1000u; diff --git a/src/input/InputMQTT.cpp b/src/input/InputMQTT.cpp index 1e14dbc8f..f960d7049 100644 --- a/src/input/InputMQTT.cpp +++ b/src/input/InputMQTT.cpp @@ -123,19 +123,19 @@ void c_InputMQTT::GetConfig (JsonObject & jsonConfig) // DEBUG_START; // Serialize Config - jsonConfig[CN_ip] = ip; - jsonConfig[CN_port] = port; - jsonConfig[CN_user] = user; - jsonConfig[CN_password] = password; - jsonConfig[CN_topic] = topic; + JsonWrite(jsonConfig, CN_ip, ip); + JsonWrite(jsonConfig, CN_port, port); + JsonWrite(jsonConfig, CN_user, user); + JsonWrite(jsonConfig, CN_password, password); + JsonWrite(jsonConfig, CN_topic, topic); #ifdef SUPPORT_SENSOR_DS18B20 - jsonConfig[CN_tsensortopic] = TemperatureSensorTopic; + JsonWrite(jsonConfig, CN_tsensortopic, TemperatureSensorTopic); #endif // def SUPPORT_SENSOR_DS18B20 - jsonConfig[CN_clean] = CleanSessionRequired; - jsonConfig[CN_hadisco] = hadisco; - jsonConfig[CN_haprefix] = haprefix; - jsonConfig[CN_effects] = true; - jsonConfig[CN_play] = true; + JsonWrite(jsonConfig, CN_clean, CleanSessionRequired); + JsonWrite(jsonConfig, CN_hadisco, hadisco); + JsonWrite(jsonConfig, CN_haprefix, haprefix); + JsonWrite(jsonConfig, CN_effects, true); + JsonWrite(jsonConfig, CN_play, true); // DEBUG_END; @@ -147,14 +147,14 @@ void c_InputMQTT::GetStatus (JsonObject & jsonStatus) // DEBUG_START; JsonObject Status = jsonStatus[F ("mqtt")].to (); - Status[CN_id] = InputChannelId; + JsonWrite(Status, CN_id, InputChannelId); // DEBUG_END; } // GetStatus //----------------------------------------------------------------------------- -void c_InputMQTT::Process (bool StayDark) +void c_InputMQTT::Process () { // DEBUG_START; @@ -163,12 +163,12 @@ void c_InputMQTT::Process (bool StayDark) if (nullptr != pEffectsEngine) { // DEBUG_V (""); - pEffectsEngine->Process (StayDark); + pEffectsEngine->Process (); } else if (nullptr != pPlayFileEngine) { - pPlayFileEngine->Poll (StayDark); + pPlayFileEngine->Poll (); } else { @@ -614,29 +614,31 @@ void c_InputMQTT::GetEngineConfig (JsonObject & JsonConfig) { // DEBUG_V ("Effects engine running"); ((c_InputEffectEngine*)(pEffectsEngine))->GetMqttConfig (effectConfig); - } else { + } + else + { // DEBUG_V ("Effects engine not running"); } - JsonConfig[CN_effect] = effectConfig.effect; - JsonConfig[CN_mirror] = effectConfig.mirror; - JsonConfig[CN_allleds] = effectConfig.allLeds; - JsonConfig[CN_brightness] = effectConfig.brightness; - JsonConfig[CN_EffectWhiteChannel] = effectConfig.whiteChannel; + JsonWrite(JsonConfig, CN_effect, effectConfig.effect); + JsonWrite(JsonConfig, CN_mirror, effectConfig.mirror); + JsonWrite(JsonConfig, CN_allleds, effectConfig.allLeds); + JsonWrite(JsonConfig, CN_brightness, effectConfig.brightness); + JsonWrite(JsonConfig, CN_EffectWhiteChannel, effectConfig.whiteChannel); - JsonObject color = JsonConfig[CN_color].to (); - color[CN_r] = effectConfig.color.r; - color[CN_g] = effectConfig.color.g; - color[CN_b] = effectConfig.color.b; + JsonObject color = JsonConfig[(char*)CN_color].to (); + JsonWrite(color, CN_r, effectConfig.color.r); + JsonWrite(color, CN_g, effectConfig.color.g); + JsonWrite(color, CN_b, effectConfig.color.b); if (nullptr != pPlayFileEngine) { - JsonConfig[CN_effect] = CN_playFseq; - JsonConfig[CN_filename] = pPlayFileEngine->GetFileName (); + JsonWrite(JsonConfig, CN_effect, String(CN_playFseq)); + JsonWrite(JsonConfig, CN_filename, pPlayFileEngine->GetFileName ()); } else { - JsonConfig[CN_filename] = String (""); + JsonWrite(JsonConfig, CN_filename, emptyString); } // DEBUG_END; @@ -658,9 +660,9 @@ void c_InputMQTT::GetEffectList (JsonObject & JsonConfig) } // DEBUG_V (""); - JsonConfig[CN_brightness] = CN_true; + JsonWrite(JsonConfig, CN_brightness, String(CN_true)); ((c_InputEffectEngine*)(pEffectsEngine))->GetMqttEffectList (JsonConfig); - JsonConfig[CN_effect] = CN_true; + JsonWrite(JsonConfig, CN_effect, String(CN_true)); if (!EffectEngineIsRunning) { @@ -668,7 +670,7 @@ void c_InputMQTT::GetEffectList (JsonObject & JsonConfig) pEffectsEngine = nullptr; } - JsonConfig[CN_effect_list].add (CN_playFseq); + JsonConfig[(char*)CN_effect_list].add ((char*)CN_playFseq); // add the file play fields. // DEBUG_END; @@ -697,29 +699,29 @@ void c_InputMQTT::publishHA() JsonDocument root; JsonObject JsonConfig = root.to (); - JsonConfig[F ("platform")] = F ("MQTT"); - JsonConfig[CN_name] = config.id; - JsonConfig[F ("schema")] = F ("json"); - JsonConfig[F ("state_topic")] = topic; - JsonConfig[F ("command_topic")] = lwtTopic; - JsonConfig[F ("availability_topic")] = lwtTopic; - JsonConfig[F ("rgb")] = CN_true; + JsonWrite(JsonConfig, F ("platform"), F ("MQTT")); + JsonWrite(JsonConfig, CN_name, config.id); + JsonWrite(JsonConfig, F ("schema"), F ("json")); + JsonWrite(JsonConfig, F ("state_topic"), topic); + JsonWrite(JsonConfig, F ("command_topic"), lwtTopic); + JsonWrite(JsonConfig, F ("availability_topic"), lwtTopic); + JsonWrite(JsonConfig, F ("rgb"), String(CN_true)); GetEffectList (JsonConfig); // Register the attributes topic - JsonConfig[F ("json_attributes_topic")] = topic + F ("/attributes"); + JsonWrite(JsonConfig, F ("json_attributes_topic"), topic + F ("/attributes")); // Create a unique id using the chip id, and fill in the device properties // to enable integration support in HomeAssistant. - JsonConfig[F ("unique_id")] = CN_ESPixelStick + chipId; + JsonWrite(JsonConfig, F ("unique_id"), CN_ESPixelStick + chipId); - JsonObject device = JsonConfig[CN_device].to (); - device[F ("identifiers")] = WiFi.macAddress (); - device[F ("manufacturer")] = F ("Forkineye"); - device[F ("model")] = CN_ESPixelStick; - device[CN_name] = config.id; - device[F ("sw_version")] = String (CN_ESPixelStick) + " v" + VERSION; + JsonObject device = JsonConfig[(char*)CN_device].to (); + JsonWrite(device, F ("identifiers"), WiFi.macAddress ()); + JsonWrite(device, F ("manufacturer"), F ("Forkineye")); + JsonWrite(device, F ("model"), String(CN_ESPixelStick)); + JsonWrite(device, CN_name, config.id); + JsonWrite(device, F ("sw_version"), String (CN_ESPixelStick) + " v" + VERSION); String HaJsonConfig; serializeJson(JsonConfig, HaJsonConfig); @@ -745,7 +747,7 @@ void c_InputMQTT::publishState() JsonDocument root; JsonObject JsonConfig = root[F ("MQTT")].to(); - JsonConfig[CN_state] = (true == stateOn) ? String(ON) : String(OFF); + JsonWrite(JsonConfig, CN_state, String((true == stateOn) ? ON : OFF)); // populate the effect information GetEngineConfig (JsonConfig); @@ -803,7 +805,7 @@ void c_InputMQTT::UpdateEffectConfiguration (JsonObject & JsonConfig) setFromJSON (effectConfig.brightness, JsonConfig, CN_brightness); setFromJSON (effectConfig.whiteChannel, JsonConfig, CN_EffectWhiteChannel); - JsonObject JsonColor = JsonConfig[CN_color]; + JsonObject JsonColor = JsonConfig[(char*)CN_color].to(); if (JsonColor) { setFromJSON (effectConfig.color.r, JsonColor, CN_r); diff --git a/src/input/InputMgr.cpp b/src/input/InputMgr.cpp index 312f6732c..4972e8feb 100644 --- a/src/input/InputMgr.cpp +++ b/src/input/InputMgr.cpp @@ -36,8 +36,6 @@ // needs to be last #include "input/InputMgr.hpp" -//----------------------------------------------------------------------------- - //----------------------------------------------------------------------------- // Local Data definitions //----------------------------------------------------------------------------- @@ -62,6 +60,53 @@ static const InputTypeXlateMap_t InputTypeXlateMap[c_InputMgr::e_InputType::Inpu {c_InputMgr::e_InputType::InputType_Disabled, "Disabled", c_InputMgr::e_InputChannelIds::InputChannelId_ALL} }; +uint32_t DeltaTime = 0; + +#if defined ARDUINO_ARCH_ESP32 +# include + +static TaskHandle_t PollTaskHandle = NULL; +//---------------------------------------------------------------------------- +void InputMgrTask (void *arg) +{ + // DEBUG_V(String("Current CPU ID: ") + String(xPortGetCoreID())); + // DEBUG_V(String("Current Task Priority: ") + String(uxTaskPriorityGet(NULL))); + uint32_t PollStartTime = millis(); + uint32_t PollEndTime = PollStartTime; + uint32_t PollTime = pdMS_TO_TICKS(25); + const uint32_t MinPollTimeMs = 25; + + while(1) + { + DeltaTime = PollEndTime - PollStartTime; + + if (DeltaTime < MinPollTimeMs) + { + PollTime = pdMS_TO_TICKS(MinPollTimeMs - DeltaTime); + vTaskDelay(PollTime); + } + else + { + // DEBUG_V(String("handle time wrap and long frames. DeltaTime:") + String(DeltaTime)); + } + FeedWDT(); + + PollStartTime = millis(); + + InputMgr.Process(); + FeedWDT(); + + // record the loop end time + PollEndTime = millis(); + } +} // InputMgrTask +#else +void TimerPollHandler() +{ + InputMgr.Process(); +} +#endif // def ARDUINO_ARCH_ESP32 + //----------------------------------------------------------------------------- // Methods //----------------------------------------------------------------------------- @@ -89,6 +134,15 @@ c_InputMgr::~c_InputMgr () { // DEBUG_START; +#ifdef ARDUINO_ARCH_ESP32 + if(PollTaskHandle) + { + logcon("Stop Input Task"); + vTaskDelete(PollTaskHandle); + PollTaskHandle = NULL; + } +#endif // def ARDUINO_ARCH_ESP32 + // delete pInputInstances; int pInputChannelDriversIndex = 0; for (auto & CurrentInput : InputChannelDrivers) @@ -111,6 +165,8 @@ void c_InputMgr::Begin (uint32_t BufferSize) { // DEBUG_START; + // DEBUG_V(String("Current CPU ID: ") + String(xPortGetCoreID())); + InputDataBufferSize = BufferSize; // DEBUG_V (String("InputDataBufferSize: ") + String (InputDataBufferSize)); @@ -126,13 +182,20 @@ void c_InputMgr::Begin (uint32_t BufferSize) InstantiateNewInputChannel(e_InputChannelIds(CurrentInput.DriverId), e_InputType::InputType_Disabled); // DEBUG_V (""); } - HasBeenInitialized = true; // load up the configuration from the saved file. This also starts the drivers LoadConfig (); // CreateNewConfig(); +#if defined ARDUINO_ARCH_ESP32 + xTaskCreatePinnedToCore(InputMgrTask, "InputMgrTask", 4096, NULL, INPUTMGR_TASK_PRIORITY, &PollTaskHandle, 1); +#else + MsTicker.attach_ms (uint32_t (FPP_TICKER_PERIOD_MS), &TimerPollHandler); // Add Timer Function +#endif // ! defined ARDUINO_ARCH_ESP32 + + HasBeenInitialized = true; + // DEBUG_END; } // begin @@ -161,12 +224,12 @@ void c_InputMgr::CreateJsonConfig (JsonObject & jsonConfig) // DEBUG_V (""); // add the channels header - JsonObject InputMgrChannelsData = jsonConfig[CN_channels]; + JsonObject InputMgrChannelsData = jsonConfig[(char*)CN_channels]; if (!InputMgrChannelsData) { // add our section header // DEBUG_V (""); - InputMgrChannelsData = jsonConfig[CN_channels].to (); + InputMgrChannelsData = jsonConfig[(char*)CN_channels].to (); } // add the channel configurations @@ -191,7 +254,7 @@ void c_InputMgr::CreateJsonConfig (JsonObject & jsonConfig) } // save the name as the selected channel type - ChannelConfigData[CN_type] = int (CurrentChannel.pInputChannelDriver->GetInputType ()); + JsonWrite(ChannelConfigData, CN_type, int (CurrentChannel.pInputChannelDriver->GetInputType ())); String DriverTypeId = String (int (CurrentChannel.pInputChannelDriver->GetInputType ())); JsonObject ChannelConfigByTypeData = ChannelConfigData[(String (DriverTypeId))]; @@ -207,7 +270,7 @@ void c_InputMgr::CreateJsonConfig (JsonObject & jsonConfig) // Populate the driver name String DriverName = ""; CurrentChannel.pInputChannelDriver->GetDriverName (DriverName); - ChannelConfigByTypeData[CN_type] = DriverName; + JsonWrite(ChannelConfigByTypeData, CN_type, DriverName); CurrentChannel.pInputChannelDriver->GetConfig (ChannelConfigByTypeData); // DEBUG_V (""); @@ -237,10 +300,10 @@ void c_InputMgr::CreateNewConfig () JsonDocument JsonConfigDoc; // DEBUG_V(""); - JsonObject JsonConfig = JsonConfigDoc[CN_input_config].to(); + JsonObject JsonConfig = JsonConfigDoc[(char*)CN_input_config].to(); // DEBUG_V(""); - JsonConfig[CN_cfgver] = CurrentConfigVersion; + JsonWrite(JsonConfig, CN_cfgver, CurrentConfigVersion); // DEBUG_V ("for each Input type"); for (int InputTypeId = int (InputType_Start); @@ -631,13 +694,13 @@ void c_InputMgr::Process () do // once { - if (configInProgress) + if (configInProgress || PauseProcessing) { // prevent calls to process when we are doing a long operation break; } - ExternalInput.Poll (false); + ExternalInput.Poll (); if (NO_CONFIG_NEEDED != ConfigLoadNeeded) { @@ -657,12 +720,12 @@ void c_InputMgr::Process () bool aBlankTimerIsRunning = false; for (auto & CurrentInput : InputChannelDrivers) { - if(nullptr == CurrentInput.pInputChannelDriver) + if(nullptr == CurrentInput.pInputChannelDriver || aBlankTimerIsRunning) { continue; } // DEBUG_V(String("pInputChannelDriver: 0x") + String(uint32_t(CurrentInput.pInputChannelDriver), HEX)); - CurrentInput.pInputChannelDriver->Process (aBlankTimerIsRunning); + CurrentInput.pInputChannelDriver->Process (); if (!BlankTimerHasExpired (CurrentInput.pInputChannelDriver->GetInputChannelId())) { @@ -721,7 +784,7 @@ bool c_InputMgr::FindJsonChannelConfig (JsonObject& jsonConfig, do // once { - JsonObject InputChannelMgrData = jsonConfig[CN_input_config]; + JsonObject InputChannelMgrData = jsonConfig[(char*)CN_input_config]; if (!InputChannelMgrData) { logcon (String (F ("No Input Interface Settings Found. Using Defaults"))); @@ -756,7 +819,7 @@ bool c_InputMgr::FindJsonChannelConfig (JsonObject& jsonConfig, } // do we have a channel configuration array? - JsonObject InputChannelArray = InputChannelMgrData[CN_channels]; + JsonObject InputChannelArray = InputChannelMgrData[(char*)CN_channels]; if (!InputChannelArray) { // if not, flag an error and stop processing @@ -952,6 +1015,8 @@ void c_InputMgr::SetOperationalState (bool ActiveFlag) // DEBUG_START; // DEBUG_V(String("ActiveFlag: ") + String(ActiveFlag)); + PauseProcessing = !ActiveFlag; + // pass through each active interface and set the active state for (auto & InputChannel : InputChannelDrivers) { diff --git a/src/input/externalInput.cpp b/src/input/externalInput.cpp index d23644fe4..b9c018b08 100644 --- a/src/input/externalInput.cpp +++ b/src/input/externalInput.cpp @@ -68,12 +68,12 @@ void c_ExternalInput::GetConfig (JsonObject JsonData) { // DEBUG_START; - JsonData[CN_enabled] = Enabled; - JsonData[CN_name] = name; - JsonData[CN_id] = GpioId; - JsonData[CN_polarity] = (ActiveHigh == polarity) ? CN_ActiveHigh : CN_ActiveLow; - JsonData[CN_channels] = TriggerChannel; - JsonData[CN_long] = LongPushDelayMS; + JsonWrite(JsonData, CN_enabled, Enabled); + JsonWrite(JsonData, CN_name, name); + JsonWrite(JsonData, CN_id, GpioId); + JsonWrite(JsonData, CN_polarity, String((ActiveHigh == polarity) ? CN_ActiveHigh : CN_ActiveLow)); + JsonWrite(JsonData, CN_channels, TriggerChannel); + JsonWrite(JsonData, CN_long, LongPushDelayMS); // DEBUG_V (String ("m_iPinId: ") + String (m_iPinId)); @@ -86,8 +86,8 @@ void c_ExternalInput::GetStatistics (JsonObject JsonData) { // DEBUG_START; - JsonData[CN_id] = GpioId; - JsonData[CN_state] = (ReadInput()) ? CN_on : CN_off; + JsonWrite(JsonData, CN_id, GpioId); + JsonWrite(JsonData, CN_state, String((ReadInput()) ? CN_on : CN_off)); // DEBUG_END; @@ -125,7 +125,7 @@ void c_ExternalInput::ProcessConfig (JsonObject JsonData) } // ProcessConfig /*****************************************************************************/ -void c_ExternalInput::Poll (bool StayDark) +void c_ExternalInput::Poll () { // DEBUG_START; diff --git a/src/main.cpp b/src/main.cpp index 1ae0a1559..f18fb0282 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,7 @@ * ESPixelStick.ino * * Project: ESPixelStick - An ESP8266 / ESP32 and E1.31 based pixel driver -* Copyright (c) 2016, 2022 Shelby Merrick +* Copyright (c) 2016, 2025 Shelby Merrick * http://www.forkineye.com * * This program is provided free for you to use in any way that you wish, @@ -261,7 +261,7 @@ bool dsDevice(JsonObject & json) // PrettyPrint (json, "dsDevice"); bool ConfigChanged = false; - JsonObject JsonDeviceConfig = json[CN_device]; + JsonObject JsonDeviceConfig = json[(char*)CN_device]; if (JsonDeviceConfig) { // PrettyPrint(JsonDeviceConfig, "device"); @@ -304,9 +304,9 @@ bool deserializeCore (JsonObject & json) bool DataHasBeenAccepted = false; // PrettyPrint (json, "Main Config"); - JsonObject SystemConfig = json[CN_system]; - JsonObject InitConfig = json[CN_init]; - JsonObject NetworkConfig = json[CN_network]; + JsonObject SystemConfig = json[(char*)CN_system]; + JsonObject InitConfig = json[(char*)CN_init]; + JsonObject NetworkConfig = json[(char*)CN_network]; JsonObject DeviceConfig; do // once @@ -315,7 +315,7 @@ bool deserializeCore (JsonObject & json) if (SystemConfig) { // DEBUG_V("Detected a System Config"); - DeviceConfig = json[CN_system]; + DeviceConfig = json[(char*)CN_system]; // PrettyPrint (DeviceConfig, "System based DeviceConfig"); } // is this an initial config from the flash tool? @@ -399,7 +399,7 @@ void SaveConfig() // Create buffer and root object JsonDocument jsonConfigDoc; - JsonObject JsonConfig = jsonConfigDoc[CN_system].to(); + JsonObject JsonConfig = jsonConfigDoc[(char*)CN_system].to(); GetConfig(JsonConfig); @@ -441,12 +441,12 @@ void GetConfig (JsonObject & json) // DEBUG_START; // Config Version - json[CN_cfgver] = CurrentConfigVersion; + json[(char*)CN_cfgver] = CurrentConfigVersion; // Device - JsonObject device = json[CN_device].to(); - device[CN_id] = config.id; - device[CN_blanktime] = config.BlankDelay; + JsonObject device = json[(char*)CN_device].to(); + JsonWrite(device, CN_id, config.id); + JsonWrite(device, CN_blanktime, config.BlankDelay); // PrettyPrint(device, "device"); @@ -513,9 +513,6 @@ void loop() // Keep the Network Open NetworkMgr.Poll (); - // Process input data - InputMgr.Process (); - // Poll output OutputMgr.Poll(); diff --git a/src/network/EthernetDriver.cpp b/src/network/EthernetDriver.cpp index d8910ab3c..e11f31437 100644 --- a/src/network/EthernetDriver.cpp +++ b/src/network/EthernetDriver.cpp @@ -128,21 +128,21 @@ void c_EthernetDriver::GetConfig (JsonObject& json) { // DEBUG_START; - json[CN_ip] = ip.toString (); - json[CN_netmask] = netmask.toString (); - json[CN_gateway] = gateway.toString (); - json[CN_dnsp] = primaryDns.toString (); - json[CN_dnss] = secondaryDns.toString (); - json[CN_dhcp] = UseDhcp; - - json[CN_type] = phy_type; - json[CN_addr] = phy_addr; - json[CN_power_pin] = power_pin; - json[CN_mode] = clk_mode; - json[CN_mdc_pin] = mdc_pin; - json[CN_mdio_pin] = mdio_pin; - json[CN_activevalue] = powerPinActiveValue; - json[CN_activedelay] = powerPinActiveDelayMs; + JsonWrite(json, CN_ip, ip.toString ()); + JsonWrite(json, CN_netmask, netmask.toString ()); + JsonWrite(json, CN_gateway, gateway.toString ()); + JsonWrite(json, CN_dnsp, primaryDns.toString ()); + JsonWrite(json, CN_dnss, secondaryDns.toString ()); + JsonWrite(json, CN_dhcp, UseDhcp); + + JsonWrite(json, CN_type, phy_type); + JsonWrite(json, CN_addr, phy_addr); + JsonWrite(json, CN_power_pin, power_pin); + JsonWrite(json, CN_mode, clk_mode); + JsonWrite(json, CN_mdc_pin, mdc_pin); + JsonWrite(json, CN_mdio_pin, mdio_pin); + JsonWrite(json, CN_activevalue, powerPinActiveValue); + JsonWrite(json, CN_activedelay, powerPinActiveDelayMs); // DEBUG_END; @@ -185,14 +185,12 @@ void c_EthernetDriver::GetStatus (JsonObject& jsonStatus) String Hostname; GetHostname (Hostname); - jsonStatus[CN_hostname] = Hostname; - - jsonStatus[CN_ip] = GetIpAddress ().toString (); - jsonStatus[CN_subnet] = GetIpSubNetMask ().toString (); - jsonStatus[CN_mac] = GetMacAddress (); - jsonStatus[CN_gateway] = GetIpGateway (); - - jsonStatus[CN_connected] = IsConnected (); + JsonWrite(jsonStatus, CN_hostname, Hostname); + JsonWrite(jsonStatus, CN_ip, GetIpAddress ().toString ()); + JsonWrite(jsonStatus, CN_subnet, GetIpSubNetMask ().toString ()); + JsonWrite(jsonStatus, CN_mac, GetMacAddress ()); + JsonWrite(jsonStatus, CN_gateway, GetIpGateway ()); + JsonWrite(jsonStatus, CN_connected, IsConnected ()); // DEBUG_END; } // GetStatus diff --git a/src/network/NetworkMgr.cpp b/src/network/NetworkMgr.cpp index ddfcbb702..68804c42b 100644 --- a/src/network/NetworkMgr.cpp +++ b/src/network/NetworkMgr.cpp @@ -92,17 +92,17 @@ void c_NetworkMgr::GetConfig (JsonObject & json) { // DEBUG_START; - JsonObject NetworkConfig = json[CN_network].to (); + JsonObject NetworkConfig = json[(char*)CN_network].to (); - NetworkConfig[CN_hostname] = hostname; + JsonWrite(NetworkConfig, CN_hostname, hostname); - JsonObject NetworkWiFiConfig = NetworkConfig[CN_wifi].to (); + JsonObject NetworkWiFiConfig = NetworkConfig[(char*)CN_wifi].to (); WiFiDriver.GetConfig (NetworkWiFiConfig); #ifdef SUPPORT_ETHERNET - NetworkConfig[CN_weus] = AllowWiFiAndEthUpSimultaneously; + JsonWrite(NetworkConfig, CN_weus, AllowWiFiAndEthUpSimultaneously); - JsonObject NetworkEthConfig = NetworkConfig[CN_eth].to (); + JsonObject NetworkEthConfig = NetworkConfig[(char*)CN_eth].to (); EthernetDriver.GetConfig (NetworkEthConfig); #endif // def SUPPORT_ETHERNET @@ -121,16 +121,16 @@ void c_NetworkMgr::GetStatus (JsonObject & json) { // DEBUG_START; - JsonObject NetworkStatus = json[CN_network].to (); + JsonObject NetworkStatus = json[(char*)CN_network].to (); String name; GetHostname (name); - NetworkStatus[CN_hostname] = name; + JsonWrite(NetworkStatus, CN_hostname, name); - JsonObject NetworkWiFiStatus = NetworkStatus[CN_wifi].to (); + JsonObject NetworkWiFiStatus = NetworkStatus[(char*)CN_wifi].to (); WiFiDriver.GetStatus (NetworkWiFiStatus); #ifdef SUPPORT_ETHERNET - JsonObject NetworkEthStatus = NetworkStatus[CN_eth].to (); + JsonObject NetworkEthStatus = NetworkStatus[(char*)CN_eth].to (); EthernetDriver.GetStatus (NetworkEthStatus); #endif // def SUPPORT_ETHERNET @@ -165,7 +165,7 @@ bool c_NetworkMgr::SetConfig (JsonObject & json) do // once { - JsonObject network = json[CN_network]; + JsonObject network = json[(char*)CN_network]; if (!network) { logcon (String (F ("No network config found. Use default settings"))); @@ -178,7 +178,7 @@ bool c_NetworkMgr::SetConfig (JsonObject & json) HostnameChanged = setFromJSON (hostname, network, CN_hostname); // DEBUG_V(""); - JsonObject networkWiFi = network[CN_wifi]; + JsonObject networkWiFi = network[(char*)CN_wifi]; if (networkWiFi) { // DEBUG_V(""); @@ -187,7 +187,7 @@ bool c_NetworkMgr::SetConfig (JsonObject & json) else { // DEBUG_V(""); - JsonObject ssid = network[CN_ssid]; + JsonObject ssid = network[(char*)CN_ssid]; // this may be an old style config if (!ssid) { @@ -205,7 +205,7 @@ bool c_NetworkMgr::SetConfig (JsonObject & json) #ifdef SUPPORT_ETHERNET ConfigChanged = setFromJSON (AllowWiFiAndEthUpSimultaneously, network, CN_weus); - JsonObject networkEth = network[CN_eth]; + JsonObject networkEth = network[(char*)CN_eth]; if (networkEth) { ConfigChanged |= EthernetDriver.SetConfig (networkEth); diff --git a/src/network/WiFiDriver.cpp b/src/network/WiFiDriver.cpp index a1a10ce8d..57dc3dba0 100644 --- a/src/network/WiFiDriver.cpp +++ b/src/network/WiFiDriver.cpp @@ -312,37 +312,37 @@ void c_WiFiDriver::GetConfig (JsonObject& json) { // DEBUG_START; - json[CN_ssid] = ssid; - json[CN_passphrase] = passphrase; - json[CN_ap_ssid] = ap_ssid; - json[CN_ap_passphrase] = ap_passphrase; + JsonWrite(json, CN_ssid, ssid); + JsonWrite(json, CN_passphrase, passphrase); + JsonWrite(json, CN_ap_ssid, ap_ssid); + JsonWrite(json, CN_ap_passphrase, ap_passphrase); #ifdef ARDUINO_ARCH_ESP8266 IPAddress Temp = ip; - json[CN_ip] = Temp.toString (); + JsonWrite(json, CN_ip, Temp.toString ()); Temp = netmask; - json[CN_netmask] = Temp.toString (); + JsonWrite(json, CN_netmask, Temp.toString ()); Temp = gateway; - json[CN_gateway] = Temp.toString (); + JsonWrite(json, CN_gateway, Temp.toString ()); Temp = primaryDns; - json[CN_dnsp] = Temp.toString (); + JsonWrite(json, CN_dnsp, Temp.toString ()); Temp = secondaryDns; - json[CN_dnss] = Temp.toString (); + JsonWrite(json, CN_dnss, Temp.toString ()); #else - json[CN_ip] = ip.toString (); - json[CN_netmask] = netmask.toString (); - json[CN_gateway] = gateway.toString (); - json[CN_dnsp] = primaryDns.toString (); - json[CN_dnss] = secondaryDns.toString (); + JsonWrite(json, CN_ip, ip.toString ()); + JsonWrite(json, CN_netmask, netmask.toString ()); + JsonWrite(json, CN_gateway, gateway.toString ()); + JsonWrite(json, CN_dnsp, primaryDns.toString ()); + JsonWrite(json, CN_dnss, secondaryDns.toString ()); #endif // !def ARDUINO_ARCH_ESP8266 - json[CN_StayInApMode] = StayInApMode; - json[CN_dhcp] = UseDhcp; - json[CN_sta_timeout] = sta_timeout; - json[CN_ap_channel] = ap_channelNumber; - json[CN_ap_fallback] = ap_fallbackIsEnabled; - json[CN_ap_timeout] = ap_timeout; - json[CN_ap_reboot] = RebootOnWiFiFailureToConnect; + JsonWrite(json, CN_StayInApMode, StayInApMode); + JsonWrite(json, CN_dhcp, UseDhcp); + JsonWrite(json, CN_sta_timeout, sta_timeout); + JsonWrite(json, CN_ap_channel, ap_channelNumber); + JsonWrite(json, CN_ap_fallback, ap_fallbackIsEnabled); + JsonWrite(json, CN_ap_timeout, ap_timeout); + JsonWrite(json, CN_ap_reboot, RebootOnWiFiFailureToConnect); // DEBUG_END; @@ -365,14 +365,13 @@ void c_WiFiDriver::GetStatus (JsonObject& jsonStatus) // DEBUG_START; String Hostname; GetHostname (Hostname); - jsonStatus[CN_hostname] = Hostname; - - jsonStatus[CN_rssi] = WiFi.RSSI (); - jsonStatus[CN_ip] = getIpAddress ().toString (); - jsonStatus[CN_subnet] = getIpSubNetMask ().toString (); - jsonStatus[CN_mac] = WiFi.macAddress (); - jsonStatus[CN_ssid] = WiFi.SSID (); - jsonStatus[CN_connected] = IsWiFiConnected (); + JsonWrite(jsonStatus, CN_hostname, Hostname); + JsonWrite(jsonStatus, CN_rssi, WiFi.RSSI ()); + JsonWrite(jsonStatus, CN_ip, getIpAddress ().toString ()); + JsonWrite(jsonStatus, CN_subnet, getIpSubNetMask ().toString ()); + JsonWrite(jsonStatus, CN_mac, WiFi.macAddress ()); + JsonWrite(jsonStatus, CN_ssid, WiFi.SSID ()); + JsonWrite(jsonStatus, CN_connected, IsWiFiConnected ()); // DEBUG_END; } // GetStatus diff --git a/src/output/OutputCommon.cpp b/src/output/OutputCommon.cpp index 1c8c5d2c2..8870a75f7 100644 --- a/src/output/OutputCommon.cpp +++ b/src/output/OutputCommon.cpp @@ -69,17 +69,9 @@ void c_OutputCommon::BaseGetStatus (JsonObject & jsonStatus) { // DEBUG_START; - jsonStatus[CN_id] = OutputChannelId; - jsonStatus["framerefreshrate"] = int(MicroSecondsInASecond / FrameDurationInMicroSec); - jsonStatus["FrameCount"] = FrameCount; - - // jsonStatus["ActualFrameDurationMicroSec"] = ActualFrameDurationMicroSec; - // jsonStatus["FrameDurationInMicroSec"] = FrameDurationInMicroSec; - // jsonStatus["FrameRefreshTimeInMicroSec"] = FrameRefreshTimeInMicroSec; - // jsonStatus["FrameStartTimeInMicroSec"] = FrameStartTimeInMicroSec; - // jsonStatus["FrameEndTimeInMicroSec"] = FrameEndTimeInMicroSec; - // jsonStatus["FrameTimeDeltaUs"] = FrameTimeDeltaInMicroSec; - // jsonStatus["micros"] = micros(); + JsonWrite(jsonStatus, CN_id, OutputChannelId); + JsonWrite(jsonStatus, F("framerefreshrate"), int(MicroSecondsInASecond / FrameDurationInMicroSec)); + JsonWrite(jsonStatus, F("FrameCount"), FrameCount); // DEBUG_END; } // GetStatus @@ -121,7 +113,7 @@ void c_OutputCommon::GetConfig (JsonObject & jsonConfig) // DEBUG_START; // enums need to be converted to uints for json - jsonConfig[CN_data_pin] = uint8_t (DataPin); + JsonWrite(jsonConfig, CN_data_pin, uint8_t (DataPin)); // DEBUG_V(String(" DataPin: ") + String(DataPin)); diff --git a/src/output/OutputGrinch.cpp b/src/output/OutputGrinch.cpp index 562f954b0..bb648e145 100644 --- a/src/output/OutputGrinch.cpp +++ b/src/output/OutputGrinch.cpp @@ -51,7 +51,7 @@ void c_OutputGrinch::GetConfig (ArduinoJson::JsonObject& jsonConfig) // DEBUG_START; c_OutputCommon::GetConfig (jsonConfig); - jsonConfig[CN_count] = NumberOfGrinchControllers; + JsonWrite(jsonConfig, CN_count, NumberOfGrinchControllers); // DEBUG_END; } // GetConfig diff --git a/src/output/OutputMgr.cpp b/src/output/OutputMgr.cpp index 46d2dce93..290306b9d 100644 --- a/src/output/OutputMgr.cpp +++ b/src/output/OutputMgr.cpp @@ -225,6 +225,7 @@ c_OutputMgr::~c_OutputMgr() void c_OutputMgr::Begin () { // DEBUG_START; + // DEBUG_V(String("Current CPU ID: ") + String(xPortGetCoreID())); // IsBooting = false; // FileMgr.DeleteConfigFile(ConfigFileName); @@ -286,11 +287,11 @@ void c_OutputMgr::CreateJsonConfig (JsonObject& jsonConfig) // DEBUG_V (); // add the channels header - JsonObject OutputMgrChannelsData = jsonConfig[CN_channels]; + JsonObject OutputMgrChannelsData = jsonConfig[(char*)CN_channels]; if (!OutputMgrChannelsData) { // DEBUG_V (); - OutputMgrChannelsData = jsonConfig[CN_channels].to (); + OutputMgrChannelsData = jsonConfig[(char*)CN_channels].to (); } // add the channel configurations @@ -308,7 +309,7 @@ void c_OutputMgr::CreateJsonConfig (JsonObject& jsonConfig) } // save the name as the selected channel type - ChannelConfigData[CN_type] = int(CurrentChannel.pOutputChannelDriver->GetOutputType()); + JsonWrite(ChannelConfigData, CN_type, int(CurrentChannel.pOutputChannelDriver->GetOutputType())); String DriverTypeId = String(int(CurrentChannel.pOutputChannelDriver->GetOutputType())); JsonObject ChannelConfigByTypeData = ChannelConfigData[String (DriverTypeId)]; @@ -329,7 +330,7 @@ void c_OutputMgr::CreateJsonConfig (JsonObject& jsonConfig) CurrentChannel.pOutputChannelDriver->GetDriverName(DriverName); // DEBUG_V (String ("DriverName: ") + DriverName); - ChannelConfigByTypeData[CN_type] = DriverName; + JsonWrite(ChannelConfigByTypeData, CN_type, DriverName); // DEBUG_V (); // PrettyPrint (ChannelConfigByTypeData, String ("jsonConfig")); @@ -369,11 +370,11 @@ void c_OutputMgr::CreateNewConfig () // DEBUG_V (); // DEBUG_V("Create a new output config structure."); - JsonObject JsonConfig = JsonConfigDoc[CN_output_config].to (); + JsonObject JsonConfig = JsonConfigDoc[(char*)CN_output_config].to (); // DEBUG_V (); - JsonConfig[CN_cfgver] = CurrentConfigVersion; - JsonConfig[CN_MaxChannels] = sizeof(OutputBuffer); + JsonWrite(JsonConfig, CN_cfgver, CurrentConfigVersion); + JsonWrite(JsonConfig, CN_MaxChannels, sizeof(OutputBuffer)); // DEBUG_V("Collect the all ports disabled config first"); CreateJsonConfig (JsonConfig); @@ -466,7 +467,7 @@ void c_OutputMgr::GetStatus (JsonObject & jsonStatus) // jsonStatus["PollCount"] = PollCount; #endif // defined(ARDUINO_ARCH_ESP32) - JsonArray OutputStatus = jsonStatus[CN_output].to (); + JsonArray OutputStatus = jsonStatus[(char*)CN_output].to (); for (auto & CurrentOutput : OutputChannelDrivers) { // DEBUG_V (); @@ -1044,7 +1045,7 @@ bool c_OutputMgr::FindJsonChannelConfig (JsonDocument& jsonConfig, do // once { - JsonObject OutputChannelMgrData = jsonConfig[CN_output_config]; + JsonObject OutputChannelMgrData = jsonConfig[(char*)CN_output_config]; if (!OutputChannelMgrData) { logcon(String(MN_16) + MN_18); @@ -1065,7 +1066,7 @@ bool c_OutputMgr::FindJsonChannelConfig (JsonDocument& jsonConfig, } // do we have a channel configuration array? - JsonObject OutputChannelArray = OutputChannelMgrData[CN_channels]; + JsonObject OutputChannelArray = OutputChannelMgrData[(char*)CN_channels]; if (!OutputChannelArray) { // if not, flag an error and stop processing @@ -1330,7 +1331,7 @@ void c_OutputMgr::Poll() } } // done need to save the current config - if ((false == IsOutputPaused) && (false == ConfigInProgress) && (false == RebootInProgress()) ) + if ((false == OutputIsPaused) && (false == ConfigInProgress) && (false == RebootInProgress()) ) { // //DEBUG_V(); for (DriverInfo_t & OutputChannel : OutputChannelDrivers) @@ -1420,7 +1421,7 @@ void c_OutputMgr::PauseOutputs(bool PauseTheOutput) // DEBUG_START; // DEBUG_V(String("PauseTheOutput: ") + String(PauseTheOutput)); - IsOutputPaused = PauseTheOutput; + OutputIsPaused = PauseTheOutput; for (auto & CurrentOutput : OutputChannelDrivers) { @@ -1437,6 +1438,11 @@ void c_OutputMgr::WriteChannelData(uint32_t StartChannelId, uint32_t ChannelCoun do // once { + if(OutputIsPaused) + { + // DEBUG_V("Ignore the write request"); + break; + } if (((StartChannelId + ChannelCount) > UsedBufferSize) || (0 == ChannelCount)) { // DEBUG_V (String("ERROR: Invalid parameters")); @@ -1496,6 +1502,11 @@ void c_OutputMgr::ReadChannelData(uint32_t StartChannelId, uint32_t ChannelCount do // once { + if(OutputIsPaused) + { + // DEBUG_V("Ignore the read request"); + break; + } if ((StartChannelId + ChannelCount) > UsedBufferSize) { // DEBUG_V (String("ERROR: Invalid parameters")); diff --git a/src/output/OutputPixel.cpp b/src/output/OutputPixel.cpp index 8889f4d40..481901ce0 100644 --- a/src/output/OutputPixel.cpp +++ b/src/output/OutputPixel.cpp @@ -51,15 +51,15 @@ void c_OutputPixel::GetConfig (ArduinoJson::JsonObject& jsonConfig) { // DEBUG_START; - jsonConfig[CN_color_order] = color_order; - jsonConfig[CN_pixel_count] = pixel_count; - jsonConfig[CN_group_size] = PixelGroupSize; - jsonConfig[CN_zig_size] = zig_size; - jsonConfig[CN_gamma] = gamma; - jsonConfig[CN_brightness] = brightness; // save as a 0 - 100 percentage - jsonConfig[CN_interframetime] = InterFrameGapInMicroSec; - jsonConfig[CN_prependnullcount] = PrependNullPixelCount; - jsonConfig[CN_appendnullcount] = AppendNullPixelCount; + JsonWrite(jsonConfig, CN_color_order, color_order); + JsonWrite(jsonConfig, CN_pixel_count, pixel_count); + JsonWrite(jsonConfig, CN_group_size, PixelGroupSize); + JsonWrite(jsonConfig, CN_zig_size, zig_size); + JsonWrite(jsonConfig, CN_gamma, gamma); + JsonWrite(jsonConfig, CN_brightness, brightness); // save as a 0 - 100 percentage + JsonWrite(jsonConfig, CN_interframetime, InterFrameGapInMicroSec); + JsonWrite(jsonConfig, CN_prependnullcount, PrependNullPixelCount); + JsonWrite(jsonConfig, CN_appendnullcount, AppendNullPixelCount); c_OutputCommon::GetConfig (jsonConfig); diff --git a/src/output/OutputRelay.cpp b/src/output/OutputRelay.cpp index 7cb94813f..13c458492 100644 --- a/src/output/OutputRelay.cpp +++ b/src/output/OutputRelay.cpp @@ -223,7 +223,7 @@ bool c_OutputRelay::SetConfig (ArduinoJson::JsonObject & jsonConfig) setFromJSON (UpdateInterval, jsonConfig, OM_RELAY_UPDATE_INTERVAL_NAME); // do we have a channel configuration array? - JsonArray JsonChannelList = jsonConfig[CN_channels]; + JsonArray JsonChannelList = jsonConfig[(char*)CN_channels]; if (!JsonChannelList) { // if not, flag an error and stop processing @@ -301,24 +301,24 @@ void c_OutputRelay::GetConfig (ArduinoJson::JsonObject & jsonConfig) { // DEBUG_START; - jsonConfig[OM_RELAY_UPDATE_INTERVAL_NAME] = UpdateInterval; + JsonWrite(jsonConfig, OM_RELAY_UPDATE_INTERVAL_NAME, UpdateInterval); - JsonArray JsonChannelList = jsonConfig[CN_channels].to (); + JsonArray JsonChannelList = jsonConfig[(char*)CN_channels].to (); uint8_t ChannelId = 0; for (RelayChannel_t & currentRelay : OutputList) { JsonObject JsonChannelData = JsonChannelList.add (); - JsonChannelData[CN_id] = ChannelId; - JsonChannelData[OM_RELAY_CHANNEL_ENABLED_NAME] = currentRelay.Enabled; - JsonChannelData[OM_RELAY_CHANNEL_INVERT_NAME] = currentRelay.InvertOutput; - JsonChannelData[OM_RELAY_CHANNEL_PWM_NAME] = currentRelay.Pwm; - JsonChannelData[CN_trig] = currentRelay.OnOffTriggerLevel; - JsonChannelData[CN_gid] = int(currentRelay.GpioId); + JsonWrite(JsonChannelData, CN_id, ChannelId); + JsonWrite(JsonChannelData, OM_RELAY_CHANNEL_ENABLED_NAME, currentRelay.Enabled); + JsonWrite(JsonChannelData, OM_RELAY_CHANNEL_INVERT_NAME, currentRelay.InvertOutput); + JsonWrite(JsonChannelData, OM_RELAY_CHANNEL_PWM_NAME, currentRelay.Pwm); + JsonWrite(JsonChannelData, CN_trig, currentRelay.OnOffTriggerLevel); + JsonWrite(JsonChannelData, CN_gid, int(currentRelay.GpioId)); #if defined(ARDUINO_ARCH_ESP32) - JsonChannelData[CN_Frequency] = currentRelay.PwmFrequency; + JsonWrite(JsonChannelData, CN_Frequency, currentRelay.PwmFrequency); #endif // defined(ARDUINO_ARCH_ESP32) // DEBUGV (String ("CurrentRelayChanIndex: ") + String (ChannelId)); @@ -340,15 +340,15 @@ void c_OutputRelay::GetStatus(ArduinoJson::JsonObject &jsonStatus) // DEBUG_START; c_OutputCommon::BaseGetStatus(jsonStatus); - JsonArray JsonChannelList = jsonStatus[CN_Relay].to (); + JsonArray JsonChannelList = jsonStatus[(char*)CN_Relay].to (); uint8_t ChannelId = 0; for (RelayChannel_t & currentRelay : OutputList) { JsonObject JsonChannelData = JsonChannelList.add (); - JsonChannelData[CN_id] = ChannelId; - JsonChannelData[CN_activevalue] = currentRelay.previousValue; + JsonWrite(JsonChannelData, CN_id, ChannelId); + JsonWrite(JsonChannelData, CN_activevalue, currentRelay.previousValue); ++ChannelId; } diff --git a/src/output/OutputRmt.cpp b/src/output/OutputRmt.cpp index d12b478e6..6cd246f53 100644 --- a/src/output/OutputRmt.cpp +++ b/src/output/OutputRmt.cpp @@ -39,6 +39,8 @@ static uint32_t FrameTimeouts = 0; //---------------------------------------------------------------------------- void RMT_Task (void *arg) { + // DEBUG_V(String("Current CPU ID: ") + String(xPortGetCoreID())); + unsigned long FrameStartTimeMS = millis(); unsigned long FrameEndTimeMS = FrameStartTimeMS; const uint32_t MinFrameTimeMs = 25; diff --git a/src/output/OutputSerial.cpp b/src/output/OutputSerial.cpp index c3ad90469..a88a58cc1 100644 --- a/src/output/OutputSerial.cpp +++ b/src/output/OutputSerial.cpp @@ -66,10 +66,10 @@ void c_OutputSerial::GetConfig(ArduinoJson::JsonObject &jsonConfig) { // DEBUG_START; - jsonConfig[CN_gen_ser_hdr] = GenericSerialHeader; - jsonConfig[CN_gen_ser_ftr] = GenericSerialFooter; - jsonConfig[CN_num_chan] = Num_Channels; - jsonConfig[CN_baudrate] = CurrentBaudrate; + JsonWrite(jsonConfig, CN_gen_ser_hdr, GenericSerialHeader); + JsonWrite(jsonConfig, CN_gen_ser_ftr, GenericSerialFooter); + JsonWrite(jsonConfig, CN_num_chan, Num_Channels); + JsonWrite(jsonConfig, CN_baudrate, CurrentBaudrate); c_OutputCommon::GetConfig (jsonConfig); @@ -177,7 +177,7 @@ bool c_OutputSerial::SetConfig (ArduinoJson::JsonObject& jsonConfig) #if defined(SUPPORT_OutputType_DMX) if (OutputType == c_OutputMgr::e_OutputType::OutputType_DMX) { - jsonConfig[CN_baudrate] = uint32_t(BaudRate::BR_DMX); + JsonWrite(jsonConfig, CN_baudrate, uint32_t(BaudRate::BR_DMX)); } #endif // defined(SUPPORT_OutputType_DMX) diff --git a/src/output/OutputServoPCA9685.cpp b/src/output/OutputServoPCA9685.cpp index d04d605df..6f92165b9 100644 --- a/src/output/OutputServoPCA9685.cpp +++ b/src/output/OutputServoPCA9685.cpp @@ -161,7 +161,7 @@ bool c_OutputServoPCA9685::SetConfig (ArduinoJson::JsonObject & jsonConfig) pwm->setPWMFreq (UpdateFrequency); // do we have a channel configuration array? - JsonArray JsonChannelList = jsonConfig[OM_SERVO_PCA9685_CHANNELS_NAME]; + JsonArray JsonChannelList = jsonConfig[(char*)OM_SERVO_PCA9685_CHANNELS_NAME]; if (!JsonChannelList) { // if not, flag an error and stop processing @@ -216,23 +216,23 @@ void c_OutputServoPCA9685::GetConfig (ArduinoJson::JsonObject & jsonConfig) { // DEBUG_START; - jsonConfig[OM_SERVO_PCA9685_UPDATE_INTERVAL_NAME] = UpdateFrequency; + JsonWrite(jsonConfig, OM_SERVO_PCA9685_UPDATE_INTERVAL_NAME, UpdateFrequency); - JsonArray JsonChannelList = jsonConfig[OM_SERVO_PCA9685_CHANNELS_NAME].to (); + JsonArray JsonChannelList = jsonConfig[(char*)OM_SERVO_PCA9685_CHANNELS_NAME].to (); uint8_t ChannelId = 0; for (ServoPCA9685Channel_t & currentServoPCA9685 : OutputList) { JsonObject JsonChannelData = JsonChannelList.add (); - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_ID_NAME] = ChannelId; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_ENABLED_NAME] = currentServoPCA9685.Enabled; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_MINLEVEL_NAME] = currentServoPCA9685.MinLevel; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_MAXLEVEL_NAME] = currentServoPCA9685.MaxLevel; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_REVERSED] = currentServoPCA9685.IsReversed; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_16BITS] = currentServoPCA9685.Is16Bit; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_SCALED] = currentServoPCA9685.IsScaled; - JsonChannelData[OM_SERVO_PCA9685_CHANNEL_HOME] = currentServoPCA9685.HomeValue; + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_ID_NAME, ChannelId); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_ENABLED_NAME, currentServoPCA9685.Enabled); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_MINLEVEL_NAME, currentServoPCA9685.MinLevel); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_MAXLEVEL_NAME, currentServoPCA9685.MaxLevel); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_REVERSED, currentServoPCA9685.IsReversed); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_16BITS, currentServoPCA9685.Is16Bit); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_SCALED, currentServoPCA9685.IsScaled); + JsonWrite(JsonChannelData, OM_SERVO_PCA9685_CHANNEL_HOME, currentServoPCA9685.HomeValue); // DEBUG_V (String ("ChannelId: ") + String (ChannelId)); // DEBUG_V (String (" Enabled: ") + String (currentServoPCA9685.Enabled)); diff --git a/src/output/OutputSpi.cpp b/src/output/OutputSpi.cpp index 67f88c6a7..4bf44f788 100644 --- a/src/output/OutputSpi.cpp +++ b/src/output/OutputSpi.cpp @@ -181,9 +181,9 @@ void c_OutputSpi::GetConfig (ArduinoJson::JsonObject & jsonConfig) // DEBUG_START; JsonObject SpiConfig = jsonConfig["dataspi"].to(); - SpiConfig[CN_cs_pin] = CsPin; - SpiConfig[CN_data_pin] = DataPin; - SpiConfig[CN_clock_pin] = ClockPin; + JsonWrite(SpiConfig, CN_cs_pin, CsPin); + JsonWrite(SpiConfig, CN_data_pin, DataPin); + JsonWrite(SpiConfig, CN_clock_pin, ClockPin); // DEBUG_END; } // GetConfig diff --git a/src/output/OutputTM1814.cpp b/src/output/OutputTM1814.cpp index fb2fd8037..94473fd19 100644 --- a/src/output/OutputTM1814.cpp +++ b/src/output/OutputTM1814.cpp @@ -61,7 +61,7 @@ void c_OutputTM1814::GetConfig (ArduinoJson::JsonObject& jsonConfig) // DEBUG_START; c_OutputPixel::GetConfig (jsonConfig); - jsonConfig[CN_currentlimit] = CurrentLimit; + JsonWrite(jsonConfig, CN_currentlimit, CurrentLimit); // DEBUG_END; } // GetConfig diff --git a/src/output/OutputUart.cpp b/src/output/OutputUart.cpp index 711f243d6..b9544df9b 100644 --- a/src/output/OutputUart.cpp +++ b/src/output/OutputUart.cpp @@ -283,7 +283,7 @@ void c_OutputUart::GetConfig(JsonObject &jsonConfig) // enums need to be converted to uints for json // jsonConfig[CN_data_pin] = uint8_t(OutputUartConfig.DataPin); - jsonConfig[CN_baudrate] = OutputUartConfig.Baudrate; + JsonWrite(jsonConfig, CN_baudrate, OutputUartConfig.Baudrate); // DEBUG_V(String(" DataPin: ") + String(OutputUartConfig.DataPin)); // DEBUG_V(String("Baudrate: ") + String(OutputUartConfig.Baudrate)); diff --git a/src/service/FPPDiscovery.cpp b/src/service/FPPDiscovery.cpp index ba8701539..fd46a00be 100644 --- a/src/service/FPPDiscovery.cpp +++ b/src/service/FPPDiscovery.cpp @@ -139,6 +139,17 @@ void c_FPPDiscovery::Enable () } // Enable +//----------------------------------------------------------------------------- +void c_FPPDiscovery::SetOperationalState (bool ActiveFlag) +{ + // DEBUG_START; + + // Do NOT call enable / disable since they call other functions. + IsEnabled = ActiveFlag; + + // DEBUG_END; +} + //----------------------------------------------------------------------------- void c_FPPDiscovery::GetStatus (JsonObject & jsonStatus) { @@ -147,35 +158,35 @@ void c_FPPDiscovery::GetStatus (JsonObject & jsonStatus) if (IsEnabled) { #ifdef FPP_DEBUG_ENABLED - jsonStatus[F ("pktCommand")] = MultiSyncStats.pktCommand; - jsonStatus[F ("pktSyncSeqOpen")] = MultiSyncStats.pktSyncSeqOpen; - jsonStatus[F ("pktSyncSeqStart")] = MultiSyncStats.pktSyncSeqStart; - jsonStatus[F ("pktSyncSeqStop")] = MultiSyncStats.pktSyncSeqStop; - jsonStatus[F ("pktSyncSeqSync")] = MultiSyncStats.pktSyncSeqSync; - jsonStatus[F ("pktSyncMedOpen")] = MultiSyncStats.pktSyncMedOpen; - jsonStatus[F ("pktSyncMedStart")] = MultiSyncStats.pktSyncMedStart; - jsonStatus[F ("pktSyncMedStop")] = MultiSyncStats.pktSyncMedStop; - jsonStatus[F ("pktSyncMedSync")] = MultiSyncStats.pktSyncMedSync; - jsonStatus[F ("pktBlank")] = MultiSyncStats.pktBlank; - jsonStatus[F ("pktPing")] = MultiSyncStats.pktPing; - jsonStatus[F ("pktPlugin")] = MultiSyncStats.pktPlugin; - jsonStatus[F ("pktFPPCommand")] = MultiSyncStats.pktFPPCommand; - jsonStatus[F ("pktHdrError")] = MultiSyncStats.pktHdrError; - jsonStatus[F ("pktUnknown")] = MultiSyncStats.pktUnknown; - jsonStatus[F ("pktLastCommand")] = MultiSyncStats.pktLastCommand; - - jsonStatus[F ("ProcessFPPJson")] = SystemDebugStats.ProcessFPPJson; - jsonStatus[F ("ProcessFPPDJson")] = SystemDebugStats.ProcessFPPDJson; - jsonStatus[F ("CmdGetFPPstatus")] = SystemDebugStats.CmdGetFPPstatus; - jsonStatus[F ("CmdGetSysInfoJSON")] = SystemDebugStats.CmdGetSysInfoJSON; - jsonStatus[F ("CmdGetHostname")] = SystemDebugStats.CmdGetHostname; - jsonStatus[F ("CmdGetConfig")] = SystemDebugStats.CmdGetConfig; - jsonStatus[F ("CmdNotFound")] = SystemDebugStats.CmdNotFound; + JsonWrite(jsonStatus, F ("pktCommand"), MultiSyncStats.pktCommand); + JsonWrite(jsonStatus, F ("pktSyncSeqOpen"), MultiSyncStats.pktSyncSeqOpen); + JsonWrite(jsonStatus, F ("pktSyncSeqStart"), MultiSyncStats.pktSyncSeqStart); + JsonWrite(jsonStatus, F ("pktSyncSeqStop"), MultiSyncStats.pktSyncSeqStop); + JsonWrite(jsonStatus, F ("pktSyncSeqSync"), MultiSyncStats.pktSyncSeqSync); + JsonWrite(jsonStatus, F ("pktSyncMedOpen"), MultiSyncStats.pktSyncMedOpen); + JsonWrite(jsonStatus, F ("pktSyncMedStart"), MultiSyncStats.pktSyncMedStart); + JsonWrite(jsonStatus, F ("pktSyncMedStop"), MultiSyncStats.pktSyncMedStop); + JsonWrite(jsonStatus, F ("pktSyncMedSync"), MultiSyncStats.pktSyncMedSync); + JsonWrite(jsonStatus, F ("pktBlank"), MultiSyncStats.pktBlank); + JsonWrite(jsonStatus, F ("pktPing"), MultiSyncStats.pktPing); + JsonWrite(jsonStatus, F ("pktPlugin"), MultiSyncStats.pktPlugin); + JsonWrite(jsonStatus, F ("pktFPPCommand"), MultiSyncStats.pktFPPCommand); + JsonWrite(jsonStatus, F ("pktHdrError"), MultiSyncStats.pktHdrError); + JsonWrite(jsonStatus, F ("pktUnknown"), MultiSyncStats.pktUnknown); + JsonWrite(jsonStatus, F ("pktLastCommand"), MultiSyncStats.pktLastCommand); + + JsonWrite(jsonStatus, F ("ProcessFPPJson"), SystemDebugStats.ProcessFPPJson); + JsonWrite(jsonStatus, F ("ProcessFPPDJson"), SystemDebugStats.ProcessFPPDJson); + JsonWrite(jsonStatus, F ("CmdGetFPPstatus"), SystemDebugStats.CmdGetFPPstatus); + JsonWrite(jsonStatus, F ("CmdGetSysInfoJSON"), SystemDebugStats.CmdGetSysInfoJSON); + JsonWrite(jsonStatus, F ("CmdGetHostname"), SystemDebugStats.CmdGetHostname); + JsonWrite(jsonStatus, F ("CmdGetConfig"), SystemDebugStats.CmdGetConfig); + JsonWrite(jsonStatus, F ("CmdNotFound"), SystemDebugStats.CmdNotFound); #endif // def FPP_DEBUG_ENABLED // DEBUG_V ("Is Enabled"); JsonObject MyJsonStatus = jsonStatus[F ("FPPDiscovery")].to (); - MyJsonStatus[F ("FppRemoteIp")] = FppRemoteIp.toString (); + JsonWrite(MyJsonStatus, F ("FppRemoteIp"), FppRemoteIp.toString ()); if (InputFPPRemotePlayFile) { InputFPPRemotePlayFile->GetStatus (MyJsonStatus); @@ -338,7 +349,7 @@ void c_FPPDiscovery::ProcessSyncPacket (uint8_t action, String FileName, float S // DEBUG_START; do // once { - if (!AllowedToRemotePlayFiles ()) + if (!IsEnabled || !AllowedToRemotePlayFiles ()) { // DEBUG_V ("Not allowed to play remote files"); break; @@ -429,9 +440,9 @@ void c_FPPDiscovery::ProcessBlankPacket () { // DEBUG_START; - StopPlaying (false); if (IsEnabled) { + StopPlaying (false); memset (OutputMgr.GetBufferAddress(), 0x0, OutputMgr.GetBufferUsedSize ()); } // DEBUG_END; @@ -531,15 +542,17 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St JsonDocument JsonDoc; JsonObject JsonData = JsonDoc.to (); + // DEBUG_V(String("FileHandle: ") + String(fseq)); + FSEQRawHeader fsqHeader; FileMgr.ReadSdFile (fseq, (byte*)&fsqHeader, sizeof (fsqHeader), size_t(0)); - JsonData[F ("Name")] = fname; - JsonData[CN_Version] = String (fsqHeader.majorVersion) + "." + String (fsqHeader.minorVersion); - JsonData[F ("ID")] = int64String (read64 (fsqHeader.id, 0)); - JsonData[F ("StepTime")] = String (fsqHeader.stepTime); - JsonData[F ("NumFrames")] = String (read32 (fsqHeader.TotalNumberOfFramesInSequence, 0)); - JsonData[F ("CompressionType")] = fsqHeader.compressionType; + JsonWrite(JsonData, F ("Name"), fname); + JsonWrite(JsonData, CN_Version, String (fsqHeader.majorVersion) + "." + String (fsqHeader.minorVersion)); + JsonWrite(JsonData, F ("ID"), int64String (read64 (fsqHeader.id, 0))); + JsonWrite(JsonData, F ("StepTime"), String (fsqHeader.stepTime)); + JsonWrite(JsonData, F ("NumFrames"), String (read32 (fsqHeader.TotalNumberOfFramesInSequence, 0))); + JsonWrite(JsonData, F ("CompressionType"), fsqHeader.compressionType); static const int TIME_STR_CHAR_COUNT = 32; char timeStr[TIME_STR_CHAR_COUNT]; @@ -552,23 +565,23 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St // TODO: assert ((actuallyWritten > 0) && (actuallyWritten < TIME_STR_CHAR_COUNT)) if ((actuallyWritten > 0) && (actuallyWritten < TIME_STR_CHAR_COUNT)) { - JsonData[F ("lastReceiveTime")] = timeStr; + JsonWrite(JsonData, F ("lastReceiveTime"), timeStr); } - JsonData[F ("pktCommand")] = MultiSyncStats.pktCommand; - JsonData[F ("pktSyncSeqOpen")] = MultiSyncStats.pktSyncSeqOpen; - JsonData[F ("pktSyncSeqStart")] = MultiSyncStats.pktSyncSeqStart; - JsonData[F ("pktSyncSeqStop")] = MultiSyncStats.pktSyncSeqStop; - JsonData[F ("pktSyncSeqSync")] = MultiSyncStats.pktSyncSeqSync; - JsonData[F ("pktSyncMedOpen")] = MultiSyncStats.pktSyncMedOpen; - JsonData[F ("pktSyncMedStart")] = MultiSyncStats.pktSyncMedStart; - JsonData[F ("pktSyncMedStop")] = MultiSyncStats.pktSyncMedStop; - JsonData[F ("pktSyncMedSync")] = MultiSyncStats.pktSyncMedSync; - JsonData[F ("pktBlank")] = MultiSyncStats.pktBlank; - JsonData[F ("pktPing")] = MultiSyncStats.pktPing; - JsonData[F ("pktPlugin")] = MultiSyncStats.pktPlugin; - JsonData[F ("pktFPPCommand")] = MultiSyncStats.pktFPPCommand; - JsonData[F ("pktError")] = MultiSyncStats.pktHdrError; + JsonWrite(JsonData, F ("pktCommand"), MultiSyncStats.pktCommand); + JsonWrite(JsonData, F ("pktSyncSeqOpen"), MultiSyncStats.pktSyncSeqOpen); + JsonWrite(JsonData, F ("pktSyncSeqStart"), MultiSyncStats.pktSyncSeqStart); + JsonWrite(JsonData, F ("pktSyncSeqStop"), MultiSyncStats.pktSyncSeqStop); + JsonWrite(JsonData, F ("pktSyncSeqSync"), MultiSyncStats.pktSyncSeqSync); + JsonWrite(JsonData, F ("pktSyncMedOpen"), MultiSyncStats.pktSyncMedOpen); + JsonWrite(JsonData, F ("pktSyncMedStart"), MultiSyncStats.pktSyncMedStart); + JsonWrite(JsonData, F ("pktSyncMedStop"), MultiSyncStats.pktSyncMedStop); + JsonWrite(JsonData, F ("pktSyncMedSync"), MultiSyncStats.pktSyncMedSync); + JsonWrite(JsonData, F ("pktBlank"), MultiSyncStats.pktBlank); + JsonWrite(JsonData, F ("pktPing"), MultiSyncStats.pktPing); + JsonWrite(JsonData, F ("pktPlugin"), MultiSyncStats.pktPlugin); + JsonWrite(JsonData, F ("pktFPPCommand"), MultiSyncStats.pktFPPCommand); + JsonWrite(JsonData, F ("pktError"), MultiSyncStats.pktHdrError); uint32_t maxChannel = read32 (fsqHeader.channelCount, 0); @@ -591,8 +604,8 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St uint32_t RangeLength = read24 (CurrentFSEQRangeEntry->Length); JsonObject JsonRange = JsonDataRanges.add (); - JsonRange[F ("Start")] = String (RangeStart); - JsonRange[F ("Length")] = String (RangeLength); + JsonWrite(JsonRange, F ("Start"), String (RangeStart)); + JsonWrite(JsonRange, F ("Length"), String (RangeLength)); if ((RangeStart + RangeLength - 1) > maxChannel) { @@ -603,8 +616,8 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St free (RangeDataBuffer); } - JsonData[F ("MaxChannel")] = String (maxChannel); - JsonData[F ("ChannelCount")] = String (read32 (fsqHeader.channelCount,0)); + JsonWrite(JsonData, F ("MaxChannel"), String (maxChannel)); + JsonWrite(JsonData, F ("ChannelCount"), String (read32 (fsqHeader.channelCount,0))); uint32_t FileOffsetToCurrentHeaderRecord = read16 (fsqHeader.VariableHdrOffset); uint32_t FileOffsetToStartOfSequenceData = read16 (fsqHeader.dataOffset); // DataOffset @@ -637,7 +650,7 @@ void c_FPPDiscovery::BuildFseqResponse (String fname, c_FileMgr::FileId fseq, St FileMgr.ReadSdFile (fseq, (byte*)VariableDataHeaderDataBuffer, VariableDataHeaderDataLength, FileOffsetToCurrentHeaderRecord); JsonObject JsonDataHeader = JsonDataHeaders.add (); - JsonDataHeader[HeaderTypeCode] = String (VariableDataHeaderDataBuffer); + JsonWrite(JsonDataHeader, HeaderTypeCode.c_str(), String (VariableDataHeaderDataBuffer)); free (VariableDataHeaderDataBuffer); } @@ -676,12 +689,12 @@ void c_FPPDiscovery::ProcessGET (AsyncWebServerRequest* request) if (path.startsWith (F ("/api/sequence/")) && AllowedToRemotePlayFiles()) { - // DEBUG_V (""); + // DEBUG_V (emptyString); String seq = path.substring (14); if (seq.endsWith (F ("/meta"))) { - // DEBUG_V (""); + // DEBUG_V (emptyString); seq = seq.substring (0, seq.length () - 5); StopPlaying (false); @@ -765,7 +778,7 @@ void c_FPPDiscovery::ProcessPOST (AsyncWebServerRequest* request) } // DEBUG_V ("BuildFseqResponse"); - String resp = ""; + String resp = emptyString; BuildFseqResponse (filename, FileHandle, resp); FileMgr.CloseSdFile (FileHandle); request->send (200, CN_applicationSLASHjson, resp); @@ -811,18 +824,17 @@ void c_FPPDiscovery::ProcessFile ( if(!inFileUpload) { - // DEBUG_V(); - // wait for the player to become idle + // DEBUG_V(String("Current CPU ID: ") + String(xPortGetCoreID())); + // DEBUG_V("wait for the player to become idle"); StopPlaying(true); inFileUpload = true; UploadFileName = filename; InputMgr.SetOperationalState(false); OutputMgr.PauseOutputs(true); - memset(OutputMgr.GetBufferAddress(), 0x00, OutputMgr.GetBufferSize()); } - // DEBUG_V(); - bool writeFailed = !FileMgr.handleFileUpload (UploadFileName, index, data, len, final, ContentLength); + // DEBUG_V("Write the file block"); + writeFailed = !FileMgr.handleFileUpload (UploadFileName, index, data, len, final, ContentLength); if(writeFailed) { @@ -831,13 +843,19 @@ void c_FPPDiscovery::ProcessFile ( } // DEBUG_V(); - if (final || writeFailed) + if (final) { - // DEBUG_V("Allow file to play"); inFileUpload = false; - UploadFileName = ""; + UploadFileName = emptyString; + writeFailed = false; + memset(OutputMgr.GetBufferAddress(), 0x00, OutputMgr.GetBufferSize()); InputMgr.SetOperationalState(true); OutputMgr.PauseOutputs(false); + FeedWDT(); + delay(1000); + FeedWDT(); + // DEBUG_V("Allow file to play"); + StartPlaying(UploadFileName, 0.0); } } while (false); @@ -866,7 +884,7 @@ void c_FPPDiscovery::ProcessBody ( // is this the first packet? if (0 == index) { - // DEBUG_V(); + // DEBUG_V("New Download"); if(!request->hasParam(ulrPath)) { @@ -885,9 +903,11 @@ void c_FPPDiscovery::ProcessBody ( break; } UploadFileName = String (request->getParam (CN_filename)->value ()); - // DEBUG_V (""); + // DEBUG_V (emptyString); } + writeFailed = false; + // DEBUG_V (String (" name: ") + UploadFileName); // DEBUG_V (String (" index: ") + String (index)); // DEBUG_V (String (" len: ") + String (len)); @@ -909,24 +929,24 @@ void c_FPPDiscovery::GetSysInfoJSON (JsonObject & jsonResponse) String Hostname; NetworkMgr.GetHostname (Hostname); - jsonResponse[CN_HostName] = Hostname; - jsonResponse[F ("HostDescription")] = config.id; - jsonResponse[CN_Platform] = CN_ESPixelStick; - jsonResponse[F ("Variant")] = FPP_VARIANT_NAME; - jsonResponse[F ("Mode")] = (true == AllowedToRemotePlayFiles()) ? CN_remote : CN_bridge; - jsonResponse[CN_Version] = VERSION; + JsonWrite(jsonResponse, CN_HostName, Hostname); + JsonWrite(jsonResponse, F ("HostDescription"), config.id); + JsonWrite(jsonResponse, CN_Platform, String(CN_ESPixelStick)); + JsonWrite(jsonResponse, F ("Variant"), FPP_VARIANT_NAME); + JsonWrite(jsonResponse, F ("Mode"), String((true == AllowedToRemotePlayFiles()) ? CN_remote : CN_bridge)); + JsonWrite(jsonResponse, CN_Version, VERSION); const char* version = VERSION.c_str (); - jsonResponse[F ("majorVersion")] = (uint16_t)atoi (version); - jsonResponse[F ("minorVersion")] = (uint16_t)atoi (&version[2]); - jsonResponse[F ("typeId")] = FPP_TYPE_ID; + JsonWrite(jsonResponse, F ("majorVersion"), (uint16_t)atoi (version)); + JsonWrite(jsonResponse, F ("minorVersion"), (uint16_t)atoi (&version[2])); + JsonWrite(jsonResponse, F ("typeId"), FPP_TYPE_ID); JsonObject jsonResponseUtilization = jsonResponse[F ("Utilization")].to (); - jsonResponseUtilization[F ("MemoryFree")] = ESP.getFreeHeap (); - jsonResponseUtilization[F ("Uptime")] = millis (); + JsonWrite(jsonResponseUtilization, F ("MemoryFree"), ESP.getFreeHeap ()); + JsonWrite(jsonResponseUtilization, F ("Uptime"), millis ()); - jsonResponse[CN_rssi] = WiFi.RSSI (); + JsonWrite(jsonResponse, CN_rssi, WiFi.RSSI ()); JsonArray jsonResponseIpAddresses = jsonResponse[F ("IPS")].to (); jsonResponseIpAddresses.add(WiFi.localIP ().toString ()); @@ -934,52 +954,52 @@ void c_FPPDiscovery::GetSysInfoJSON (JsonObject & jsonResponse) } // GetSysInfoJSON +//----------------------------------------------------------------------------- void c_FPPDiscovery::GetStatusJSON (JsonObject & JsonData, bool adv) { // DEBUG_START; JsonObject JsonDataMqtt = JsonData[F ("MQTT")].to(); - JsonDataMqtt[F ("configured")] = false; - JsonDataMqtt[F ("connected")] = false; + JsonWrite(JsonDataMqtt, F ("configured"), false); + JsonWrite(JsonDataMqtt, F ("connected"), false); JsonObject JsonDataCurrentPlaylist = JsonData[F ("current_playlist")].to (); - JsonDataCurrentPlaylist[CN_count] = "0"; - JsonDataCurrentPlaylist[F ("description")] = ""; - JsonDataCurrentPlaylist[F ("index")] = "0"; - JsonDataCurrentPlaylist[CN_playlist] = ""; - JsonDataCurrentPlaylist[CN_type] = ""; + JsonWrite(JsonDataCurrentPlaylist, CN_count, "0"); + JsonWrite(JsonDataCurrentPlaylist, F ("description"), emptyString); + JsonWrite(JsonDataCurrentPlaylist, F ("index"), "0"); + JsonWrite(JsonDataCurrentPlaylist, CN_playlist, emptyString); + JsonWrite(JsonDataCurrentPlaylist, CN_type, emptyString); // DEBUG_V(); - JsonData[F ("volume")] = 70; - JsonData[F ("media_filename")] = ""; - JsonData[F ("fppd")] = F ("running"); - JsonData[F ("current_song")] = ""; + JsonWrite(JsonData, F ("volume"), 70); + JsonWrite(JsonData, F ("media_filename"), emptyString); + JsonWrite(JsonData, F ("fppd"), F ("running")); + JsonWrite(JsonData, F ("current_song"), emptyString); if (false == PlayingFile()) { - JsonData[CN_current_sequence] = ""; - JsonData[CN_playlist] = ""; - JsonData[CN_seconds_elapsed] = String (0); - JsonData[CN_seconds_played] = String (0); - JsonData[CN_seconds_remaining] = String (0); - JsonData[CN_sequence_filename] = ""; - JsonData[CN_time_elapsed] = String("00:00"); - JsonData[CN_time_remaining] = String ("00:00"); - - JsonData[CN_status] = 0; - JsonData[CN_status_name] = F ("idle"); + JsonWrite(JsonData, CN_current_sequence, emptyString); + JsonWrite(JsonData, CN_playlist, emptyString); + JsonWrite(JsonData, CN_seconds_elapsed, String (0)); + JsonWrite(JsonData, CN_seconds_played, String (0)); + JsonWrite(JsonData, CN_seconds_remaining, String (0)); + JsonWrite(JsonData, CN_sequence_filename, emptyString); + JsonWrite(JsonData, CN_time_elapsed, String("00:00")); + JsonWrite(JsonData, CN_time_remaining, String ("00:00")); + JsonWrite(JsonData, CN_status, 0); + JsonWrite(JsonData, CN_status_name, F ("idle")); if (IsEnabled) { - JsonData[CN_mode] = 8; - JsonData[CN_mode_name] = CN_remote; + JsonWrite(JsonData, CN_mode, 8); + JsonWrite(JsonData, CN_mode_name, String(CN_remote)); } else { - JsonData[CN_mode] = 1; - JsonData[CN_mode_name] = CN_bridge; + JsonWrite(JsonData, CN_mode, 1); + JsonWrite(JsonData, CN_mode_name, String(CN_bridge)); } } else @@ -990,11 +1010,11 @@ void c_FPPDiscovery::GetStatusJSON (JsonObject & JsonData, bool adv) // DEBUG_V(); InputFPPRemotePlayFile->GetStatus (JsonData); } - JsonData[CN_status] = 1; - JsonData[CN_status_name] = F ("playing"); + JsonWrite(JsonData, CN_status, 1); + JsonWrite(JsonData, CN_status_name, F ("playing")); - JsonData[CN_mode] = 8; - JsonData[CN_mode_name] = CN_remote; + JsonWrite(JsonData, CN_mode, 8); + JsonWrite(JsonData, CN_mode_name, String(CN_remote)); } // DEBUG_V(); @@ -1056,7 +1076,7 @@ void c_FPPDiscovery::ProcessFPPJson (AsyncWebServerRequest* request) SystemDebugStats.CmdGetSysInfoJSON++; GetSysInfoJSON (JsonData); - String resp = ""; + String resp = emptyString; serializeJson (JsonData, resp); // DEBUG_V (String ("JsonDoc: ") + resp); request->send (200, CN_applicationSLASHjson, resp); @@ -1070,8 +1090,8 @@ void c_FPPDiscovery::ProcessFPPJson (AsyncWebServerRequest* request) String Hostname; NetworkMgr.GetHostname (Hostname); - JsonData[CN_HostName] = Hostname; - JsonData[F ("HostDescription")] = config.id; + JsonWrite(JsonData, CN_HostName, Hostname); + JsonWrite(JsonData, F ("HostDescription"), config.id); String resp; serializeJson (JsonData, resp); @@ -1143,6 +1163,7 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) { // DEBUG_START; // DEBUG_V (String("Open:: FileName: ") + FileName); + // DEBUG_V (String ("IsEnabled '") + String(IsEnabled)); do // once { @@ -1151,14 +1172,14 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) // DEBUG_V ("Not Enabled"); break; } - // DEBUG_V (""); + // DEBUG_V (emptyString); if (inFileUpload) { // DEBUG_V ("Uploading"); break; } - // DEBUG_V (""); + // DEBUG_V (emptyString); if (FileName.isEmpty()) { @@ -1169,6 +1190,7 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) if (InputFPPRemotePlayFile) { + // DEBUG_V ("Ask FSM to start playing"); InputFPPRemotePlayFile->Start (FileName, SecondsElapsed, 1); } @@ -1183,31 +1205,43 @@ void c_FPPDiscovery::StartPlaying (String & FileName, float SecondsElapsed) void c_FPPDiscovery::StopPlaying (bool wait) { // DEBUG_START; + // DEBUG_V (String ("Current Task Priority: ") + String(uxTaskPriorityGet(NULL))); + // xDEBUG_V (String ("FPPDiscovery::StopPlaying '") + InputFPPRemotePlayFile->GetFileName() + "'"); + // DEBUG_V (String ("IsEnabled '") + String(IsEnabled)); - FeedWDT(); - - // DEBUG_V (String (F ("FPPDiscovery::StopPlaying '")) + InputFPPRemotePlayFile.GetFileName() + "'"); - // only process if the pointer is valid - while (InputFPPRemotePlayFile) + // prevent reentrant issues + if(!StopInProgress && IsEnabled) { - // DEBUG_V("Pointer is valid"); - if(InputFPPRemotePlayFile->IsIdle()) + StopInProgress = true; + // only process if the pointer is valid + while (InputFPPRemotePlayFile) { - // DEBUG_V("we are done"); - break; - } + // DEBUG_V("Pointer is valid"); + if(InputFPPRemotePlayFile->IsIdle()) + { + // DEBUG_V("we are done"); + break; + } - // DEBUG_V("try to stop"); - InputFPPRemotePlayFile->Stop (); + // DEBUG_V("try to stop"); + InputFPPRemotePlayFile->Stop (); + InputFPPRemotePlayFile->Poll (); - if(wait) - { - delay(10); - } - else - { - break; + if(wait) + { + FeedWDT(); + delay(5); + } + else + { + break; + } } + StopInProgress = false; + } + else + { + // DEBUG_V("Ignoring duplicate request to stop"); } // DEBUG_END; @@ -1295,5 +1329,4 @@ void c_FPPDiscovery::ForgetInputFPPRemotePlayFile () } // SetInputFPPRemotePlayFile - c_FPPDiscovery FPPDiscovery; diff --git a/src/service/SensorDS18B20.cpp b/src/service/SensorDS18B20.cpp index a946b1676..5f2d5f4df 100644 --- a/src/service/SensorDS18B20.cpp +++ b/src/service/SensorDS18B20.cpp @@ -44,9 +44,9 @@ void c_SensorDS18B20::GetConfig (JsonObject& json) { // DEBUG_START; - JsonObject SensorConfig = json[CN_sensor].to (); + JsonObject SensorConfig = json[(char*)CN_sensor].to (); - SensorConfig[CN_units] = TempUnit; + JsonWrite(SensorConfig, CN_units, TempUnit); // DEBUG_END; } // GetConfig @@ -60,7 +60,7 @@ bool c_SensorDS18B20::SetConfig (JsonObject& json) do // once { - JsonObject JsonDeviceConfig = json[CN_sensor]; + JsonObject JsonDeviceConfig = json[(char*)CN_sensor]; if (!JsonDeviceConfig) { logcon (F ("No Sensor settings found.")); @@ -82,7 +82,7 @@ bool c_SensorDS18B20::SetConfig (JsonObject& json) } // SetConfig //----------------------------------------------------------------------------- -void c_SensorDS18B20::GetStatus (JsonObject& json) +void c_SensorDS18B20::GetStatus (JsonObject& json) { // DEBUG_START; @@ -93,9 +93,9 @@ void c_SensorDS18B20::GetStatus (JsonObject& json) break; } - JsonObject SensorStatus = json[CN_sensor].to (); + JsonObject SensorStatus = json[(char*)CN_sensor].to (); - SensorStatus[CN_reading] = String(LastReading) + ((TempUnit == TempUnit_t::TempUnitCentegrade) ? " C" : " F"); + JsonWrite(SensorStatus, CN_reading, String(LastReading) + ((TempUnit == TempUnit_t::TempUnitCentegrade) ? " C" : " F")); } while(false);