From 66140ea82314cd0dc818723c05b0039d54272a76 Mon Sep 17 00:00:00 2001 From: Gustice Date: Fri, 14 Nov 2025 21:30:22 +0100 Subject: [PATCH] refactor: Working on SPIT yet again --- .vscode/c_cpp_properties.json | 2 +- .vscode/settings.json | 20 +- CMakeLists.txt | 2 - components/spit/include/spit_client.hpp | 8 +- components/spit/include/spit_message.hpp | 18 +- components/spit/include/spit_processor.hpp | 321 +++++ components/spit/include/spit_type.hpp | 3 +- components/spit/src/spit_client.cpp | 12 +- components/spit/src/spit_message.cpp | 12 +- components/spit/src/spit_processor.cpp | 1235 +++++++++++++++++ components/spit/test/CMakeLists.txt | 5 + components/spit/test/test_spit_client.cpp | 123 ++ components/spit/uTest/spitClientTest.cpp | 79 -- components/spit/uTest/spitProcessorTest.cpp | 170 +++ .../spit/uTest/spitProcessor_complexTest.cpp | 511 +++++++ esp_idf_project_configuration.json | 4 +- main/watchMain.cpp | 6 +- sdkconfig | 20 + test/unitOnTarget/CMakeLists.txt | 2 +- test/unitOnTarget/main/unitTest.cpp | 8 +- 20 files changed, 2444 insertions(+), 117 deletions(-) create mode 100644 components/spit/include/spit_processor.hpp create mode 100644 components/spit/src/spit_processor.cpp create mode 100644 components/spit/test/CMakeLists.txt create mode 100644 components/spit/test/test_spit_client.cpp delete mode 100644 components/spit/uTest/spitClientTest.cpp create mode 100644 components/spit/uTest/spitProcessorTest.cpp create mode 100644 components/spit/uTest/spitProcessor_complexTest.cpp diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 3f579ae..4396ca2 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -2,7 +2,7 @@ "configurations": [ { "name": "ESP-IDF", - "compileCommands": "/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build_uTest/compile_commands.json", + "compileCommands": "/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build/compile_commands.json", "includePath": [ "${config:idf.espIdfPath}/components/**", "${config:idf.espIdfPathWin}/components/**", diff --git a/.vscode/settings.json b/.vscode/settings.json index 5930075..2543558 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,5 +38,21 @@ "--background-index", "--query-driver=/home/gustice/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20241119/riscv32-esp-elf/bin/riscv32-esp-elf-gcc", "--compile-commands-dir=/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build_uTest" - ] -} + ], + "cmake.debugConfig": { + "setupCommands": [ + { + "description": "Skip standard library code", + "text": "skip file /usr/include/*" + }, + { + "description": "Skip GCC internal code", + "text": "skip file /usr/lib/gcc/*" + }, + { + "description": "Skip std namespace", + "text": "skip namespace std" + } + ] + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 368dd37..d6eab38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,5 @@ cmake_minimum_required(VERSION 3.16) -option(BUILD_UNIT_TESTS "Build unit tests instead of main app" OFF) - if(TgtEnv STREQUAL "Host") message("Using Host-Branch") add_subdirectory("test/unitOnHost") diff --git a/components/spit/include/spit_client.hpp b/components/spit/include/spit_client.hpp index 5fe9903..d107a01 100644 --- a/components/spit/include/spit_client.hpp +++ b/components/spit/include/spit_client.hpp @@ -238,7 +238,7 @@ class SClient : ISadClient { * @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd * @return the pointer to the new SPITType. */ - SType *createSPITTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration); + SType *createTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration); /** * Creates a SPITType for application actions.
@@ -252,11 +252,11 @@ class SClient : ISadClient { * @param p_ProjectIndepended true = the SPITType belongs to a specific project, false = the SpitType always exists for every project * @return the pointer to the new SPITType. */ - SType *createSPITType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended); + SType *createType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended); private: - // receive SPITTypes - void parseReportSPITType(Message::ReportType &message); + // receive SPIT-Types + void parseReportType(Message::ReportType &message); void parseRemoveSPITType(Message::RemoveType &message); int sendSPITTypeInternal(SType &spitType); diff --git a/components/spit/include/spit_message.hpp b/components/spit/include/spit_message.hpp index c35533a..b50b44a 100644 --- a/components/spit/include/spit_message.hpp +++ b/components/spit/include/spit_message.hpp @@ -389,7 +389,7 @@ class Message { private: bool mConfirmed{}; - string mSPITTypeID{}; + string mTypeID{}; bool mFixed{}; bool mServerRemote{}; bool mServerProjectIndepended{}; @@ -405,7 +405,7 @@ class Message { bool parse(const std::vector &message); bool getConfirmed() const { return mConfirmed; } - const string getID() const { return mSPITTypeID; } + const string getID() const { return mTypeID; } bool getFixed() const { return mFixed; } bool getServerRemote() const { return mServerRemote; } bool getServerProjectIndepended() const { return mServerProjectIndepended; } @@ -417,7 +417,7 @@ class Message { ReportType(); void setConfirmed(bool p_Confirmed) { mConfirmed = p_Confirmed; } - void setID(string iD) { mSPITTypeID = iD; } + void setID(string iD) { mTypeID = iD; } void setFixed(bool p_Fixed) { mFixed = p_Fixed; } void setServerRemote(bool p_IsServerRemote) { mServerRemote = p_IsServerRemote; } void setServerProjectIndepended(bool p_ProjectIndpended) { mServerProjectIndepended = p_ProjectIndpended; } @@ -437,7 +437,7 @@ class Message { static constexpr int BYTESLENGTH = 45; private: - string mSPITTypeID{}; + string mTypeID{}; public: RemoveType(const RemoveType &orig); @@ -445,11 +445,11 @@ class Message { RemoveType(unique_ptr
header); bool parse(const std::vector &message); - const string getID() const { return mSPITTypeID; } + const string getID() const { return mTypeID; } // Send RemoveType(); - void setID(string iD) { mSPITTypeID = iD; } + void setID(string iD) { mTypeID = iD; } bool fillBytes(std::vector &message); }; @@ -468,7 +468,7 @@ class Message { bool mFixed{}; bool mServerRemote{}; string mSPITObjectName{}; - string mSPITTypeID{}; + string mTypeID{}; string mServerParams{}; uint64_t mFrameStart{}; uint64_t mFrameLength{}; @@ -493,7 +493,7 @@ class Message { bool getFixed() const { return mFixed; } bool getServerRemote() const { return mServerRemote; } const string getName() const { return mSPITObjectName; } - const string getSPITTypeID() const { return mSPITTypeID; } + const string getSPITTypeID() const { return mTypeID; } const string getServerParams() const { return mServerParams; } uint64_t getFrameStart() const { return mFrameStart; } uint64_t getFrameLength() const { return mFrameLength; } @@ -515,7 +515,7 @@ class Message { void setFixed(bool p_Fixed) { mFixed = p_Fixed; }; void setServerRemote(bool p_IsRemote) { mServerRemote = p_IsRemote; }; void setName(string p_Name) { mSPITObjectName = p_Name; }; - void setSPITTypeID(string iD) { mSPITTypeID = iD; }; + void setSPITTypeID(string iD) { mTypeID = iD; }; void setServerParams(string p_Parameters) { mServerParams = p_Parameters; }; void setFrameStart(uint64_t p_StartTime) { mFrameStart = p_StartTime; }; void setFrameLength(uint64_t p_Length) { mFrameLength = p_Length; }; diff --git a/components/spit/include/spit_processor.hpp b/components/spit/include/spit_processor.hpp new file mode 100644 index 0000000..7b01a1f --- /dev/null +++ b/components/spit/include/spit_processor.hpp @@ -0,0 +1,321 @@ +#pragma once + +#include "sad_DetectedServer.hpp" +#include "spit_object.hpp" +#include "spit_player.hpp" +#include "spit_type.hpp" +#include "spit_message.hpp" +#include "spit_repo.hpp" +#include +#include +#include + +using namespace std; + +namespace spit { + +class SProcessor { + public: + /** Maximal length of a SPITMessage*/ + static const int MAXSPITMESSAGEBYTECOUNT = 512; + + enum class ProjUpdate { + ServerLoaded, + StartTransfer, + EndTransfer, + ServerClosed, + }; + enum class ServerEvent { + Detect, + Lost, + Changed, + }; + enum class ObjectEvent { + Created, + Changed, + Deleted + }; + enum class Connection { + None = 0, // No Connection established.
Either no connect tried or disconnected + NoneServer = 1, // Server has disconnected + Lost = 2, // The connection is lost
Either because of a network crash or because the server no longer responds. + Ok = 3, // Connection to the serv er is established. + TryConnection = 4, // A connection to the server is tried. + }; + + struct Callbacks { + function onServerEvent; + function onConnectionStatus; + function onProjectUpdate; + function onSpitType; + function onSpitObject; + function onPlay; + function onPlaySpitType; + function onPlayRemoteObjectStatus; + function onCheckSpitTypeVeto; + function onCheckSpitObjectVeto; + }; + + //------ PlayerType ------ + public: + /** continous main player, time value can be used like a timecode.
The time value is the position in server's project.
A server should use only one main player.*/ + static constexpr char PLAYERTYPE_MAIN = 0x02; + /** continous player. This player plays SPIT objects sometime during the project.*/ + static constexpr char PLAYERTYPE_CONTINOUS = 0x01; + /** diescrete player. This player is used to transmit single discrete values.*/ + static constexpr char PLAYERTYPE_DISCRETE = 0x00; + + //------ Value Flag ------ + //------ used by sendRemoteObject + public: + /**Set the given value directly*/ + static constexpr char VALUEFLAG_DIRECT = 0x00; + /**Increase the existing value by the given value.
This is usefull e.g. when instead of a fader a endless wheel is used*/ + static constexpr char VALUEFLAG_INCREASE = 0x01; + /**Decrease the existing value by the given value.
This is usefull e.g. when instead of a fader a endless wheel is used*/ + static constexpr char VALUEFLAG_DECREASE = 0x02; + static constexpr int MAX_OVERTAKING_SPIT_MESSAGES = 10; + + //----- SProcessor ----- + public: + SProcessor(string name, string projName, string hostName, string guid, Callbacks calls); + virtual ~SProcessor(); + + private: + Callbacks mCallbacks; + + Connection mConnectionStatus{Connection::None}; + bool mDisconnectedByServer{}; // flag true = when server disconnects + string mGuid; + string mName; + string mProjName; + string mComputerName; + + string mClientProjectName; + + uint8_t mMessageNumberSend{1}; + int mMessageNumberReceived{-1}; // set to -1 because the first received message will set the number (1..255) + vector> mOvertakingMessages; + + // Server's info filled by parseConnectAnswer + string mServerID{}; + string mServerName{}; + string mServerComputerName{}; + int mServerStepTime{-1}; + + //--- Server Project --- + string mServerProjectID; + string mServerProjectName; + int mServerFramesPerSecond; + + public: + /** The ID of the client.
Every client instance should set an unique id*/ + string getID() { return mGuid; } + /** The name of the client, should be set by the user app*/ + string getName() { return mName; } + //----- Computer Params ----- + /** The name of the client's host computer*/ + string getComputerName() { return mComputerName; } + void setClientProjectName(string clientProjectName) { mClientProjectName = clientProjectName; } + string getClientProjectName() { return mClientProjectName; } + + // connected Server Infos + /** The ID of the connected SPITServer*/ + string getServerID() { return mServerID; } + /** The host computername of the connected SPITServer*/ + string getServerComputerName() { return mServerComputerName; } + /** The name of the connected SPITServer*/ + string getServerName() { return mServerName; } + + /** Expected Refreah Rate of the connectd SPITServer.
+ * When the server plays objects, it will do so at discrete time steps.
+ * Play events will take place in these time steps.. + */ + int getServerStepTime() { return mServerStepTime; } + + /** Should be called when the client wants to close his project*/ + void clientProjectClose(); + /** + * Should be called whenever the client has a project loaded + */ + void clientProjectLoaded(); + + void setActionSPITType(string spitypeID, bool actionAssigned); + void setActionSPITObject(string objectID, bool actionAssigned); + + //--------------- SPITMessage --------------- + private: + // Reconnect to the server when connection is lost see eventConnectionStatus and eventServerDetected + bool _doReconnect{}; // true = on eventServerDetected connect to the server identified by mServerID + public: + std::vector createMessage(Message::OPPart & spitMessageOPPart); + void checkParseMessageData(vector data); + + + //--------------- ServerAutoDetection SAD --------------- + public: + /** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before.*/ + void startServerAutoDetect(); + /** Stops the autodetection of SPITServers in the local network*/ + void stopServerAutoDetect(); + /** Called every time a new SPITServer is detetced in the local network */ + void eventServerDetected(SadDetectedServer &server); + /** Called every time a prior detected SPITServer is is no longer found.*/ + void eventServerLost(SadDetectedServer &server); + void eventServerChanged(SadDetectedServer &server); + + //--------------- Connection --------------- + public: + /** + * Tries a connection to the SPITServer + * @param p_ServerIP ip address of the SPITServer + * @param p_ServerPort port of the SPITServer + * @param p_ClientIP IP of the client + * @param p_ClientPort if "0" any free port will be used + * @param p_LoginName maybe some SPITServer need a login - liveSHOWsoftware will not. + * @param p_LoginPassword maybe some SPITServer need a login - liveSHOWsoftware will not + * @return true = the connection try is ok, SPITServer will answer with COnnectAnswer and an eventConnectionStatus will occur.
+ * false = something is going wrong. (client could not bind) + */ + bool connect(string serverIP, string serverPort, string clientIP, string clientPort, string loginName = "", string loginPassword = ""); + /** + * Terminates the connection to the SPITServer. + */ + void disconnect(); + + private: + void disconnectInternal(Connection cause); + void resetMessageNumberReceived(); + void parseMessage(Message& message); + void addOvertakingMessage(unique_ptr message); + void parseConnectAnswer(Message::ConnectAnswer &message); + void parseDisconnect(Message::Disconnect &message); + void parseWatchdog(Message::Watchdog &message); + void parseWatchdogAnswer(Message::WatchdogAnswer &message); + + public: + /** Used internally*/ + void sendWatchdog(); + /** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/ + void eventWatchdogLost(); + //--------------- SPIT Project --------------- + private: + void parseReportProject(Message::ReportProject &message); + void parseCloseProject(Message::CloseProject &message); + + public: + /** Returns the SPITServer's project ID - may be the same as the project's name*/ + string getServerProjectID(); + /** Returns the SPITServer's project name*/ + string getServerProjectName(); + /** Returns frame rate per second. This is the time resolution in which the server transmits time data. The unit of time data is always frames.*/ + int getServerFramesPerSecond(); + + private: + void parseRequestProjectTransfer(Message::RequestProjectTransfer &message); + void parseStartProjectTransfer(Message::StartProjectTransfer &message); + void parseEndProjectTransfer(Message::EndProjectTransfer &message); + + public: + // static void sendProject(SClient *p_PtrSProcessor); + + // --------------- SPIT Types --------------- + public: + /** + * Creates a fixed SPITType for application actions that are always present and project independent.
+ * Fixed SPIT types cannot be changed or deleted by the server.
+ * These SPITTypes will be automatically added to the SPITType-List and sended to the server. + * @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids. + * @param p_GroupName a name which groups the actions/SPITTypes + * @param p_Name the name of the Action/SPITType + * @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd + * @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd + * @return the pointer to the new SPITType. + */ + SType *createTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration); + + /** + * Creates a SPITType for application actions.
+ * These SPITTypes will be automatically added to the SPITType-List and sended to the server. + * @param p_ID an unique of the SPITType, these are always the same per client approach. Different client approaches should use different ids. + * @param p_GroupName a name which groups the actions/SPITTypes + * @param p_Name the name of the Action/SPITType + * @param p_DefaultDelay maybe there is an default delay until the action starts, this is only used for graphical representations, 0 is allowd + * @param p_DefaultDuration maybe the action has a default duration, this is only used for graphical representations, 0 is allowd + * @param p_Fixed true = the server is not allowed to change this SPITType, false = the server may change or delete this SPITType + * @param p_ProjectIndepended true = the SPITType belongs to a specific project, false = the SpitType always exists for every project + * @return the pointer to the new SPITType. + */ + SType *createType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended); + + private: + // receive SPIT-Types + void parseReportType(Message::ReportType &message); + void parseRemoveSPITType(Message::RemoveType &message); + int sendSPITTypeInternal(SType &sType); + + public: + /** + * If a client wants to change a SPITType, he should send it to the server.
+ * If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the change.
+ * @param spitypeID the id of the SPITType to remove. + * @return 0 = is sended, -1 = is not sended + */ + bool changeSPITType(SType *spitType); + /** + * If a client wants to remove a SPITType, he should send it to the server.
+ * If the SPITTye is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the deletion.
+ * @param spitypeID the id of the SPITType to remove. + * @return 0 = is sended, -1 = is not sended + */ + int removeSPITType(string spitypeID); + + public: + //--------------- SPIT Objects --------------- + private: + void parseReportSPITObject(Message::ReportObject &message); + void parseRemoveSPITObject(Message::RemoveObject &message); + int sendSPITObjectInternal(SObject *ptrObject); + + public: + /** + * When the client changes a SPITObject (normally the client should not do this), then it should send the changes to the SPITServer.
+ * The SPITServer may discard the changes and an eventSPITObject occurs.
+ * @param spitObject the pointer to the changed SPITObject. + * @return 0 = sended, -1 = not sended + */ + bool changeSPITObject(SObject *spitObject); + /** + * When the client removes a SPITObject (normally the client should not do this), then he should send it to the SPITServer.
+ * The SPITServer may discard the deletion and an eventSPITObject occurs.
+ * @param objectID the id of the SPITObject to remove. + * @return 0 = sended, -1 = not sended + */ + int removeSPITObject(string objectID); + + public: + //--------------- Play SPIT Objects --------------- + private: + void parsePlaySPITStart(Message::PlayStart &message); + void parsePlaySPITObject(Message::PlayObject &message); + void parsePlaySPITEnd(Message::PlayEnd &message); + void parseReportPlayStatus(Message::ReportPlayStatus &message); + + public: + //--------- Remote ---------- + void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00); + + private: + bool mAbortSearch{}; + bool sAnswered{}; + void answerWatchdog() { + sAnswered = true; + } + + SpitRepo mSpitObjects; + SpitRepo mRemoteSpitObjects; + SpitRepo mSpitTypes; + SpitRepo mRemoteSpitTypes; +}; + +} \ No newline at end of file diff --git a/components/spit/include/spit_type.hpp b/components/spit/include/spit_type.hpp index ed8c1bb..5b3c0ef 100644 --- a/components/spit/include/spit_type.hpp +++ b/components/spit/include/spit_type.hpp @@ -1,6 +1,5 @@ #pragma once -#include "spit_socket.hpp" #include "spit_message.hpp" #include "spit_repo.hpp" @@ -88,7 +87,7 @@ class SType { private: bool mConfirmed{}; string mID; - bool mCreatedByClient; // flag true = the SPITTyype is created by the client + bool mCreatedByClient{}; // flag true = the SPITTyype is created by the client // false = the SType is received from the server public: diff --git a/components/spit/src/spit_client.cpp b/components/spit/src/spit_client.cpp index bbe8769..3a39a8b 100644 --- a/components/spit/src/spit_client.cpp +++ b/components/spit/src/spit_client.cpp @@ -258,7 +258,7 @@ void SClient::resetMessageNumberReceived() { void SClient::checkParseMessage(unique_ptr p_SPITMessage) { answerWatchdog(); - if (!p_SPITMessage || !p_SPITMessage->getHeader() || p_SPITMessage->getOPPart()) { + if (!p_SPITMessage || !p_SPITMessage->getHeader() || !p_SPITMessage->getOPPart()) { ESP_LOGD(TAG, "Client::parseMessage incomplete message"); return; } @@ -370,7 +370,7 @@ void SClient::parseMessage(unique_ptr message) { break; //----- SPIT Types ------ case Message::ReportType::OPFLAG: - parseReportSPITType(message->getAs()); + parseReportType(message->getAs()); break; case Message::RemoveType::OPFLAG: parseRemoveSPITType(message->getAs()); @@ -785,7 +785,7 @@ void SClient::parseEndProjectTransfer(Message::EndProjectTransfer &message) { } //----- SPIT Types ------ -void SClient::parseReportSPITType(Message::ReportType &message) { +void SClient::parseReportType(Message::ReportType &message) { ESP_LOGD(TAG, "parse ReportType ID %s Name %s",message.getID().c_str(), message.getName().c_str()); SType *ptrSPITType; bool boolNew = false; @@ -931,11 +931,11 @@ int SClient::removeSPITType(string p_SPITTypeID) { return -1; } -SType *SClient::createSPITTypeFixed(string iD, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration) { - return createSPITType(iD, p_GroupName, p_Name, p_DefaultDelay, p_DefaultDuration, true, true); +SType *SClient::createTypeFixed(string iD, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration) { + return createType(iD, p_GroupName, p_Name, p_DefaultDelay, p_DefaultDuration, true, true); } -SType *SClient::createSPITType(string p_ID, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) { +SType *SClient::createType(string p_ID, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) { bool boolNew; SType *ptrSPITType = mSpitTypes.getEntry(p_ID); if (ptrSPITType == nullptr) { diff --git a/components/spit/src/spit_message.cpp b/components/spit/src/spit_message.cpp index 3729786..0777670 100644 --- a/components/spit/src/spit_message.cpp +++ b/components/spit/src/spit_message.cpp @@ -700,7 +700,7 @@ bool Message::ReportType::parse(const std::vector &message) { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); mConfirmed = getBoolean(message, mParseOffset).value(); - mSPITTypeID = getString(message, mParseOffset, 41).value(); + mTypeID = getString(message, mParseOffset, 41).value(); mFixed = getBoolean(message, mParseOffset).value(); mServerRemote = getBoolean(message, mParseOffset).value(); mServerProjectIndepended = getBoolean(message, mParseOffset).value(); @@ -731,7 +731,7 @@ bool Message::ReportType::fillBytes(std::vector &message) { mParseOffset = mHeader->BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); mParseOffset += setBoolean(mConfirmed, message, mParseOffset); - mParseOffset += setString(mSPITTypeID, message, mParseOffset, 41); + mParseOffset += setString(mTypeID, message, mParseOffset, 41); mParseOffset += setBoolean(mFixed, message, mParseOffset); mParseOffset += setBoolean(mServerRemote, message, mParseOffset); mParseOffset += setBoolean(mServerProjectIndepended, message, mParseOffset); @@ -762,7 +762,7 @@ bool Message::RemoveType::parse(const std::vector &message) { try { mParseOffset = Header::BYTESLENGTH; mBytesCount = getInt(message, mParseOffset).value(); - mSPITTypeID = getString(message, mParseOffset, 41).value(); + mTypeID = getString(message, mParseOffset, 41).value(); } catch (...) { ESP_LOGE(TAG, "failed to parse RemoveType message"); return false; @@ -785,7 +785,7 @@ bool Message::RemoveType::fillBytes(std::vector &message) { try { mParseOffset = Header::BYTESLENGTH; mParseOffset += setInt(mBytesCount, message, mParseOffset); - mParseOffset += setString(mSPITTypeID, message, mParseOffset, 41); + mParseOffset += setString(mTypeID, message, mParseOffset, 41); } catch (...) { ESP_LOGE(TAG, "failed to create RemoveType message"); return false; @@ -815,7 +815,7 @@ bool Message::ReportObject::parse(const std::vector &message) { mFixed = getBoolean(message, mParseOffset).value(); mServerRemote = getBoolean(message, mParseOffset).value(); mSPITObjectName = getString(message, mParseOffset, 64).value(); - mSPITTypeID = getString(message, mParseOffset, 41).value(); + mTypeID = getString(message, mParseOffset, 41).value(); mServerParams = getString(message, mParseOffset, 64).value(); mFrameStart = getLong(message, mParseOffset).value(); mFrameLength = getLong(message, mParseOffset).value(); @@ -865,7 +865,7 @@ bool Message::ReportObject::fillBytes(std::vector &message) { mParseOffset += setBoolean(mFixed, message, mParseOffset); mParseOffset += setBoolean(mServerRemote, message, mParseOffset); mParseOffset += setString(mSPITObjectName, message, mParseOffset, 64); - mParseOffset += setString(mSPITTypeID, message, mParseOffset, 41); + mParseOffset += setString(mTypeID, message, mParseOffset, 41); mParseOffset += setString(mServerParams, message, mParseOffset, 64); mParseOffset += setLong(mFrameStart, message, mParseOffset); mParseOffset += setLong(mFrameLength, message, mParseOffset); diff --git a/components/spit/src/spit_processor.cpp b/components/spit/src/spit_processor.cpp new file mode 100644 index 0000000..285344d --- /dev/null +++ b/components/spit/src/spit_processor.cpp @@ -0,0 +1,1235 @@ + +#include "spit_processor.hpp" +#include "esp_log.h" + +namespace spit { +static const char *TAG = "SPIT"; + +/** + * Create a new SPIT_client instance, should be done once by the user app. + * @param p_SPITClientInterface the user app should implement the SPIT_ClientInterface. + */ +SProcessor::SProcessor(string name, string projName, string hostName, string guid, Callbacks calls) // @todo + : mCallbacks(calls), + mGuid(guid), + mName(name), + mProjName(projName), + mComputerName(hostName) { +} + +SProcessor::~SProcessor() { // @todo + stopServerAutoDetect(); + disconnectInternal(Connection::None); +} + +void SProcessor::clientProjectClose() { // @todo + if (mConnectionStatus == Connection::Ok) { + ESP_LOGI(TAG, " ... tidy up ressources"); + Message::CloseProject closeSPITProject(mProjName); + // if (sendSPITMessage(closeSPITProject) < 0) { + // ESP_LOGD(TAG, "Client could not send Client's ReportProject"); + // } + } +} + +void SProcessor::clientProjectLoaded() { // @todo + // set confirmed = false for all SPITTypes and SPITObjects + SType::setConfirmedFalse(mSpitTypes); + SObject::setConfirmedFalse(mSpitObjects); + + if (mConnectionStatus == Connection::Ok) { + // send ReportProject to the server + Message::ReportProject reportSPITProject(mProjName, mProjName); + reportSPITProject.setFramesPerSecond(0); + // if (sendSPITMessage(reportSPITProject) < 0) { + // ESP_LOGD(TAG, "SPIT_CLient::clientProjectLoaded could not send Client's ReportProject"); + // } + + // send RequestProjectTransfer + Message::RequestProjectTransfer sMRequestProjectTransfer; + // if (sendSPITMessage(sMRequestProjectTransfer) < 0) { + // ESP_LOGD(TAG, "SPIT_CLient::clientProjectLoaded could not send RequestProjectTransfer"); + // } + } +} + +/** + * Virtual construct - means actionAssigned for SPITTypes is is not implemented in SPITProtocol. + * This can used to setActionAssigned to all SPITObjects with this SPITType. + * This may be used in the case when the same action should be done for every SPITObject with this SPITType associated. + * This tells the server not what action is done, but it tells the server that there is an action. + * @param typeId the id of the SPITType + * @param actionAssigned + */ +void SProcessor::setActionSPITType(string typeId, bool actionAssigned) { // @todo + SType *spitType = mSpitTypes.getEntry(typeId); + if (spitType == nullptr) + return; + if (spitType->ActionAssigned.set(actionAssigned)) { + sendSPITTypeInternal(*spitType); + for (auto& [key, value] : mSpitObjects.getRepo()) { + if (value->SPITTypeID.get() == spitType->getID()) { + if (value->setActionAssignedType(actionAssigned) == true) { + sendSPITObjectInternal(value.get()); + } + } + } + } +} + +/** This should be called if the user wants to associate/remove an action with a SPITObject. */ +void SProcessor::setActionSPITObject(string spitObjId, bool actionAssigned) { // @todo + SObject *spitObject = mSpitObjects.getEntry(spitObjId); + if (spitObject == nullptr) + return; + if (spitObject->setActionAssigned(actionAssigned) == true) { + sendSPITObjectInternal(spitObject); + } +} +//---------- ServerAutoDetection SAD ----------- + +/** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before. + * If a SPITServer is detected in the locale network an eventServerDetected occurs. + */ +void SProcessor::startServerAutoDetect() { // @todo + // if (mDisconnectedByServer == true) { + // // Server has previously disconnected -> do not start ServerAutodetect directly + // fos::Task::delayMs(1000); // sleep a little to give the SPITServer time to clean up its stuff + // } + // SadDetectedServer::clearDetectedServers(); + // if (!sThread) { + // sThread = new fos::TaskT(SProcessor::processSocketTask, *this, "spitSock", fos::Task::DefaultStackSize * 2); // @todo + // } + // mAbortSearch = false; + // sStartSad.give(); +} + +/** Stops the auto detection of SPIT servers. */ +void SProcessor::stopServerAutoDetect() { // @todo + mAbortSearch = true; +} +/** + * If a new server was found by the ServerAutoDetect mechanism, this function is called. + * To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect. + * If a server can be reached via several IP addresses, the IP address is selected according to the following preference: + */ +void SProcessor::eventServerDetected(SadDetectedServer &server) { // @todo + mCallbacks.onServerEvent(ServerEvent::Detect, server); + // If a connection has been established and the connection is lost -> reconnect + if (_doReconnect) { + if (mServerID == server.getID()) { + stopServerAutoDetect(); + ESP_LOGI(TAG, "reconnect to %s / %s", server.getIP().data(), server.getPort().data()); + if (connect(server.getIP(), server.getPort(), server.getClientIP(), "0")) { + return; + } + } + } + // Stop auto detection because a suitable server was found + stopServerAutoDetect(); + ESP_LOGI(TAG, "connect to %s / %s", server.getIP().data(), server.getPort().data()); + if (!connect(server.getIP(), server.getPort(), server.getClientIP(), "0" /*= any port*/)) { + // connection message could not be sent -> better to restart AutoDetection + startServerAutoDetect(); + } +} + +/** + * If a SPITServer is not more found, this function is called. + * To do so the SAD_Client ServerAutoDetect has to be startet - see SAD_Client::startServerAutoDetect. + */ +void SProcessor::eventServerLost(SadDetectedServer &server) { // @todo + mCallbacks.onServerEvent(ServerEvent::Lost, server); +} + +void SProcessor::eventServerChanged(SadDetectedServer &server) { // @todo + mCallbacks.onServerEvent(ServerEvent::Changed, server); + // tryConnection(detectedServer); +} + +// void MyApp::tryConnection(const SadDetectedServer &detected) { +// // fetch the infoemations from the detected +// bool boolSuccess = false; +// bool boolPossibleConnect = checkPossibleConnection(detected); + +// if (boolPossibleConnect == false) +// return; + +// // -------------------------------------- +// // You have three Options to use the detected server +// // OPTION 1 Use the first server found +// // OPTION 2 Use the first server found that fulfills specific conditions +// // OPTION 3 take a copy of the detected and do connection later +// // SadDetectedServer o_DetectedServer = detected; //this will call the copy constructor +// // --------------------------------------- + +// // Excample use the first detected LOOPBACK server, means the server runs on the same computer as this client +// // if (detected.getIpIsLoopback() == true) { //omit the if condition if you want to use the first server found + +// boolSuccess = false; +// // Stop auto detection because a suitable server was found +// stopServerAutoDetect(); +// if (mSPIT_Client != nullptr) { +// mServerProjectName = detected.getProjectName(); +// mServerIP = detected.getIP(); + +// #if defined(DEBUGOUTPUT) +// ESP_LOGD(TAG, "MySPITApp: connect to %s ", detected.getIP().data()); +// #endif +// // Use the mBoardNumber as login name +// string stringLoginName = ""; +// string stringLoginPassword = ""; +// boolSuccess = mSPIT_Client->connect(detected.getIP(), detected.getPort(), detected.getClientIP(), stringLoginName, stringLoginPassword); // ClientPort = "0" meeans use any port +// } +// if (boolSuccess == false) { +// // connection message could not be sent +// // perhaps restart AutoDetection +// startServerAutoDetect(); +// } else { +// // WAITING FOR CONNECTION ANSWER +// // If the Server is closed in the meantime no answer will return +// //-> connect(..) has started the watchdog +// } + +// // } //Excample +// } + +std::vector SProcessor::createMessage(Message::OPPart &opPart) { + if (mMessageNumberSend == 255) + mMessageNumberSend = 1; + else + mMessageNumberSend++; + opPart.setMessageNumber(mMessageNumberSend); + opPart.setServerInfoInHeader(mGuid, mServerID); + + int opFlag = opPart.getHeader()->getType(); + try { + return Message::createMessage(opPart); + } catch (...) { + ESP_LOGD(TAG, "Exception client OPFlag: %d", opFlag); + } + return {}; +} +// todo Delete SProcessor::sendSPITMessage(Message::OPPart &opPart + +// void SProcessor::receiveSPITMessage(SClient &rM) { // @todo +// char buffer[MAXSPITMESSAGEBYTECOUNT + 1]; +// int rdLen; +// while (rM.mStopReceiveMessages == false) { +// rdLen = rM.mSocket.receiveMessage(buffer, MAXSPITMESSAGEBYTECOUNT, nullptr); +// if (rdLen < 0) { +// if (rM.mStopReceiveMessages) { +// return; +// } +// continue; +// } +// auto vec = vector(buffer, buffer + rdLen); +// rM.checkParseMessageData(move(spitMsg)); +// // rM.checkParseMessage(move(spitMsg)); +// } +// } + +void SProcessor::resetMessageNumberReceived() { // @todo + mMessageNumberReceived = -1; + mOvertakingMessages.clear(); +} + +void SProcessor::checkParseMessageData(vector data) { + auto message = make_unique(data); + answerWatchdog(); + if (!message->getHeader() || !message->getOPPart()) { + ESP_LOGD(TAG, "Client::parseMessage incomplete message"); + return; + } + + int msgNum = (int)(message->getHeader()->getMessageNumber() & 0xFF); + + if (msgNum == 0) { + parseMessage(*message); + return; + } + if (mMessageNumberReceived < 0) { + mMessageNumberReceived = msgNum; + parseMessage(*message); + return; + } + + int msgNumNext = mMessageNumberReceived + 1; + if (msgNumNext > 255 || msgNumNext < 1) + msgNumNext = 1; + + if (msgNum == msgNumNext) { + mMessageNumberReceived = msgNum; + parseMessage(*message); + + // check overtaking messages + auto it = mOvertakingMessages.begin(); + while (mOvertakingMessages.size() > 0) { + + msgNumNext = mMessageNumberReceived + 1; + if (msgNumNext > 255 || msgNumNext < 1) + msgNumNext = 1; + + auto &overtakingMessage = *it; + msgNum = (int)(overtakingMessage->getHeader()->getMessageNumber() & 0xFF); + + if (msgNum == msgNumNext) { + mMessageNumberReceived = msgNum; + parseMessage(*overtakingMessage); + mOvertakingMessages.erase(it); + + it = mOvertakingMessages.begin(); + } else { + break; + } + } + + } else { + // p_SPITMessage has overtaken another message + addOvertakingMessage(move(message)); + } +} + +void SProcessor::addOvertakingMessage(unique_ptr message) { // @todo + if (!message) { + return; + } + if (mOvertakingMessages.size() > MAX_OVERTAKING_SPIT_MESSAGES) { + ESP_LOGD(TAG, "Client receiveing: perhaps message lost !!!!!"); + } + + int intMessageNumber = (int)(message->getHeader()->getMessageNumber() & 0xFF); + for (auto it = mOvertakingMessages.begin(); it != mOvertakingMessages.end(); ++it) { + const auto &overtaking = *it; + int intOvertakingMessageNumber = (int)(overtaking->getHeader()->getMessageNumber() & 0xFF); + if (intMessageNumber < intOvertakingMessageNumber) { + mOvertakingMessages.insert(it, move(message)); + return; + } + } + mOvertakingMessages.push_back(move(message)); +} + +void SProcessor::parseMessage(Message& message) { // @todo + answerWatchdog(); + if (!message.getHeader() || !message.getOPPart()) { + ESP_LOGD(TAG, "Client::parseMessage incomplete message"); + return; + } + + switch (message.getType()) { + //----- Connection ----- + case Message::ConnectAnswer::OPFLAG: + parseConnectAnswer(message.getAs()); + break; + case Message::Disconnect::OPFLAG: + parseDisconnect(message.getAs()); + break; + case Message::ReportProject::OPFLAG: + parseReportProject(message.getAs()); + break; + case Message::Watchdog::OPFLAG: + parseWatchdog(message.getAs()); + break; + case Message::WatchdogAnswer::OPFLAG: + parseWatchdogAnswer(message.getAs()); + break; + //----- SPIT Project ----- + case Message::StartProjectTransfer::OPFLAG: + parseStartProjectTransfer(message.getAs()); + break; + case Message::CloseProject::OPFLAG: + parseCloseProject(message.getAs()); + break; + case Message::RequestProjectTransfer::OPFLAG: + parseRequestProjectTransfer(message.getAs()); + break; + case Message::EndProjectTransfer::OPFLAG: + parseEndProjectTransfer(message.getAs()); + break; + //----- SPIT Types ------ + case Message::ReportType::OPFLAG: + parseReportType(message.getAs()); + break; + case Message::RemoveType::OPFLAG: + parseRemoveSPITType(message.getAs()); + //----- SPIT Objects ------ + break; + case Message::ReportObject::OPFLAG: + parseReportSPITObject(message.getAs()); + break; + case Message::RemoveObject::OPFLAG: + parseRemoveSPITObject(message.getAs()); + break; + //----- Play SPIT Objects ------ + case Message::PlayStart::OPFLAG: + parsePlaySPITStart(message.getAs()); + break; + case Message::PlayObject::OPFLAG: + parsePlaySPITObject(message.getAs()); + break; + case Message::PlayEnd::OPFLAG: + parsePlaySPITEnd(message.getAs()); + break; + case Message::ReportPlayStatus::OPFLAG: + parseReportPlayStatus(message.getAs()); + break; + default: + ESP_LOGD(TAG, "Client::parseMessage: Unknown Message"); + } +} + +//----- Connection ------ +/** + * Tries to connect to a SPITServer. + * @param serverIP the ip address of the SPIT server + * @param serverPort the port number of the SPIT server + * @param clientIP the local IP address of the client + * @param clientPort the port number of the Client, if "0" the OS uses any possible port number + * @param loginName login user name (liveSHOW does not use this -> mayby "" + * @param loginPassword login user password (liveSHOW does not use this -> mayby "" + * @return false = an error has occured, true = the connect was sent to the server + */ +bool SProcessor::connect(string serverIP, string serverPort, string clientIP, string clientPort, string loginName, string loginPassword) { // @todo + disconnect(); + // mSocket.setConnectionParams(serverIP, serverPort, clientIP, clientPort); + // if (mSocket.bindSocket(clientIP, clientPort) < 0) { + // mStopReceiveMessages = true; + // return false; + // } + Message::Connect sMConnect(mComputerName, mName); + sMConnect.setLoginName(loginName); + sMConnect.setLoginPassword(loginPassword); + sMConnect.setServerIP(serverIP); + if (serverPort.length() <= 0) { + serverPort = "0"; + } + int intServerPort = stoi(serverPort); + sMConnect.setServerPort(intServerPort); + + // if (startReceiveSPITMessages() == false) { + // mStopReceiveMessages = true; + // return false; + // } + resetMessageNumberReceived(); + Connection intOldConnectionStatus = mConnectionStatus; + + mConnectionStatus = Connection::TryConnection; + mCallbacks.onConnectionStatus(mServerID, mServerComputerName, mServerName, mServerStepTime, + mConnectionStatus, intOldConnectionStatus); + + // sleep a little to make sure that the reception of the messages is started + // fos::Task::delayMs(500); + // if (sendSPITMessage(sMConnect) < 0) { + // mConnectionStatus = Connection::None; + // mStopReceiveMessages = true; + // return false; + // } + return true; +} + +/** + * Terminates the connection to the SPITServer. + */ +void SProcessor::disconnect() { // @todo + disconnectInternal(Connection::None); +} + +void SProcessor::disconnectInternal(Connection cause) { // @todo + Connection intOldConnectionStatus = mConnectionStatus; + + mConnectionStatus = cause; + switch (mConnectionStatus) { + case Connection::Lost: + break; + case Connection::None: { + Message::Disconnect sMDisconnect; + // sendSPITMessage(sMDisconnect); + } break; + case Connection::NoneServer: + break; + default: + break; + } + + // stopReceiveSPITMessages(); + mCallbacks.onConnectionStatus(mServerID, mServerComputerName, mServerName, mServerStepTime, + mConnectionStatus, intOldConnectionStatus); + + if (intOldConnectionStatus != Connection::None && intOldConnectionStatus != Connection::NoneServer) { + ESP_LOGI(TAG, "eventConnectionStatus %d ", (int)mConnectionStatus); + switch (mConnectionStatus) { + case SProcessor::Connection::None: // @todo + ESP_LOGD(TAG, "not connected"); + break; + case SProcessor::Connection::NoneServer: // @todo + ESP_LOGD(TAG, "connection terminated by server"); + // call eventProjectClosed because this may not be sended by the server, + // when the connection is closed + mCallbacks.onProjectUpdate(ProjUpdate::ServerClosed, mServerProjectID); + + // Server has terminated the connection -> start a new game + // _doReconnect = false; + startServerAutoDetect(); + break; + case SProcessor::Connection::Lost: // @todo + ESP_LOGD(TAG, "connection lost"); + // Maybe you want to reconnect, see eventServerDetected(...) + // We have lost the connection -> set the flag to true and start the autodetection to reconnect at eventServerDetected(...) + // _doReconnect = true; + startServerAutoDetect(); + break; + default: + break; + } + } +} + +void SProcessor::parseConnectAnswer(Message::ConnectAnswer &message) { // @todo + if (message.getClientID() != mGuid) + return; + + mServerID = message.getServerID(); + mServerComputerName = message.getServerComputerName(); + mServerName = message.getServerName(); + mServerStepTime = message.getStepTime(); + + if (message.getConnected() == false) { + disconnectInternal(Connection::NoneServer); + } else { + message.getStepTime(); + mConnectionStatus = Connection::Ok; + mDisconnectedByServer = false; + ESP_LOGD(TAG, "connection established"); + stopServerAutoDetect(); // normally you should stop the autodetection before you try a connection + // This is redundand + // mStopReceiveMessages = false; + + // Maybe you want to reconnect, see eventServerDetected(...) + // Here the connection is established -> don't reconnect at eventServerDetected(...) + // _doReconnect = false; + } +} + +/** + * The SPIT server was closed + * @param message + */ +void SProcessor::parseDisconnect(Message::Disconnect &message) { // @todo + Connection intCauseDisconnect = Connection::NoneServer; + /* + function o_Callable = bind(&SProcessor::disconnectInternal, this, intCauseDisconnect); // @todo + SPIT_Handler::addCallable(o_Callable); + */ + mDisconnectedByServer = true; + SProcessor::disconnectInternal(intCauseDisconnect); // @todo +} + +//----- Watchdog ------ +/** + * The SPIT server sends a watchdog message at regular intervals. The client responds immediately with WatchdogAnswer + * Conversely, the client also sends a watchdog message at regular intervals and waits for a WatchdogAnswer message. + * This is used to check if the other side is still present. + * @param message + */ +void SProcessor::parseWatchdog(Message::Watchdog &message) { // @todo + // ESP_LOGD(TAG, "parse Watchdog "); + Message::WatchdogAnswer o_WatchdogAnswer; + // sendSPITMessage(o_WatchdogAnswer); +} +/** + * The SPIT server sends a watchdog message at regular intervals. The client responds immediately with WatchdogAnswer + * Conversely, the client also sends a watchdog message at regular intervals and waits for a WatchdogAnswer message. + * This is used to check if the other side is still present. + * @param message + */ +void SProcessor::parseWatchdogAnswer(Message::WatchdogAnswer &message) { // @todo + answerWatchdog(); // is also done by parseMessage +} +void SProcessor::sendWatchdog() { // @todo + int intResult{}; + Message::Watchdog message; + // intResult = sendSPITMessage(message); + if (intResult < 0) { + ESP_LOGW("WDT", "Failed to send Watchdog msg"); + } +} +void SProcessor::eventWatchdogLost() { // @todo + if (mConnectionStatus == Connection::TryConnection) { + disconnectInternal(Connection::NoneServer); + } else { + disconnectInternal(Connection::Lost); + } +} + +//----- SPIT Project ------ +void SProcessor::parseReportProject(Message::ReportProject &message) { // @todo + ESP_LOGD(TAG, "parse ReportProject"); + mServerProjectID = message.getProjectID(); + mServerProjectName = message.getProjectName(); + mServerFramesPerSecond = message.getFramesPerSecond(); + mCallbacks.onProjectUpdate(ProjUpdate::ServerLoaded, mServerProjectID); + + // Set all SPITTypes and SPITObjects confirmed = false + SType::setConfirmedFalse(mSpitTypes); + SObject::setConfirmedFalse(mSpitObjects); + + // Send RequestProjectTransfer + Message::RequestProjectTransfer sMRequestProjectTransfer; + // if (sendSPITMessage(sMRequestProjectTransfer) < 0) { + // ESP_LOGD(TAG, "Client::parseReportProject could not send RequestProjectTransfer"); + // } + + // todo Don't send the ReportProject here it should be sended after parseEndProjectTransfer + // Send client's ReportProject + Message::ReportProject reportProject(mProjName, mProjName); + reportProject.setFramesPerSecond(0); + // if (sendSPITMessage(reportProject) < 0) { + // ESP_LOGD(TAG, "Client::parseReportProject could not send Client's ReportProject"); + // } +} +void SProcessor::parseCloseProject(Message::CloseProject &p_CloseSPITProject) { // @todo + ESP_LOGD(TAG, "parse CloseProject"); + string stringProjectID; + mCallbacks.onProjectUpdate(ProjUpdate::ServerClosed, p_CloseSPITProject.getProjectID()); + SPlayer::clearPlayers(); +} + +string SProcessor::getServerProjectID() { return mServerProjectID; } // @todo +string SProcessor::getServerProjectName() { return mServerProjectName; } // @todo +int SProcessor::getServerFramesPerSecond() { return mServerFramesPerSecond; } // @todo + +void SProcessor::parseRequestProjectTransfer(Message::RequestProjectTransfer &message) { // @todo + ESP_LOGD(TAG, "parse RequestProjectTransfer"); + // StartProjectTransfer + Message::StartProjectTransfer sMStartProjectTransfer; + // if (sendSPITMessage(sMStartProjectTransfer) < 0) { + // return; + // } + + // send all listes SPITTypes + for (const auto& [key, value] : mSpitTypes.getRepo()) { + sendSPITTypeInternal(*value); + // fos::Task::delayMs(10); + } + for (auto& [key, value] : mSpitObjects.getRepo()) { + sendSPITObjectInternal(value.get()); + // fos::Task::delayMs(10); + } + + // EndProjectTransfer + Message::EndProjectTransfer sMEndProjectTransfer; + // sendSPITMessage(sMEndProjectTransfer); +} + +/* NEW IMPLEMENTATION + +void SProcessor::parseRequestProjectTransfer(Message::RequestProjectTransfer* message) { // @todo +// ESP_LOGD(TAG, "parse RequestProjectTransfer"); + thread* o_ThreadSend; + o_ThreadSend = new thread(&this->sendProject, this); + // int intResult; + // Message::StartProjectTransfer* ptrSMStartProjectTransfer; + // Message::EndProjectTransfer* ptrSMEndProjectTransfer; + // int intCount; + // SPITType* ptrSPITType; + // SObject* ptrSPITObject; + + + // //StartProjectTransfer + // NotifyStartProjectTransfer_Client* o_RunnableStart = new NotifyStartProjectTransfer_Client(mSPITClientInterface); + // SPIT_Handler::addRunnable(o_RunnableStart); + + // ptrSMStartProjectTransfer = new Message::StartProjectTransfer(); + // intResult = sendSPITMessage(ptrSMStartProjectTransfer); + // if (intResult < 0) { + // return; + // } + // mWatchdog->answerWatchdog(); + // { + // //send all listes SPITTypes + // unique_lock o_LockType(*SPITType::getMutex()); + // intCount = SPITType::getSPITTypeCount(); + // for (int i = 0; i < intCount; i++) { + // ptrSPITType = mSpitTypes.getEntry(i); + // if (ptrSPITType == nullptr) continue; + // intResult = sendSPITTypeInternal(ptrSPITType); + // if (intResult < 0) return; + // mWatchdog->answerWatchdog(); + // this_thread::sleep_for(chrono::milliseconds(7)); + // } + // } + + // { + // unique_lock o_LockObject(*SObject::getMutex()); + // intCount = mSpitObjects.getEntryCount(); + // for (int i = 0; i < intCount; i++) { + // ptrSPITObject = mSpitObjects.getEntry(i); + // if (ptrSPITObject == nullptr) continue; + // intResult = sendSPITObjectInternal(ptrSPITObject); + // if (intResult < 0) return; + // mWatchdog->answerWatchdog(); + // this_thread::sleep_for(chrono::milliseconds(7)); + // } + // } + + // //EndProjectTransfer + // ptrSMEndProjectTransfer = new Message::EndProjectTransfer(); + // intResult = sendSPITMessage(ptrSMEndProjectTransfer); + // if (intResult < 0) { + // return; + // } + // mWatchdog->answerWatchdog(); + // NotifyEndProjectTransfer_Client* o_RunnableEnd = new NotifyEndProjectTransfer_Client(mSPITClientInterface); + // SPIT_Handler::addRunnable(o_RunnableEnd); + + // //Send act +} +*/ + +// void SProcessor::sendProject(SClient *p_PtrSPIT_Client) { // @todo + // int intResult; + // Message::StartProjectTransfer* ptrSMStartProjectTransfer; + // Message::EndProjectTransfer* ptrSMEndProjectTransfer; + // int intCount; + // SPITType* ptrSPITType; + // SObject* ptrSPITObject; + + // //StartProjectTransfer + // NotifyStartProjectTransfer_Client* o_RunnableStart = new NotifyStartProjectTransfer_Client(p_PtrSPIT_Client->getSPITClientInterface()); + // SPIT_Handler::addRunnable(o_RunnableStart); + + // ptrSMStartProjectTransfer = new Message::StartProjectTransfer(); + // intResult = p_PtrSPIT_Client->sendSPITMessage(ptrSMStartProjectTransfer); + // if (intResult < 0) { + // return; + // } + + // // mWatchdog->answerWatchdog(); + // // { + // //send all listes SPITTypes + // // unique_lock o_LockType(*SPITType::getMutex()); + // intCount = SPITType::getSPITTypeCount(); + // for (int i = 0; i < intCount; i++) { + // ptrSPITType = mSpitTypes.getEntry(i); + // if (ptrSPITType == nullptr) continue; + // if (ptrSPITType->getCreatedByClient() == false) continue; + // intResult = p_PtrSPIT_Client->sendSPITTypeInternal(ptrSPITType); + // if (intResult < 0) return; + // // mWatchdog->answerWatchdog(); + // this_thread::sleep_for(chrono::milliseconds(7)); + // } + // // } + + // // { + // // unique_lock o_LockObject(*SObject::getMutex()); + // intCount = mSpitObjects.getEntryCount(); + // for (int i = 0; i < intCount; i++) { + // ptrSPITObject = mSpitObjects.getEntry(i); + // if (ptrSPITObject == nullptr) continue; + // if (ptrSPITObject->getCreatedByClient() == false) continue; + // intResult = p_PtrSPIT_Client->sendSPITObjectInternal(ptrSPITObject); + // if (intResult < 0) return; + // // mWatchdog->answerWatchdog(); + // this_thread::sleep_for(chrono::milliseconds(7)); + // } + // // } + + // //EndProjectTransfer + // ptrSMEndProjectTransfer = new Message::EndProjectTransfer(); + // intResult = p_PtrSPIT_Client->sendSPITMessage(ptrSMEndProjectTransfer); + // if (intResult < 0) { + // return; + // } + // // mWatchdog->answerWatchdog(); + // NotifyEndProjectTransfer_Client* o_RunnableEnd = new NotifyEndProjectTransfer_Client(p_PtrSPIT_Client->getSPITClientInterface()); + // SPIT_Handler::addRunnable(o_RunnableEnd); + + // //Send act +// } + +void SProcessor::parseStartProjectTransfer(Message::StartProjectTransfer &message) { // @todo + mCallbacks.onProjectUpdate(ProjUpdate::StartTransfer, mServerProjectID); +} +void SProcessor::parseEndProjectTransfer(Message::EndProjectTransfer &message) { // @todo + SObject::clearUnconfirmedObjects(mSpitObjects); + mCallbacks.onProjectUpdate(ProjUpdate::EndTransfer, mServerProjectID); + + // Send Message::ReportProject after the mSPITClientInterface is notfied of EndProjectTransfer + Message::ReportProject reportSPITProject(mProjName, mProjName); + reportSPITProject.setFramesPerSecond(0); + // if (sendSPITMessage(reportSPITProject) < 0) { + // ESP_LOGD(TAG, "Client::parseReportProject could not send Client's ReportProject"); + // } +} + +//----- SPIT Types ------ +void SProcessor::parseReportType(Message::ReportType &message) { // @todo + ESP_LOGD(TAG, "parse ReportType ID %s Name %s",message.getID().c_str(), message.getName().c_str()); + SType *sType; + bool boolNew = false; + bool boolChanged = false; + { + if (message.getServerRemote() == false) { + sType = mSpitTypes.getEntry(message.getID()); + if (sType == nullptr) { + // The user's app may veto the SPITType + bool createdByClient = false; + if (sType) { + createdByClient = sType->getCreatedByClient(); + } + + if (mCallbacks.onCheckSpitTypeVeto(false, createdByClient) == false) { + ESP_LOGW(TAG, "TypeVeto %s / %s", message.getID().c_str(), message.getName().c_str()); + return; + } + auto spitType = make_unique(message.getID()); + sType = spitType.get(); + mSpitTypes.addEntry(move(spitType)); + boolNew = true; + } + } else { + sType = mRemoteSpitTypes.getEntry(message.getID()); + if (sType == nullptr) { + auto spitType = make_unique(message.getID()); + sType = spitType.get(); + mRemoteSpitTypes.addEntry(move(spitType)); + boolNew = true; + } + } + if (!sType->setMessageOP(message)) { + // SPITType is not changable -> send back to the server + sendSPITTypeInternal(*sType); + return; + } + + auto eventType = boolNew ? ObjectEvent::Created : ObjectEvent::Changed; + // add or change SPITType + mCallbacks.onSpitType(eventType, sType->ServerRemote.get(), *sType); + + if (sType != nullptr) { + if (sType->setConfirmed(true) == true || boolChanged == true) { + sendSPITTypeInternal(*sType); + } + } + } +} +void SProcessor::parseRemoveSPITType(Message::RemoveType &message) { // @todo + ESP_LOGD(TAG, "parse RemoveType %s", message.getID().c_str()); + bool boolRemote = false; + string stringSPITTypeID = message.getID(); + + SType *ptrSPITType = mRemoteSpitTypes.getEntry(stringSPITTypeID); + if (!ptrSPITType) { + boolRemote = true; + } else { + ptrSPITType = mSpitTypes.getEntry(stringSPITTypeID); + if (!ptrSPITType) { + boolRemote = false; + } else { + // No SPITType with stringSPITTypeID is listet + return; + } + } + + if (ptrSPITType->getCreatedByClient() && ptrSPITType->Fixed.get()) { + // the SPITyte is created by client himself and it is fixed -> don't remove the SPITType!! + // Send the SPITTyp back to the server + sendSPITTypeInternal(*ptrSPITType); + return; + } + + mCallbacks.onSpitType(ObjectEvent::Deleted, boolRemote, *ptrSPITType); + if (boolRemote == false) { + mSpitTypes.removeEntry(*ptrSPITType); + } else { + mRemoteSpitTypes.removeEntry(*ptrSPITType); + } +} + +/** + * If a client has changed a SPITType, it should send it to the server to transmit the changes. + * If the SPITType is a fixed one and not created by the client himself, then an eventSPITType can be sent from the server, which cancels the changes. + * @param p_SPITType the pointer to the changed SPITType + * @return 0 = is sended, -1 = is not sended + */ +int SProcessor::sendSPITTypeInternal(SType &p_SPITType) { // @todo + Message::ReportType sMReportSPITType; + p_SPITType.fillMessageOP(sMReportSPITType); + // return sendSPITMessage(sMReportSPITType); + return 1; +} + +/** + * Change an existing SPIT_Type. + * @param p_SPITType the SPITType vont + * @return true = changed, false = not changed maybe p_SPITType is NULL or the SPITType doesn't exists + */ +bool SProcessor::changeSPITType(SType *p_SPITType) { // @todo + if (p_SPITType == nullptr) + return false; + SType *ptrSPITType = mSpitTypes.getEntry(p_SPITType->getID()); + if (ptrSPITType == nullptr) + return false; + + ptrSPITType->DefaultDelay.set(p_SPITType->DefaultDelay.get()); + ptrSPITType->DefaultDuration.set(p_SPITType->DefaultDuration.get()); + ptrSPITType->Fixed.set(p_SPITType->Fixed.get()); + ptrSPITType->GroupName.set(p_SPITType->GroupName.get()); + ptrSPITType->Name.set(p_SPITType->Name.get()); + ptrSPITType->ProjectIndepended.set(p_SPITType->ProjectIndepended.get()); + + mCallbacks.onSpitType(ObjectEvent::Changed, false, *ptrSPITType); + sendSPITTypeInternal(*ptrSPITType); + + return true; +} + +/** + * If a client has removed a SPITType where id == p_SPITTypeID, it should send it to the server. + * The corresponding SPITType if listet in SPITType will be deleted. + * An eventRemoveSPITType will occur. + * If a connection to a SPITServer is established, the SPITServer may dicard the deletion an an eventSPITType will occur + * -> the SPITType will be listet again. + * @param p_SPITType the id of the SPITType ro remove + * @return 0 = is sended, -1 = is not sended + */ +int SProcessor::removeSPITType(string p_SPITTypeID) { // @todo + if (p_SPITTypeID.length() <= 0) + return -1; + SType *ptrSPITType; + { + ptrSPITType = mSpitTypes.getEntry(p_SPITTypeID); + if (ptrSPITType == nullptr) + return -1; + Message::RemoveType sMRemoveSPITType; + ptrSPITType->fillMessageOP(sMRemoveSPITType); + mCallbacks.onSpitType(ObjectEvent::Deleted, false, *ptrSPITType); + mSpitTypes.removeEntry(*ptrSPITType); + // return sendSPITMessage(sMRemoveSPITType); + return 1; + } + return -1; +} + +SType *SProcessor::createTypeFixed(string iD, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration) { // @todo + return createType(iD, p_GroupName, p_Name, p_DefaultDelay, p_DefaultDuration, true, true); +} + +SType *SProcessor::createType(string p_ID, string p_GroupName, string p_Name, uint64_t p_DefaultDelay, uint64_t p_DefaultDuration, bool p_FIxed, bool p_ProjectIndepended) { // @todo + bool boolNew; + SType *ptrSPITType = mSpitTypes.getEntry(p_ID); + if (ptrSPITType == nullptr) { + auto spitType = make_unique(p_ID, p_GroupName, p_Name, p_FIxed, p_ProjectIndepended, p_DefaultDelay, p_DefaultDuration); + ptrSPITType = spitType.get(); + mSpitTypes.addEntry(move(spitType)); + ptrSPITType->setCreatedByClient(true); + boolNew = true; + } else { + ptrSPITType->GroupName.set(p_GroupName); + ptrSPITType->Name.set(p_Name); + ptrSPITType->Fixed.set(p_FIxed); + ptrSPITType->ProjectIndepended.set(p_ProjectIndepended); + ptrSPITType->DefaultDelay.set(p_DefaultDelay); + ptrSPITType->DefaultDuration.set(p_DefaultDuration); + boolNew = false; + } + + auto eventType = boolNew ? ObjectEvent::Created : ObjectEvent::Changed; + mCallbacks.onSpitType(eventType, false, *ptrSPITType); + sendSPITTypeInternal(*ptrSPITType); + return ptrSPITType; +} + +//----- SPIT Objects ------ +void SProcessor::parseReportSPITObject(Message::ReportObject &message) { // @todo + ESP_LOGD(TAG, "parse ReportObject %s", message.getID().c_str()); + SObject *ptrSPITObject; + SType *ptrSPITType; + bool boolNew = false; + bool boolRemote = false; + bool boolChanged = false; + { + ESP_LOGD(TAG, "parse ReportObject %s / %s", message.getID().c_str(), message.getName().c_str()); + if (message.getServerRemote() == false) { + boolRemote = false; + ptrSPITObject = mSpitObjects.getEntry(message.getID()); + ptrSPITType = mSpitTypes.getEntry(message.getSPITTypeID()); + + if (ptrSPITType == nullptr) { + // No associated SPITType found + if (ptrSPITObject != nullptr) { + // SpitObject exists but has no corresponding SPITType -> remove the SPITObject without sending a message + // Maybe the SPITObject has changed the SPITTypeID to a SPITTypeID of another board + mSpitObjects.removeEntry(*ptrSPITObject); + } + return; + } + bool isKnownType = ptrSPITType != nullptr; + if (ptrSPITObject == nullptr) { + // The user's app my veto the SPITType + if (mCallbacks.onCheckSpitObjectVeto(isKnownType) == false) { + ESP_LOGW(TAG, "ObjectVeto %s / %s", message.getID().c_str(), message.getName().c_str()); + return; + } + auto spitObj = make_unique(message.getID()); + ptrSPITObject = spitObj.get(); + mSpitObjects.addEntry(move(spitObj)); + boolNew = true; + } else { + // The user's app my veto the SPITType + if (mCallbacks.onCheckSpitObjectVeto(isKnownType) == false) { + // SpitObject exists and User APp denied the SPITObject -> remove the SPITObject without sending a message + mSpitObjects.removeEntry(*ptrSPITObject); + ESP_LOGW(TAG, "TypeVeto %s / %s", message.getID().c_str(), message.getName().c_str()); + return; + } + } + } else { + boolRemote = true; + ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID()); + ptrSPITType = mRemoteSpitTypes.getEntry(message.getSPITTypeID()); + if (ptrSPITType == nullptr) { + // No associated SPITType found + return; + } + if (ptrSPITObject == nullptr) { + auto spitObj = make_unique(message.getID()); + ptrSPITObject = spitObj.get(); + mRemoteSpitObjects.addEntry(move(spitObj)); + boolNew = true; + } + } + + if (!ptrSPITObject->setMessageOP(&message)) { + ESP_LOGE(TAG, "Change not allowed"); + // setMessageOP error - the SPITObject can't be changed, it may be fixed and crated by this client + sendSPITObjectInternal(ptrSPITObject); + return; + } + + if (boolRemote == false) { + // set the virtual action assignment + ptrSPITObject->setActionAssignedType(ptrSPITType->ActionAssigned.get()); + } + + auto eventType = boolNew ? ObjectEvent::Created : ObjectEvent::Changed; + mCallbacks.onSpitObject(eventType, boolRemote, *ptrSPITType, *ptrSPITObject); + + if (ptrSPITObject->setConfirmed(true) == true || boolChanged == true) { + // Confirmation has changed + sendSPITObjectInternal(ptrSPITObject); + } + } +} +void SProcessor::parseRemoveSPITObject(Message::RemoveObject &message) { // @todo + ESP_LOGD(TAG, "parse RemoveObject %s", message.getID().c_str()); + SObject *ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID()); + if (ptrSPITObject != nullptr) { + SType *ptrSPITType = mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); + if (ptrSPITType != nullptr) { + mCallbacks.onSpitObject(ObjectEvent::Deleted, true, *ptrSPITType, *ptrSPITObject); + } + mRemoteSpitObjects.removeEntry(*ptrSPITObject); + } else { + // call removeSPITObject, this will notify the server that the object is removed + removeSPITObject(message.getID()); + } +} + +int SProcessor::sendSPITObjectInternal(SObject *ptrSPITObject) { // @todo + if (ptrSPITObject == nullptr) + return -1; + Message::ReportObject sMReportSPITObject; + ptrSPITObject->fillMessageOP(sMReportSPITObject); + + // return sendSPITMessage(sMReportSPITObject); + return 1; +} +/** + * When the client changes an existing SPITObject (normally the client should not do this), then he should send the changes to the SPITServer. + * An eventSPITObject occurs. + * The SPITServer may discard the changes and a second eventSPITObject occurs to correct the changes. + * @param obj the pointer to the changed SPITObject. + * CAUTION: The SPITObject must already exist. + * @return true = SPITObject is changed, false = not changed, maybe obj is NULL or the SPITObject doesn't exists + */ +bool SProcessor::changeSPITObject(SObject *obj) { // @todo + if (obj == nullptr) + return false; + SObject *ptrSPITObject; + SType *ptrSPITType; + { + ptrSPITObject = mSpitObjects.getEntry(obj->getID()); + if (ptrSPITObject == nullptr) + return false; + ptrSPITType = mSpitTypes.getEntry(obj->getID()); + if (ptrSPITObject == nullptr) + return false; + + ptrSPITObject->setActionAssigned(obj->getActionAssigned()); + ; + ptrSPITObject->Delay.set(obj->Delay.get()); + ptrSPITObject->Duration.set(obj->Delay.get()); + ptrSPITObject->Fixed.set(obj->Fixed.get()); + ptrSPITObject->FrameFadeInLength.set(obj->FrameFadeInLength.get()); + ptrSPITObject->FrameFadeOutLength.set(obj->FrameFadeOutLength.get()); + ptrSPITObject->FrameLength.set(obj->FrameLength.get()); + ptrSPITObject->FrameStart.set(obj->FrameStart.get()); + ptrSPITObject->Name.set(obj->Name.get()); + ptrSPITObject->Remark.set(obj->Remark.get()); + ptrSPITObject->SPITTypeID.set(obj->SPITTypeID.get()); + ptrSPITObject->ServerParams.set(obj->ServerParams.get()); + ptrSPITObject->Track.set(obj->Track.get()); + ptrSPITObject->ValueFactor.set(obj->ValueFactor.get()); + ptrSPITObject->ValueUse.set(obj->ValueUse.get()); + + mCallbacks.onSpitObject(ObjectEvent::Changed, false, *ptrSPITType, *ptrSPITObject); + sendSPITObjectInternal(ptrSPITObject); + } + return true; +} + +/** + * When the client wants to remove a SPITObject with id == p_SPITObjectID (normally the client should not do this), then he should send it to the SPITServer. + * The corresponding SPITObject if listet in SPITObject will be deleted. + * An eventRemoveSPITType will occur. + * If an connection to a SPITServer is established, the SPITServer may discard the deletion and an eventSPITObject occurs + * -> the SPITObject is listet again. + * @param objId the id of the SPITObject to remove. + * @return 0 = sended to the SPITServer, -1 = not sended to the SPITServer or nos SPITObject with id == objId exists. + */ +int SProcessor::removeSPITObject(string objId) { // @todo + if (objId.length() <= 0) + return -1; + SType *ptrSPITType; + SObject *ptrSPITObject; + { + Message::RemoveObject sMRemoveSPITObject; + + ptrSPITObject = mSpitObjects.getEntry(objId); + if (ptrSPITObject == nullptr) + return -1; + ptrSPITType = mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); + if (ptrSPITType == nullptr) + return -1; + ptrSPITObject->fillMessageOP(sMRemoveSPITObject); + mCallbacks.onSpitObject(ObjectEvent::Deleted, false, *ptrSPITType, *ptrSPITObject); + mSpitObjects.removeEntry(*ptrSPITObject); + // return sendSPITMessage(sMRemoveSPITObject); + return 1; + } + return -1; +} + +//----- Play SPIT Objects ------ + +void SProcessor::parsePlaySPITStart(Message::PlayStart &message) { // @todo + ESP_LOGD(TAG, "parse PlayStart ID: %s Name: %s Running: %d", message.getPlayerID().c_str(), message.getPlayerName().c_str(), (int)message.getPlayerIsRunning()); + SPlayer &spitPlayer = SPlayer::getSPITPlayer(message.getPlayerID()); + spitPlayer.setIsRunning(message.getPlayerIsRunning()); + spitPlayer.setName(message.getPlayerName()); + spitPlayer.setType(message.getPlayerType()); + spitPlayer.setTime(message.getTime()); + spitPlayer.startPlaySequence(); + + mCallbacks.onPlay(spitPlayer.getID(), spitPlayer.getName(), spitPlayer.getType(), spitPlayer.getIsRunning(), spitPlayer.getTime()); +} +void SProcessor::parsePlaySPITObject(Message::PlayObject &message) { // @todo + + SPlayer &ptrSPITPlayer = SPlayer::getSPITPlayer(message.getPlayerID()); + SObject *ptrSPITObject = mSpitObjects.getEntry(message.getSPITObjectID()); + + if (ptrSPITObject == nullptr) { + return; + } + SPlayer::PlayType *ptrPlaySPITType = ptrSPITPlayer.addTypePlaying(ptrSPITObject->SPITTypeID.get()); + if (ptrPlaySPITType == nullptr) { + return; + } + ptrPlaySPITType->setPlayerIsRunning(ptrSPITPlayer.getIsRunning()); + ptrPlaySPITType->addValue(((double)message.getValue() / 1000000), ((double)ptrSPITObject->ValueFactor.get() / 1000000)); +} + +void SProcessor::parsePlaySPITEnd(Message::PlayEnd &message) { // @todo + SPlayer &ptrSPITPlayer = SPlayer::getSPITPlayer(message.getPlayerID()); + + auto &ptrPlaySPITTypes = ptrSPITPlayer.getPlaySPITTypes(); + for (auto i = ptrPlaySPITTypes.begin(); i != ptrPlaySPITTypes.end(); i++) { + SPlayer::PlayType *ptrPlaySPITType = i->second.get(); + bool boolStarted = ptrPlaySPITType->getIsNew(); + bool boolStopped = (ptrPlaySPITType->getIsPlayed() == false); + SType *ptrSPITType = mSpitTypes.getEntry(ptrPlaySPITType->getSPITTypeID()); + if (ptrSPITType == nullptr) { + // set isplayed to false, the ptrPlayObject will be removed by ptrSPITPlayer.endPlaySequence() + ptrPlaySPITType->setIsPlayed(false); + continue; + } + mCallbacks.onPlaySpitType(ptrPlaySPITType->getPlayerID(), ptrPlaySPITType->getSPITTypeID(), ptrPlaySPITType->getPlayerIsRunning(), boolStarted, boolStopped, ptrPlaySPITType->getValue()); + } + ptrSPITPlayer.endPlaySequence(); +} + +void SProcessor::parseReportPlayStatus(Message::ReportPlayStatus &message) { // @todo + SType *ptrSPITType = NULL; + + SObject *ptrSPITObject = mRemoteSpitObjects.getEntry(message.getID()); + if (ptrSPITObject == nullptr) { + ptrSPITObject = mSpitObjects.getEntry(message.getID()); + if (ptrSPITObject == nullptr) { + return; + } + } + if (ptrSPITObject->ServerRemote.get() == false) { + ptrSPITType = mSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); + } else { + ptrSPITType = mRemoteSpitTypes.getEntry(ptrSPITObject->SPITTypeID.get()); + } + + if (ptrSPITType == nullptr) { + return; + } + mCallbacks.onPlayRemoteObjectStatus(*ptrSPITType, *ptrSPITObject, message.getFrameInsideObject(), message.getValue()); +} + +//--------- Remote ---------- + +/** + * Send a remote control command to the SPITServer. + * There may be different command types: + * a) Some don't use value e.g. go to next scene, olay a jingle + * b) Some use values e.g. the main sound fader + * @param p_SPITObjectID the id of the remote SPITObject (this represents the remote control command) + * @param valuePpm the value in ppm + * in case a) the value is ignored + * in case b) the value is used + * @param valueFlag indicates how the server should use valuePpm: + * VALUEFLAG_DIRECT (0x00) The server overwrites its existing value with p_Value + * VALUEFLAG_INCREASE (0x01) The server increases his existing value by valuePpm + * VALUEFLAG_DECREASE (0x01) The server decreases his existing value by valuePpm + */ +void SProcessor::sendRemoteObject(string p_SPITObjectID, int valuePpm, char valueFlag) { // @todo + SObject *ptrRemoteSPITObject = mRemoteSpitObjects.getEntry(p_SPITObjectID); + if (ptrRemoteSPITObject == nullptr) + return; + + Message::PlayStart playSPITStart(mGuid, mProjName, PLAYERTYPE_DISCRETE); + playSPITStart.setPlayerIsRunning(false); + playSPITStart.setTime(0); + // sendSPITMessage(playSPITStart); + + Message::PlayObject playSPITObject; + playSPITObject.setID(ptrRemoteSPITObject->getID()); + playSPITObject.setPlayPrePosition(false); + playSPITObject.setPlayerID(mGuid); + playSPITObject.setValue(valuePpm); + playSPITObject.setValueFlag(valueFlag); + // sendSPITMessage(playSPITObject); + + Message::PlayEnd playSPITEnd(mGuid); + // sendSPITMessage(playSPITEnd); +} + + + +} \ No newline at end of file diff --git a/components/spit/test/CMakeLists.txt b/components/spit/test/CMakeLists.txt new file mode 100644 index 0000000..1edbbf9 --- /dev/null +++ b/components/spit/test/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRC_DIRS "." + INCLUDE_DIRS "." + REQUIRES cmock spit +) diff --git a/components/spit/test/test_spit_client.cpp b/components/spit/test/test_spit_client.cpp new file mode 100644 index 0000000..254eff8 --- /dev/null +++ b/components/spit/test/test_spit_client.cpp @@ -0,0 +1,123 @@ +/** + * @file test_mean.cpp + * @author Gustice + * @brief Hardware bound unit-Test example device + */ + +#include "spit_client.hpp" +#include "unity.h" +#include +#include +#include + +using namespace spit; +using namespace std; + +queue callbackEvents; + +class ClientMock { + public: + void onServerEvent(SClient::ServerEvent event, const SadDetectedServer &detectedServer) { + } + void onConnectionStatus(string serverID, string serverComputerName, string serverName, int serverStepTime, SClient::Connection connectionStatus, SClient::Connection oldConnectionStatus) { + } + void onProjectUpdate(SClient::ProjUpdate state, string projectId) { + } + void onSpitType(SClient::ObjectEvent event, bool isRemote, const SType &spitType) { + } + void onSpitObject(SClient::ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject) { + } + void onPlay(string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { + } + void onPlaySpitType(string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { + } + void onPlayRemoteObjectStatus(const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value) { + } + bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) { + return true; + } + bool onCheckSpitObjectVeto(bool knownType) { + return true; + } +}; + +class SocketMock : public ISocket { + public: + SocketMock(IpAddress ip) : ISocket(ip) {} + + int sendMessage(const char *message, int length) override { + return 0; + } + int receiveMessage(char *bu1ffer, int bufferLength, string *serverIp) const override { + return 0; + } + void setConnectionParams(const string &serverIp, const string &serverPort, const string &clientIp, const string &clientPort) override { + } + int bindSocket(string clientIp, string clientPort) override { + return 0; + } + int setBroadcast(bool broadcast) const override { + return 0; + } + int sendMessageTo(const string &ip, const string &port, const char *message, int msgLength) override { + return 0; + } +}; + +// class SpitClientFix { +// protected: +// static ClientMock client; +// ISocket::IpAddress ip{"10.10.0.1", "255.255.255.0"}; +// SocketMock socket{ip}; +// SClient::Callbacks callbacks{ +// .onServerEvent = [&](SClient::ServerEvent event, const SadDetectedServer &detectedServer){client.onServerEvent(event, detectedServer);} , +// .onConnectionStatus = [&](string serverID, string serverComputerName, string serverName, int serverStepTime, SClient::Connection connectionStatus, SClient::Connection oldConnectionStatus){client.onConnectionStatus(serverID, serverComputerName, serverName, serverStepTime, connectionStatus, oldConnectionStatus);} , +// .onProjectUpdate = [&](SClient::ProjUpdate state, string projectId){client.onProjectUpdate(state, projectId);} , +// .onSpitType = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType){client.onSpitType(event, isRemote, spitType);} , +// .onSpitObject = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject){client.onSpitObject(event, isRemote, spitType, spitObject);} , +// .onPlay = [&](string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames){client.onPlay(playerID, playerName, playerType, playerIsRunning, timeFrames);} , +// .onPlaySpitType = [&](string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value){client.onPlaySpitType(playerID, spitTypeID, playerIsRunning, started, ended, value);} , +// .onPlayRemoteObjectStatus = [&](const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value){client.onPlayRemoteObjectStatus( spitType, spitObject, p_FrameInsideObject, value);} , +// .onCheckSpitTypeVeto = [&](bool knownType, bool createdByClient){return client.onCheckSpitTypeVeto(knownType, createdByClient);} , +// .onCheckSpitObjectVeto = [&](bool knownType){return client.onCheckSpitObjectVeto(knownType);} +// }; +// SClient sut{"sut", "sutProj", socket, callbacks}; +// }; + +TEST_CASE("Full Connect precedure", "[spit][init]") { + static ClientMock client; + ISocket::IpAddress ip{"10.10.0.1", "255.255.255.0"}; + SocketMock socket{ip}; + SClient::Callbacks callbacks{ + .onServerEvent = [&](SClient::ServerEvent event, const SadDetectedServer &detectedServer) { client.onServerEvent(event, detectedServer); }, + .onConnectionStatus = [&](string serverID, string serverComputerName, string serverName, int serverStepTime, SClient::Connection connectionStatus, SClient::Connection oldConnectionStatus) { client.onConnectionStatus(serverID, serverComputerName, serverName, serverStepTime, connectionStatus, oldConnectionStatus); }, + .onProjectUpdate = [&](SClient::ProjUpdate state, string projectId) { client.onProjectUpdate(state, projectId); }, + .onSpitType = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType) { client.onSpitType(event, isRemote, spitType); }, + .onSpitObject = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject) { client.onSpitObject(event, isRemote, spitType, spitObject); }, + .onPlay = [&](string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { client.onPlay(playerID, playerName, playerType, playerIsRunning, timeFrames); }, + .onPlaySpitType = [&](string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { client.onPlaySpitType(playerID, spitTypeID, playerIsRunning, started, ended, value); }, + .onPlayRemoteObjectStatus = [&](const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value) { client.onPlayRemoteObjectStatus(spitType, spitObject, p_FrameInsideObject, value); }, + .onCheckSpitTypeVeto = [&](bool knownType, bool createdByClient) { return client.onCheckSpitTypeVeto(knownType, createdByClient); }, + .onCheckSpitObjectVeto = [&](bool knownType) { return client.onCheckSpitObjectVeto(knownType); }}; + SClient sut{"sut", "sutProj", socket, callbacks}; + + // tood connect - Response - Request project + + // Transfer items liveSHOW -> Device + + { + Message::ReportType t1; + t1.setConfirmed(false); + t1.setID("type1Id#"); + t1.setFixed(true); + t1.setServerRemote("serverId"); + t1.setServerProjectIndepended(true); + t1.setGroupName("sGroup"); + t1.setName("type1Name"); + t1.setDelay(100); + t1.setDuration(200); + + + socket. + } +} \ No newline at end of file diff --git a/components/spit/uTest/spitClientTest.cpp b/components/spit/uTest/spitClientTest.cpp deleted file mode 100644 index 55dc430..0000000 --- a/components/spit/uTest/spitClientTest.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @file spitRepoTest.cpp - * @author Gustice - * @brief - */ - -#include "doctest/doctest.h" -#include -#include - -#include "spit_client.hpp" - -using namespace spit; -using namespace std; - -class ClientMock { - public: - void onServerEvent(SClient::ServerEvent event, const SadDetectedServer &detectedServer) { - } - void onConnectionStatus(string serverID, string serverComputerName, string serverName, int serverStepTime, SClient::Connection connectionStatus, SClient::Connection oldConnectionStatus) { - } - void onProjectUpdate(SClient::ProjUpdate state, string projectId) { - } - void onSpitType(SClient::ObjectEvent event, bool isRemote, const SType &spitType) { - } - void onSpitObject(SClient::ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject) { - } - void onPlay(string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { - } - void onPlaySpitType(string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { - } - void onPlayRemoteObjectStatus(const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value) { - } - bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) { - } - bool onCheckSpitObjectVeto(bool knownType) { - } -}; - -class SocketMock : public ISocket { - public: - SocketMock(IpAddress ip) : ISocket(ip) {} - - int sendMessage(const char *message, int length) override { - } - int receiveMessage(char *bu1ffer, int bufferLength, string *serverIp) const override { - } - void setConnectionParams(const string &serverIp, const string &serverPort, const string &clientIp, const string &clientPort) override { - } - int bindSocket(string clientIp, string clientPort) override { - } - int setBroadcast(bool broadcast) const override { - } - int sendMessageTo(const string &ip, const string &port, const char *message, int msgLength) override { - } -}; - -class SpitClientFix { - protected: - static ClientMock client; - ISocket::IpAddress ip{"10.10.0.1", "255.255.255.0"}; - SocketMock socket{ip}; - SClient::Callbacks callbacks{ - .onServerEvent = [&](SClient::ServerEvent event, const SadDetectedServer &detectedServer){client.onServerEvent(event, detectedServer);} , - .onConnectionStatus = [&](string serverID, string serverComputerName, string serverName, int serverStepTime, SClient::Connection connectionStatus, SClient::Connection oldConnectionStatus){client.onConnectionStatus(serverID, serverComputerName, serverName, serverStepTime, connectionStatus, oldConnectionStatus);} , - .onProjectUpdate = [&](SClient::ProjUpdate state, string projectId){client.onProjectUpdate(state, projectId);} , - .onSpitType = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType){client.onSpitType(event, isRemote, spitType);} , - .onSpitObject = [&](SClient::ObjectEvent event, bool isRemote, const SType &spitType, const SObject &spitObject){client.onSpitObject(event, isRemote, spitType, spitObject);} , - .onPlay = [&](string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames){client.onPlay(playerID, playerName, playerType, playerIsRunning, timeFrames);} , - .onPlaySpitType = [&](string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value){client.onPlaySpitType(playerID, spitTypeID, playerIsRunning, started, ended, value);} , - .onPlayRemoteObjectStatus = [&](const SType &spitType, const SObject &spitObject, uint64_t p_FrameInsideObject, int value){client.onPlayRemoteObjectStatus( spitType, spitObject, p_FrameInsideObject, value);} , - .onCheckSpitTypeVeto = [&](bool knownType, bool createdByClient){return client.onCheckSpitTypeVeto(knownType, createdByClient);} , - .onCheckSpitObjectVeto = [&](bool knownType){return client.onCheckSpitObjectVeto(knownType);} - }; - SClient sut{"sut", "sutProj", socket, callbacks}; -}; - -TEST_CASE_FIXTURE(SpitClientFix, "Typical use case") { -} diff --git a/components/spit/uTest/spitProcessorTest.cpp b/components/spit/uTest/spitProcessorTest.cpp new file mode 100644 index 0000000..0195019 --- /dev/null +++ b/components/spit/uTest/spitProcessorTest.cpp @@ -0,0 +1,170 @@ +/** + * @file spitRepoTest.cpp + * @author Gustice + * @brief + */ + +#include "doctest/doctest.h" +#include +#include +#include + +#include "spit_processor.hpp" + +using namespace spit; +using namespace std; +static queue cbEvents; + +class ClientMock { + public: + void onServerEvent(SProcessor::ServerEvent event, const SadDetectedServer &detectedServer) { + } + void onConnectionStatus(string serverID, string serverComputerName, string serverName, int serverStepTime, SProcessor::Connection connectionStatus, SProcessor::Connection oldConnectionStatus) { + } + void onProjectUpdate(SProcessor::ProjUpdate state, string projectId) { + } + void onSpitType(SProcessor::ObjectEvent event, bool isRemote, const SType &sType) { + cbEvents.push(fmt::format("{}: {} {} {} {}", (int)event, isRemote, sType.getID(), sType.Name.get(), sType.GroupName.get())); + } + void onSpitObject(SProcessor::ObjectEvent event, bool isRemote, const SType &sType, const SObject &sObject) { + cbEvents.push(fmt::format("{}: {} {} {} {} {}", (int)event, isRemote, sType.getID(), sType.Name.get(), sObject.Name.get(), sObject.getID())); + } + void onPlay(string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { + } + void onPlaySpitType(string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { + } + void onPlayRemoteObjectStatus(const SType &sType, const SObject &sObject, uint64_t p_FrameInsideObject, int value) { + } + bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) { + cbEvents.push(fmt::format("veto check {}/{}", knownType, createdByClient)); + return true; + } + bool onCheckSpitObjectVeto(bool knownType) { + return true; + } +}; + +class SpitClientFix { + protected: + ClientMock client; + SProcessor::Callbacks callbacks{ + .onServerEvent = [&](SProcessor::ServerEvent event, const SadDetectedServer &detectedServer) { client.onServerEvent(event, detectedServer); }, + .onConnectionStatus = [&](string serverID, string serverComputerName, string serverName, int serverStepTime, SProcessor::Connection connectionStatus, SProcessor::Connection oldConnectionStatus) { client.onConnectionStatus(serverID, serverComputerName, serverName, serverStepTime, connectionStatus, oldConnectionStatus); }, + .onProjectUpdate = [&](SProcessor::ProjUpdate state, string projectId) { client.onProjectUpdate(state, projectId); }, + .onSpitType = [&](SProcessor::ObjectEvent event, bool isRemote, const SType &t) { client.onSpitType(event, isRemote, t); }, + .onSpitObject = [&](SProcessor::ObjectEvent event, bool isRemote, const SType &t, const SObject &o) { client.onSpitObject(event, isRemote, t, o); }, + .onPlay = [&](string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { client.onPlay(playerID, playerName, playerType, playerIsRunning, timeFrames); }, + .onPlaySpitType = [&](string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { client.onPlaySpitType(playerID, spitTypeID, playerIsRunning, started, ended, value); }, + .onPlayRemoteObjectStatus = [&](const SType &t, const SObject &o, uint64_t p_FrameInsideObject, int value) { client.onPlayRemoteObjectStatus(t, o, p_FrameInsideObject, value); }, + .onCheckSpitTypeVeto = [&](bool knownType, bool createdByClient) { return client.onCheckSpitTypeVeto(knownType, createdByClient); }, + .onCheckSpitObjectVeto = [&](bool knownType) { return client.onCheckSpitObjectVeto(knownType); }}; + SProcessor sut{"sut", "sutProj", "dev", "##GUID##", callbacks}; +}; + +TEST_CASE_FIXTURE(SpitClientFix, "Spit types") { + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type1Id#Rem"); + t.setFixed(true); + t.setServerRemote(true); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type1Name"); + t.setDelay(100); + t.setDuration(200); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "0: true type1Id#Rem type1Name sGroup", cbEvents.front()); + cbEvents.pop(); + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type2Id#Rem"); + t.setFixed(true); + t.setServerRemote(true); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type2Name"); + t.setDelay(100); + t.setDuration(200); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "0: true type2Id#Rem type2Name sGroup", cbEvents.front()); + cbEvents.pop(); + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type1Id#Rem"); + t.setFixed(true); + t.setServerRemote(true); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type1Name"); + t.setDelay(200); + t.setDuration(300); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "1: true type1Id#Rem type1Name sGroup", cbEvents.front()); + cbEvents.pop(); + + CHECK(cbEvents.empty()); + + // Local Objects + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type1Id#Loc"); + t.setFixed(true); + t.setServerRemote(false); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type1Name"); + t.setDelay(100); + t.setDuration(200); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "veto check false/false", cbEvents.front()); + cbEvents.pop(); + CHECK_MESSAGE(cbEvents.front() == "0: false type1Id#Loc type1Name sGroup", cbEvents.front()); + cbEvents.pop(); + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type2Id#Loc"); + t.setFixed(true); + t.setServerRemote(false); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type2Name"); + t.setDelay(100); + t.setDuration(200); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "veto check false/false", cbEvents.front()); + cbEvents.pop(); + CHECK_MESSAGE(cbEvents.front() == "0: false type2Id#Loc type2Name sGroup", cbEvents.front()); + cbEvents.pop(); + + { + Message::ReportType t; + t.setConfirmed(false); + t.setID("type1Id#Loc"); + t.setFixed(true); + t.setServerRemote(false); + t.setServerProjectIndepended(true); + t.setGroupName("sGroup"); + t.setName("type1Name"); + t.setDelay(200); + t.setDuration(300); + sut.checkParseMessageData(sut.createMessage(t)); + } + CHECK_MESSAGE(cbEvents.front() == "1: false type1Id#Loc type1Name sGroup", cbEvents.front()); + cbEvents.pop(); + CHECK(cbEvents.empty()); +} diff --git a/components/spit/uTest/spitProcessor_complexTest.cpp b/components/spit/uTest/spitProcessor_complexTest.cpp new file mode 100644 index 0000000..2b09b6a --- /dev/null +++ b/components/spit/uTest/spitProcessor_complexTest.cpp @@ -0,0 +1,511 @@ +/** + * @file spitRepoTest.cpp + * @author Gustice + * @brief + */ + +#include "doctest/doctest.h" +#include +#include +#include + +#include "spit_processor.hpp" + +using namespace spit; +using namespace std; +static queue cbEvents; + +class ClientMockCmplx { + public: + void onServerEvent(SProcessor::ServerEvent event, const SadDetectedServer &detectedServer) { + } + void onConnectionStatus(string serverID, string serverComputerName, string serverName, int serverStepTime, SProcessor::Connection connectionStatus, SProcessor::Connection oldConnectionStatus) { + } + void onProjectUpdate(SProcessor::ProjUpdate state, string projectId) { + } + void onSpitType(SProcessor::ObjectEvent event, bool isRemote, const SType &sType) { + cbEvents.push(fmt::format("{}: {} {} {} {}", (int)event, isRemote, sType.getID(), sType.Name.get(), sType.GroupName.get())); + } + void onSpitObject(SProcessor::ObjectEvent event, bool isRemote, const SType &sType, const SObject &sObject) { + cbEvents.push(fmt::format("{}: {} {} {} {} {}", (int)event, isRemote, sType.getID(), sType.Name.get(), sObject.Name.get(), sObject.getID())); + } + void onPlay(string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { + } + void onPlaySpitType(string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { + } + void onPlayRemoteObjectStatus(const SType &sType, const SObject &sObject, uint64_t p_FrameInsideObject, int value) { + } + bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) { + cbEvents.push(fmt::format("veto check {}/{}", knownType, createdByClient)); + return true; + } + bool onCheckSpitObjectVeto(bool knownType) { + return true; + } +}; + +class SpitClientCmplsFix { + protected: + ClientMockCmplx client; + SProcessor::Callbacks callbacks{ + .onServerEvent = [&](SProcessor::ServerEvent event, const SadDetectedServer &detectedServer) { client.onServerEvent(event, detectedServer); }, + .onConnectionStatus = [&](string serverID, string serverComputerName, string serverName, int serverStepTime, SProcessor::Connection connectionStatus, SProcessor::Connection oldConnectionStatus) { client.onConnectionStatus(serverID, serverComputerName, serverName, serverStepTime, connectionStatus, oldConnectionStatus); }, + .onProjectUpdate = [&](SProcessor::ProjUpdate state, string projectId) { client.onProjectUpdate(state, projectId); }, + .onSpitType = [&](SProcessor::ObjectEvent event, bool isRemote, const SType &t) { client.onSpitType(event, isRemote, t); }, + .onSpitObject = [&](SProcessor::ObjectEvent event, bool isRemote, const SType &t, const SObject &o) { client.onSpitObject(event, isRemote, t, o); }, + .onPlay = [&](string playerID, string playerName, char playerType, bool playerIsRunning, uint64_t timeFrames) { client.onPlay(playerID, playerName, playerType, playerIsRunning, timeFrames); }, + .onPlaySpitType = [&](string playerID, string spitTypeID, bool playerIsRunning, bool started, bool ended, double value) { client.onPlaySpitType(playerID, spitTypeID, playerIsRunning, started, ended, value); }, + .onPlayRemoteObjectStatus = [&](const SType &t, const SObject &o, uint64_t p_FrameInsideObject, int value) { client.onPlayRemoteObjectStatus(t, o, p_FrameInsideObject, value); }, + .onCheckSpitTypeVeto = [&](bool knownType, bool createdByClient) { return client.onCheckSpitTypeVeto(knownType, createdByClient); }, + .onCheckSpitObjectVeto = [&](bool knownType) { return client.onCheckSpitObjectVeto(knownType); }}; + SProcessor sut{"sut", "sutProj", "dev", "##GUID##", callbacks}; +}; + +static void spoofMsgCounter(std::vector &msg, uint8_t cnt) { + msg.at(11) = cnt; +} + +TEST_CASE_FIXTURE(SpitClientCmplsFix, "Spit types Raw") { + int cnt = 1; + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x41, 0x63, 0x00, 0x00, 0x00, // #spit#.....Ac... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x37, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000m70va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition1Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000m70va8bom InPosition1Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x42, 0x63, 0x00, 0x00, 0x00, // #spit#.....Bc... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x68, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000mh0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition2Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000mh0va8bom InPosition2Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x43, 0x63, 0x00, 0x00, 0x00, // #spit#.....Cc... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x72, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000mr0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x33, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition3Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000mr0va8bom InPosition3Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x44, 0x63, 0x00, 0x00, 0x00, // #spit#.....Dc... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6e, 0x6b, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000nk0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x34, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition4Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000nk0va8bom InPosition4Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x45, 0x63, 0x00, 0x00, 0x00, // #spit#.....Ec... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6e, 0x75, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000nu0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x35, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition5Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000nu0va8bom InPosition5Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + { + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x63, 0x00, 0x00, 0x00, // #spit#.....Fc... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x15, 0xa8, 0x00, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ........00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6f, 0x34, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000o40va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x00, 0x4d, 0x61, 0x69, 0x6e, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x6c, 0x00, // ....MainScene.l. + /*00a0*/ 0x00, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .ement.......... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x6e, 0x50, 0x6f, 0x73, // ...........InPos + /*00c0*/ 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x36, 0x53, 0x63, 0x65, 0x6e, 0x65, 0x00, 0x63, 0x65, 0x6e, 0x65, // ition6Scene.cene + /*00d0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00e0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00f0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ........... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000o40va8bom InPosition6Scene MainScene", cbEvents.front()); + cbEvents.pop(); + } + CHECK(cbEvents.empty()); + + { // In InPosition1Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7b, 0x63, 0x00, 0x00, 0x00, // #spit#.....{c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x37, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000m70va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6d, 0x37, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // m70va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xb9, 0x04, 0x00, // ................ + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0xed, 0x35, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....5.......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000m70va8bom InPosition1Scene play 00000m8uedyyt0000000000000000m70va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // In InPosition2Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7d, 0x63, 0x00, 0x00, 0x00, // #spit#.....}c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x68, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000mh0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6d, 0x68, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // mh0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xef, 0x06, 0x00, // ............r... + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x26, 0x2d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....&-.......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000mh0va8bom InPosition2Scene play 00000m8uedyyt0000000000000000mh0va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // In InPosition3Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x72, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000mr0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6d, 0x72, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // mr0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0xfc, 0x08, 0x00, // ................ + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x52, 0x2e, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....R........... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000mr0va8bom InPosition3Scene play 00000m8uedyyt0000000000000000mr0va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // In InPosition4Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x81, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6e, 0x6b, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000nk0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6e, 0x6b, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // nk0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, 0x0a, 0x00, // ................ + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x36, 0x33, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....63.......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000nk0va8bom InPosition4Scene play 00000m8uedyyt0000000000000000nk0va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // In InPosition5Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x83, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6e, 0x75, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000nu0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6e, 0x75, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // nu0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x01, 0x0d, 0x00, // ................ + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x75, 0x29, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....u).......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000nu0va8bom InPosition5Scene play 00000m8uedyyt0000000000000000nu0va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // In InPosition6Scene + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x85, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x6f, 0x34, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00000o40va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 0000000000000000 + /*00f0*/ 0x6f, 0x34, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // o40va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x05, 0x0f, 0x00, // ................ + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x13, 0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .....6.......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK_MESSAGE(cbEvents.front() == "0: true 00000m8uedyyt0000000000000000o40va8bom InPosition6Scene play 00000m8uedyyt0000000000000000o40va8bom", cbEvents.front()); + cbEvents.pop(); + } + { // unknown + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x87, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x31, 0x61, 0x75, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00001au0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, // 0000000000000001 + /*00f0*/ 0x61, 0x75, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // au0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x06, 0x11, 0x00, // ............2... + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0x33, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ....3S.......... + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK(cbEvents.empty()); + } + { // unknown + std::vector msg = { + /*0000*/ 0x23, 0x73, 0x70, 0x69, 0x74, 0x23, 0x00, 0x01, 0x00, 0x00, 0x00, 0x89, 0x63, 0x00, 0x00, 0x00, // #spit#......c... + /*0010*/ 0x34, 0x30, 0x35, 0x63, 0x37, 0x31, 0x30, 0x30, 0x2d, 0x36, 0x34, 0x65, 0x38, 0x2d, 0x34, 0x33, // 405c7100-64e8-43 + /*0020*/ 0x35, 0x64, 0x2d, 0x38, 0x61, 0x37, 0x62, 0x2d, 0x30, 0x30, 0x63, 0x35, 0x36, 0x32, 0x39, 0x66, // 5d-8a7b-00c5629f + /*0030*/ 0x39, 0x63, 0x63, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x30, 0x38, 0x36, 0x36, 0x63, 0x39, // 9ccf.....70866c9 + /*0040*/ 0x62, 0x2d, 0x61, 0x66, 0x31, 0x63, 0x2d, 0x34, 0x37, 0x36, 0x35, 0x2d, 0x61, 0x31, 0x37, 0x65, // b-af1c-4765-a17e + /*0050*/ 0x2d, 0x38, 0x62, 0x34, 0x35, 0x63, 0x39, 0x33, 0x66, 0x33, 0x61, 0x63, 0x61, 0x00, 0x00, 0x00, // -8b45c93f3aca... + /*0060*/ 0x00, 0x00, 0x1f, 0x53, 0x01, 0x00, 0x00, 0x01, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, // ...S....00000m8u + /*0070*/ 0x65, 0x64, 0x79, 0x79, 0x74, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // edyyt00000000000 + /*0080*/ 0x30, 0x30, 0x30, 0x30, 0x31, 0x66, 0x6a, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, // 00001fj0va8bom.. + /*0090*/ 0x00, 0x01, 0x01, 0x70, 0x6c, 0x61, 0x79, 0x00, 0x2f, 0x20, 0x46, 0x61, 0x64, 0x65, 0x20, 0x4f, // ...play./ Fade O + /*00a0*/ 0x75, 0x74, 0x00, 0x63, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ut.cy........... + /*00b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00c0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*00d0*/ 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x6d, 0x38, 0x75, 0x65, 0x64, 0x79, 0x79, 0x74, // ...00000m8uedyyt + /*00e0*/ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, // 0000000000000001 + /*00f0*/ 0x66, 0x6a, 0x30, 0x76, 0x61, 0x38, 0x62, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x69, 0x70, 0x00, // fj0va8bom....ip. + /*0100*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0110*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0120*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0130*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xad, 0x3a, 0x14, 0x00, // .............:.. + /*0140*/ 0x00, 0x00, 0x00, 0x00, 0xb4, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0150*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x42, 0x0f, 0x00, // ............@B.. + /*0160*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0170*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0180*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*0190*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01a0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + /*01b0*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // ...... + }; + spoofMsgCounter(msg, cnt++); + sut.checkParseMessageData(std::vector(msg.begin(), msg.end())); + CHECK(cbEvents.empty()); + } +} + + + diff --git a/esp_idf_project_configuration.json b/esp_idf_project_configuration.json index 774fcde..dd82b06 100644 --- a/esp_idf_project_configuration.json +++ b/esp_idf_project_configuration.json @@ -28,7 +28,9 @@ "compileArgs": [], "ninjaArgs": [], "buildDirectoryPath": "build_uTest", - "sdkconfigDefaults": [], + "sdkconfigDefaults": [ + "test/unitOnTarget/sdkconfig.defaults" + ], "sdkconfigFilePath": "" }, "env": { diff --git a/main/watchMain.cpp b/main/watchMain.cpp index b16a0cc..faf2be1 100644 --- a/main/watchMain.cpp +++ b/main/watchMain.cpp @@ -833,8 +833,8 @@ void SpitClientApp() { ProvidedObj.push_back(LocalSpitObj{.iD = provided.startShuffle, .groupName = provided.group, .name = provided.startShuffle}); ExpectedObjects[expected.changingPos] = ""; for (size_t i = 0; i < 6; i++) { - ProvidedObj.push_back(LocalSpitObj{.iD = provided.moveToX[i], .groupName = provided.group, .name = provided.moveToX[i]}); ProvidedSpitActions[provided.moveToX[i]] = MoveCommand{.type = MoveType::StepTo, .pos = (uint8_t)(i + 1)}; + ProvidedObj.push_back(LocalSpitObj{.iD = provided.moveToX[i], .groupName = provided.group, .name = provided.moveToX[i]}); ExpectedObjects[expected.inPosX[i]] = ""; } @@ -855,7 +855,7 @@ void SpitClientApp() { }); for (auto &obj : ProvidedObj) { - SType *ptrSPITType1Fix = spitClient.createSPITTypeFixed(obj.iD, obj.groupName, obj.name, 0, 0); + SType *ptrSPITType1Fix = spitClient.createTypeFixed(obj.iD, obj.groupName, obj.name, 0, 0); spitClient.setActionSPITType(ptrSPITType1Fix->getID(), true); // should be executed whenever a SPITObject with this SPITType is played } spitClient.clientProjectLoaded(); @@ -924,7 +924,7 @@ void app_main(void) { static fos::TaskT telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096); static fos::TaskT dmxNode(dmxSocketTask, ipVersion, "dmxNode", 4096); // static fos::Task spit(SpitClientApp, "SpitClient"); - // static fos::Task mqtt(MqttThread, "MqttEndpoint"); + static fos::Task mqtt(MqttThread, "MqttEndpoint"); // static Task otaUpdate(SystemFunctions::OtaTaskEntry, "otaTask", 8192); auto &store = NvsApi::getInstance(); diff --git a/sdkconfig b/sdkconfig index 55a84cc..1089526 100644 --- a/sdkconfig +++ b/sdkconfig @@ -579,6 +579,15 @@ CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # end of Partition Table +# +# Example Configuration +# +CONFIG_DEVICE_WIFI_SSID="eth2ap" +CONFIG_DEVICE_WIFI_PASSWORD="12345678" +CONFIG_DEVICE_WIFI_CHANNEL=1 +CONFIG_DEVICE_MAX_STA_CONN=4 +# end of Example Configuration + # # Example Ethernet Configuration # @@ -2136,6 +2145,17 @@ CONFIG_LITTLEFS_MALLOC_STRATEGY_DEFAULT=y # CONFIG_LITTLEFS_MALLOC_STRATEGY_INTERNAL is not set CONFIG_LITTLEFS_ASSERTS=y # end of LittleFS + +# +# Telnet Server +# +CONFIG_TELNET_SERVER_DEFAULT_PORT=23 +CONFIG_TELNET_SERVER_MAX_CONNECTIONS=5 +CONFIG_TELNET_SERVER_STACK_SIZE=4096 +CONFIG_TELNET_SERVER_TASK_PRIORITY=24 +CONFIG_TELNET_SERVER_TASK_CORE=0 +CONFIG_TELNET_SERVER_REDIRECT_LOGS=0 +# end of Telnet Server # end of Component config # CONFIG_IDF_EXPERIMENTAL_FEATURES is not set diff --git a/test/unitOnTarget/CMakeLists.txt b/test/unitOnTarget/CMakeLists.txt index bc2ba0c..cf204be 100644 --- a/test/unitOnTarget/CMakeLists.txt +++ b/test/unitOnTarget/CMakeLists.txt @@ -14,7 +14,7 @@ set(EXTRA_COMPONENT_DIRS # - when invoking CMake directly: cmake -D TEST_COMPONENTS="xxxxx" .. # - when using idf.py: idf.py -T xxxxx build # -set(TEST_COMPONENTS "testable freeRtosApi hwHal" CACHE STRING "List of components to test") +set(TEST_COMPONENTS "testable freeRtosApi hwHal spit" CACHE STRING "List of components to test" FORCE) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(unit_test) diff --git a/test/unitOnTarget/main/unitTest.cpp b/test/unitOnTarget/main/unitTest.cpp index 5fe007b..90aea1d 100644 --- a/test/unitOnTarget/main/unitTest.cpp +++ b/test/unitOnTarget/main/unitTest.cpp @@ -9,6 +9,8 @@ #include "unity.h" #include #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" extern "C" { // This switch allows the ROS C-implementation to find this main void app_main(void); @@ -33,5 +35,9 @@ void app_main(void) { printf("# - run tagged with [tag], \n"); printf("# - run all other than ![tag])\n"); printf("# Exit with 'Ctrl-]'\n"); - unity_run_menu(); + // unity_run_menu(); // Watchdog needs to + + while (true) { + vTaskDelay(10); + } }