4 Commits

Author SHA1 Message Date
gustice 348a1a1e14 tests: Make more tests run 2026-01-06 17:01:31 +01:00
gustice 118291f8ab refactor: Tidy up SPIT 2 2026-01-05 19:53:30 +01:00
gustice 4a97988227 refactor: Tidy up SPIT 2025-11-15 20:57:26 +01:00
gustice 7aec14cbb9 feat: shuffle mode 2025-11-15 18:19:06 +01:00
29 changed files with 832 additions and 3692 deletions
+1
View File
@@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.16)
if(TgtEnv STREQUAL "Host")
message("Using Host-Branch")
enable_testing()
add_subdirectory("test/unitOnHost")
elseif(TgtEnv STREQUAL "Target")
# add_subdirectory("test/unitOnTarget")
+25 -77
View File
@@ -1,16 +1,16 @@
#pragma once
#include "sad_DetectedServer.hpp"
#include "spit_message.hpp"
#include "spit_object.hpp"
#include "spit_player.hpp"
#include "spit_processor.hpp"
#include "spit_repo.hpp"
#include "spit_socket.hpp"
#include "spit_type.hpp"
#include "spit_message.hpp"
#include "spit_repo.hpp"
#include <functional>
#include <memory>
#include <vector>
#include <functional>
using namespace std;
@@ -18,60 +18,34 @@ namespace spit {
class SClient : ISadClient {
public:
/** Maximal length of a SPITMessage*/
static const int MAXSPITMESSAGEBYTECOUNT = 512;
using Callbacks = SProcessor::Callbacks;
using ProjUpdate = SProcessor::ProjUpdate;
using ServerEvent = SProcessor::ServerEvent;
using ObjectEvent = SProcessor::ObjectEvent;
using Connection = SProcessor::Connection;
//------ PlayerType ------
public:
/** continous main player, time value can be used like a timecode.<br>The time value is the position in server's project.<br>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;
using PlayerType = SPlayer::PTypes;
using ValueFlags = SPlayer::VFlags;
//------ 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.<br>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.<br>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;
//----- SClient -----
public:
SClient(string name, string projName, ISocket &socket, Callbacks calls);
virtual ~SClient();
private:
Callbacks mCallbacks;
fos::TaskT<SClient &> *mThreadReceive{};
fos::TaskT<SClient &> *mThreadProcess{};
bool mStopReceiveMessages{};
Connection mConnectionStatus{Connection::None};
bool mDisconnectedByServer{}; // flag true = when server disconnects
string mID;
string mName;
string mProjName;
string mComputerName;
SProcessor mProcessor;
string mClientProjectName;
uint8_t mMessageNumberSend{1};
int mMessageNumberReceived{-1}; // set to -1 because the first received message will set the number (1..255)
vector<unique_ptr<Message>> mOvertakingMessages;
// Server's info filled by parseConnectAnswer
string mServerID{};
@@ -81,12 +55,11 @@ class SClient : ISadClient {
public:
/** The ID of the client.<br>Every client instance should set an unique id*/
string getID() { return mID; }
string getID() { return mProcessor.getID(); }
/** The name of the client, should be set by the user app*/
string getName() { return mName; }
//----- Computer Params -----
string getName() { return mProcessor.getName(); }
/** The name of the client's host computer*/
string getComputerName() { return mComputerName; }
string getComputerName() { return mProcessor.getComputerName(); }
void setClientProjectName(string clientProjectName) { mClientProjectName = clientProjectName; }
string getClientProjectName() { return mClientProjectName; }
@@ -111,8 +84,12 @@ class SClient : ISadClient {
*/
void clientProjectLoaded();
void setActionSPITType(string spitypeID, bool actionAssigned);
void setActionSPITObject(string objectID, bool actionAssigned);
void setActionType(string spitypeID, bool actionAssigned) {
mProcessor.setActionType(spitypeID, actionAssigned);
}
void setActionObject(string objectID, bool actionAssigned) {
mProcessor.setActionObject(objectID, actionAssigned);
}
//--------------- SPITMessage ---------------
private:
@@ -159,7 +136,7 @@ class SClient : ISadClient {
private:
void disconnectInternal(Connection cause);
void resetMessageNumberReceived();
void parseMessage(unique_ptr<Message> message);
void parseMessage(Message& message);
void checkParseMessage(unique_ptr<Message> message);
void addOvertakingMessage(unique_ptr<Message> message);
void parseConnectAnswer(Message::ConnectAnswer &message);
@@ -175,11 +152,11 @@ class SClient : ISadClient {
//--------------- SPIT Project ---------------
/** Returns the SPITServer's project ID - may be the same as the project's name*/
string getServerProjectID();
string getServerProjectID() { return mProcessor.getServerProjectID(); }
/** Returns the SPITServer's project name*/
string getServerProjectName();
string getServerProjectName() { return mProcessor.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();
int getServerFramesPerSecond() { return mProcessor.getServerFramesPerSecond(); }
public:
static void sendProject(SClient *p_PtrSClient);
@@ -199,46 +176,17 @@ class SClient : ISadClient {
*/
SType *createTypeFixed(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration);
/**
* Creates a SPITType for application actions.<br>
* 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);
int sendTypeInternal(SType &spitType);
public:
bool changeType(SType *spitType) { return mProcessor.changeType(spitType); }
int removeType(string spitypeID) { return mProcessor.removeType(spitypeID); }
public:
//--------------- SPIT Objects ---------------
private:
int sendObjectInternal(SObject *sObject);
public:
/**
* When the client changes a SPITObject (normally the client should not do this), then it should send the changes to the SPITServer.<br>
* The SPITServer may discard the changes and an eventSPITObject occurs.<br>
* @param spitObject the pointer to the changed SPITObject.
* @return 0 = sended, -1 = not sended
*/
bool changeSPITObject(SObject *spitObject);
public:
//--------- Remote ----------
void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00);
bool changeObject(SObject *sObject) { return mProcessor.changeObject(sObject); }
void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00) {
mProcessor.sendRemoteObject(objectID, valuePpm, valueFlag);
}
private:
static void processSocketTask(SClient &instance);
@@ -252,4 +200,4 @@ class SClient : ISadClient {
}
};
}
} // namespace spit
+3
View File
@@ -14,6 +14,9 @@ namespace spit {
class Message {
//----------- Header -----------
public:
/** Maximal length of a SPITMessage*/
static const int MAX_MESSAGE_SIZE = 512;
class Header {
public:
static constexpr int BYTESLENGTH = 99;
+19 -1
View File
@@ -9,6 +9,24 @@ class SPlayer {
//----- PlayObject used in PlaySequences: PlaySPITStart, PlaySPITObject,..., PlaySPITEnd ------
public:
enum PTypes {
// diescrete player: This player is used to transmit single discrete values.
PTYPE_DISCRETE = 0x00,
// continous player: This player plays SPIT objects sometime during the project.
PTYPE_CONTINOUS = 0x01,
// continous main player: time value can be used like a timecode.<br>The time value is the position in server's project.<br>A server should use only one main player.
PTYPE_MAIN = 0x02,
};
enum VFlags {
// Set the given value directly
VFLAG_DIRECT = 0x00,
// Increase the existing value by the given value.<br>This is usefull e.g. when instead of a fader a endless wheel is used*/
VFLAG_INCREASE = 0x01,
// Decrease the existing value by the given value.<br>This is usefull e.g. when instead of a fader a endless wheel is used*/
VFLAG_DECREASE = 0x02,
};
class PlayType {
public:
PlayType(SPlayer *spitPlayer, string spitObjectID);
@@ -77,4 +95,4 @@ class SPlayer {
uint64_t mTimeFrames;
};
}
} // namespace spit
+37 -184
View File
@@ -16,9 +16,6 @@ namespace spit {
class SProcessor {
public:
// /** Maximal length of a SPITMessage*/
// static const int MAXSPITMESSAGEBYTECOUNT = 512;
enum class ProjUpdate {
ServerLoaded,
StartTransfer,
@@ -59,29 +56,10 @@ class SProcessor {
struct InternalCallbacks {
function<void(int ms)> delay;
function<int(Message::OPPart &msg)> sendMessage;
function<int(SType &sType)> sendTypeInternal;
function<int(SObject *sObject)> sendObjectInternal;
function<void(Message &msg)> parseMessage;
};
// //------ PlayerType ------
// public:
// /** continous main player, time value can be used like a timecode.<br>The time value is the position in server's project.<br>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.<br>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.<br>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;
static constexpr int MAX_OVERTAKING_SPIT_MESSAGES = 10;
//----- SProcessor -----
public:
@@ -93,153 +71,40 @@ class SProcessor {
Callbacks mCallbacks;
InternalCallbacks mInternCallbacks;
// Connection mConnectionStatus{Connection::None};
// bool mDisconnectedByServer{}; // flag true = when server disconnects
string mGuid;
string mName;
string mGuid;
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<unique_ptr<Message>> 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.<br>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.<br>
// * When the server plays objects, it will do so at discrete time steps.<br>
// * 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<char> createMessage(Message::OPPart & spitMessageOPPart);
string getID() { return mGuid; }
string getName() { return mName; }
string getProjName() { return mProjName; }
string getComputerName() { return mComputerName; }
void setActionType(string spitypeID, bool actionAssigned);
void setActionObject(string objectID, bool actionAssigned);
void checkParseMessageData(vector<char> 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);
unique_ptr<Message::Connect> createConnectMessage(string serverIP, string serverPort, string loginName, string loginPassword);
// //--------------- 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.<br>
// * 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();
std::vector<char> createMessage(Message::OPPart &spitMessageOPPart);
void parseMessage(Message &message);
// void addOvertakingMessage(unique_ptr<Message> message);
// void parseConnectAnswer(Message::ConnectAnswer &message);
// void parseDisconnect(Message::Disconnect &message);
// void parseWatchdog(Message::Watchdog &message);
// void parseWatchdogAnswer(Message::WatchdogAnswer &message);
void addOvertakingMessage(unique_ptr<Message> message);
int sendOvertakingMessage(int msgNumRec);
void resetMessageNumberReceived();
// public:
// /** Used internally*/
// void sendWatchdog();
// /** Used internally. When the connection to the SPITServer is lost an eventConnectionStatus will occur*/
// void eventWatchdogLost();
// //--------------- SPIT Project ---------------
// private:
public: // tood remove
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:
public: // todo remove
void parseRequestProjectTransfer(Message::RequestProjectTransfer &message);
void parseStartProjectTransfer(Message::StartProjectTransfer &message);
void parseEndProjectTransfer(Message::EndProjectTransfer &message);
// // --------------- SPIT Types ---------------
// public:
// /**
// * Creates a fixed SPITType for application actions that are always present and project independent.<br>
// * Fixed SPIT types cannot be changed or deleted by the server.<br>
// * 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);
string getServerProjectID() { return mServerProjectID; }
string getServerProjectName() { return mServerProjectName; }
int getServerFramesPerSecond() { return mServerFramesPerSecond; }
// /**
// * Creates a SPITType for application actions.<br>
@@ -253,13 +118,9 @@ class SProcessor {
// * @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:
public: // @todo delete
void parseReportType(Message::ReportType &message);
void parseRemoveType(Message::RemoveType &message);
SType *createType(string iD, string groupName, string name, uint64_t defaultDelay, uint64_t defaultDuration, bool fixed, bool projectIndepended);
int sendTypeInternal(SType &sType);
public:
/**
* If a client wants to change a SPITType, he should send it to the server.<br>
* 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.<br>
@@ -275,41 +136,33 @@ public: // @todo delete
*/
int removeType(string spitypeID);
// public:
// //--------------- SPIT Objects ---------------
// private:
public:
int removeObject(string objectID);
bool changeObject(SObject *sObject);
void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00);
void resetConfirmedFlags() {
SType::setConfirmedFalse(mSpitTypes);
SObject::setConfirmedFalse(mSpitObjects);
}
private:
void parseReportProject(Message::ReportProject &message);
void parseCloseProject(Message::CloseProject &message);
void parseRequestProjectTransfer(Message::RequestProjectTransfer &message);
void parseStartProjectTransfer(Message::StartProjectTransfer &message);
void parseEndProjectTransfer(Message::EndProjectTransfer &message);
void parseReportType(Message::ReportType &message);
void parseRemoveType(Message::RemoveType &message);
void parseReportObject(Message::ReportObject &message);
void parseRemoveObject(Message::RemoveObject &message);
// int sendSPITObjectInternal(SObject *ptrObject);
// public:
int removeObject(string objectID);
// public:
// //--------------- Play SPIT Objects ---------------
// private:
public:
void parsePlayStart(Message::PlayStart &message);
void parsePlayObject(Message::PlayObject &message);
void parsePlayEnd(Message::PlayEnd &message);
void parseReportPlayStatus(Message::ReportPlayStatus &message);
int sendObjectInternal(SObject *sObject);
// public:
// //--------- Remote ----------
// void sendRemoteObject(string objectID, int valuePpm = 0, char valueFlag = 0x00);
// private:
// bool mAbortSearch{};
// bool sAnswered{};
// void answerWatchdog() {
// sAnswered = true;
// }
public: // @todo remove
SpitRepo<SObject> mSpitObjects;
SpitRepo<SObject> mRemoteSpitObjects;
SpitRepo<SType> mSpitTypes;
SpitRepo<SObject> mRemoteSpitObjects;
SpitRepo<SType> mRemoteSpitTypes;
};
+32 -297
View File
@@ -6,7 +6,7 @@
namespace spit {
static const char *TAG = "SPIT";
static fos::Queue<vector<char>> incommingSpit(64);
static fos::Queue<vector<char>> incommingSpit(128);
/**
@@ -16,19 +16,14 @@ static fos::Queue<vector<char>> incommingSpit(64);
SClient::SClient(string name, string projName, ISocket &socket, Callbacks calls)
: ISadClient(),
mCallbacks(calls),
mName(name),
mProjName(projName),
mProcessor(name, projName, getClientHostName(), createGUID(), calls,
{
.delay = [&](int ms){ return fos::Task::delayMs(ms); },
.sendMessage = [&](Message::OPPart &msg){ return sendMessage(msg); },
.sendTypeInternal = [&](SType &sType) { return sendTypeInternal(sType);},
.sendObjectInternal = [&](SObject *sObject) { return sendObjectInternal(sObject);}
.parseMessage = [&](Message& msg) { parseMessage(msg); }
}
),
mSocket(socket) {
mID = createGUID();
mComputerName = getClientHostName();
}
SClient::~SClient() {
@@ -39,7 +34,7 @@ SClient::~SClient() {
void SClient::clientProjectClose() {
if (mConnectionStatus == Connection::Ok) {
ESP_LOGI(TAG, " ... tidy up ressources");
Message::CloseProject closeSPITProject(mProjName);
Message::CloseProject closeSPITProject(mProcessor.getProjName());
if (sendMessage(closeSPITProject) < 0) {
ESP_LOGD(TAG, "Client could not send Client's ReportProject");
}
@@ -48,12 +43,10 @@ void SClient::clientProjectClose() {
void SClient::clientProjectLoaded() {
// set confirmed = false for all SPITTypes and SPITObjects
SType::setConfirmedFalse(mProcessor.mSpitTypes);
SObject::setConfirmedFalse(mProcessor.mSpitObjects);
mProcessor.resetConfirmedFlags();
if (mConnectionStatus == Connection::Ok) {
// send ReportProject to the server
Message::ReportProject reportSPITProject(mProjName, mProjName);
Message::ReportProject reportSPITProject(mProcessor.getProjName(), mProcessor.getProjName());
reportSPITProject.setFramesPerSecond(0);
if (sendMessage(reportSPITProject) < 0) {
ESP_LOGD(TAG, "SPIT_CLient::clientProjectLoaded could not send Client's ReportProject");
@@ -67,39 +60,6 @@ void SClient::clientProjectLoaded() {
}
}
/**
* 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 SClient::setActionSPITType(string typeId, bool actionAssigned) {
SType *spitType = mProcessor.mSpitTypes.getEntry(typeId);
if (spitType == nullptr)
return;
if (spitType->ActionAssigned.set(actionAssigned)) {
sendTypeInternal(*spitType);
for (auto& [key, value] : mProcessor.mSpitObjects.getRepo()) {
if (value->SPITTypeID.get() == spitType->getID()) {
if (value->setActionAssignedType(actionAssigned) == true) {
sendObjectInternal(value.get());
}
}
}
}
}
/** This should be called if the user wants to associate/remove an action with a SPITObject. */
void SClient::setActionSPITObject(string spitObjId, bool actionAssigned) {
SObject *spitObject = mProcessor.mSpitObjects.getEntry(spitObjId);
if (spitObject == nullptr)
return;
if (spitObject->setActionAssigned(actionAssigned) == true) {
sendObjectInternal(spitObject);
}
}
//---------- ServerAutoDetection SAD -----------
/** Starts the autodetection of SPITServers in the local network. If a connection is tried, the autodetection should be stopped before.
@@ -214,7 +174,7 @@ int SClient::sendMessage(Message::OPPart &opPart) {
else
mMessageNumberSend++;
opPart.setMessageNumber(mMessageNumberSend);
opPart.setServerInfoInHeader(mID, mServerID);
opPart.setServerInfoInHeader(mProcessor.getID(), mServerID);
int opFlag = opPart.getHeader()->getType();
try {
@@ -247,10 +207,10 @@ void SClient::stopReceiveSPITMessages() {
}
void SClient::receiveSpitMessage(SClient &rM) {
char buffer[MAXSPITMESSAGEBYTECOUNT + 1];
char buffer[Message::MAX_MESSAGE_SIZE];
int rdLen;
while (rM.mStopReceiveMessages == false) {
rdLen = rM.mSocket.receiveMessage(buffer, MAXSPITMESSAGEBYTECOUNT, nullptr);
rdLen = rM.mSocket.receiveMessage(buffer, Message::MAX_MESSAGE_SIZE, nullptr);
if (rdLen < 0) {
if (rM.mStopReceiveMessages) {
return;
@@ -267,14 +227,14 @@ void SClient::processSpitMessage(SClient &rM) {
while (true) {
auto data = *incommingSpit.dequeue();
auto spitMsg = make_unique<Message>(data);
rM.parseMessage(move(spitMsg));
rM.checkParseMessage(move(spitMsg));
}
}
void SClient::resetMessageNumberReceived() {
mMessageNumberReceived = -1;
mOvertakingMessages.clear();
mProcessor.resetMessageNumberReceived();
}
void SClient::checkParseMessage(unique_ptr<Message> p_SPITMessage) {
@@ -287,12 +247,12 @@ void SClient::checkParseMessage(unique_ptr<Message> p_SPITMessage) {
int msgNum = (int)(p_SPITMessage->getHeader()->getMessageNumber() & 0xFF);
if (msgNum == 0) {
parseMessage(std::move(p_SPITMessage));
parseMessage(*p_SPITMessage);
return;
}
if (mMessageNumberReceived < 0) {
mMessageNumberReceived = msgNum;
parseMessage(std::move(p_SPITMessage));
parseMessage(*p_SPITMessage);
return;
}
@@ -302,122 +262,39 @@ void SClient::checkParseMessage(unique_ptr<Message> p_SPITMessage) {
if (msgNum == intNextMessageNumber) {
mMessageNumberReceived = msgNum;
parseMessage(std::move(p_SPITMessage));
// check overtaking messages
auto it = mOvertakingMessages.begin();
while (mOvertakingMessages.size() > 0) {
intNextMessageNumber = mMessageNumberReceived + 1;
if (intNextMessageNumber > 255 || intNextMessageNumber < 1)
intNextMessageNumber = 1;
auto &ptrOvertakingSPIT_Message = *it;
msgNum = (int)(ptrOvertakingSPIT_Message->getHeader()->getMessageNumber() & 0xFF);
if (msgNum == intNextMessageNumber) {
mMessageNumberReceived = msgNum;
parseMessage(move(ptrOvertakingSPIT_Message));
mOvertakingMessages.erase(it);
it = mOvertakingMessages.begin();
} else {
break;
}
}
parseMessage(*p_SPITMessage);
mMessageNumberReceived = mProcessor.sendOvertakingMessage(mMessageNumberReceived);
} else {
// p_SPITMessage has overtaken another message
addOvertakingMessage(move(p_SPITMessage));
mProcessor.addOvertakingMessage(move(p_SPITMessage));
}
}
void SClient::addOvertakingMessage(unique_ptr<Message> message) {
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 SClient::parseMessage(unique_ptr<Message> message) {
void SClient::parseMessage(Message& message) {
answerWatchdog();
if (!message || !message->getHeader() || !message->getOPPart()) {
if (!message.getHeader() || !message.getOPPart()) {
ESP_LOGD(TAG, "Client::parseMessage incomplete message");
return;
}
switch (message->getType()) {
switch (message.getType()) {
//----- Connection -----
case Message::ConnectAnswer::OPFLAG:
parseConnectAnswer(message->getAs<Message::ConnectAnswer>());
parseConnectAnswer(message.getAs<Message::ConnectAnswer>());
break;
case Message::Disconnect::OPFLAG:
parseDisconnect(message->getAs<Message::Disconnect>());
break;
case Message::ReportProject::OPFLAG:
mProcessor.parseReportProject(message->getAs<Message::ReportProject>());
parseDisconnect(message.getAs<Message::Disconnect>());
break;
case Message::Watchdog::OPFLAG:
parseWatchdog(message->getAs<Message::Watchdog>());
parseWatchdog(message.getAs<Message::Watchdog>());
break;
case Message::WatchdogAnswer::OPFLAG:
parseWatchdogAnswer(message->getAs<Message::WatchdogAnswer>());
break;
//----- SPIT Project -----
case Message::StartProjectTransfer::OPFLAG:
mProcessor.parseStartProjectTransfer(message->getAs<Message::StartProjectTransfer>());
break;
case Message::CloseProject::OPFLAG:
mProcessor.parseCloseProject(message->getAs<Message::CloseProject>());
break;
case Message::RequestProjectTransfer::OPFLAG:
mProcessor.parseRequestProjectTransfer(message->getAs<Message::RequestProjectTransfer>());
break;
case Message::EndProjectTransfer::OPFLAG:
mProcessor.parseEndProjectTransfer(message->getAs<Message::EndProjectTransfer>());
break;
//----- SPIT Types ------
case Message::ReportType::OPFLAG:
mProcessor.parseReportType(message->getAs<Message::ReportType>());
break;
case Message::RemoveType::OPFLAG:
mProcessor. parseRemoveType(message->getAs<Message::RemoveType>());
//----- SPIT Objects ------
break;
case Message::ReportObject::OPFLAG:
mProcessor.parseReportObject(message->getAs<Message::ReportObject>());
break;
case Message::RemoveObject::OPFLAG:
mProcessor.parseRemoveObject(message->getAs<Message::RemoveObject>());
break;
//----- Play SPIT Objects ------
case Message::PlayStart::OPFLAG:
mProcessor.parsePlayStart(message->getAs<Message::PlayStart>());
break;
case Message::PlayObject::OPFLAG:
mProcessor.parsePlayObject(message->getAs<Message::PlayObject>());
break;
case Message::PlayEnd::OPFLAG:
mProcessor.parsePlayEnd(message->getAs<Message::PlayEnd>());
break;
case Message::ReportPlayStatus::OPFLAG:
mProcessor.parseReportPlayStatus(message->getAs<Message::ReportPlayStatus>());
parseWatchdogAnswer(message.getAs<Message::WatchdogAnswer>());
break;
default:
ESP_LOGD(TAG, "Client::parseMessage: Unknown Message");
// pass object to SubProcessor
mProcessor.parseMessage(message);
}
}
@@ -439,15 +316,8 @@ bool SClient::connect(string serverIP, string serverPort, string clientIP, strin
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);
auto connMsg = mProcessor.createConnectMessage(serverIP, serverPort, loginName, loginPassword);
if (startReceiveSPITMessages() == false) {
mStopReceiveMessages = true;
@@ -462,7 +332,7 @@ bool SClient::connect(string serverIP, string serverPort, string clientIP, strin
// sleep a little to make sure that the reception of the messages is started
fos::Task::delayMs(500);
if (sendMessage(sMConnect) < 0) {
if (sendMessage(*connMsg) < 0) {
mConnectionStatus = Connection::None;
mStopReceiveMessages = true;
return false;
@@ -528,7 +398,7 @@ void SClient::disconnectInternal(Connection cause) {
}
void SClient::parseConnectAnswer(Message::ConnectAnswer &message) {
if (message.getClientID() != mID)
if (message.getClientID() != mProcessor.getID())
return;
mServerID = message.getServerID();
@@ -539,7 +409,6 @@ void SClient::parseConnectAnswer(Message::ConnectAnswer &message) {
if (message.getConnected() == false) {
disconnectInternal(Connection::NoneServer);
} else {
message.getStepTime();
mConnectionStatus = Connection::Ok;
mDisconnectedByServer = false;
ESP_LOGD(TAG, "connection established");
@@ -559,10 +428,7 @@ void SClient::parseConnectAnswer(Message::ConnectAnswer &message) {
*/
void SClient::parseDisconnect(Message::Disconnect &message) {
Connection intCauseDisconnect = Connection::NoneServer;
/*
function<void()> o_Callable = bind(&SClient::disconnectInternal, this, intCauseDisconnect);
SPIT_Handler::addCallable(o_Callable);
*/
mDisconnectedByServer = true;
SClient::disconnectInternal(intCauseDisconnect);
}
@@ -575,7 +441,6 @@ void SClient::parseDisconnect(Message::Disconnect &message) {
* @param message
*/
void SClient::parseWatchdog(Message::Watchdog &message) {
// ESP_LOGD(TAG, "parse Watchdog ");
Message::WatchdogAnswer o_WatchdogAnswer;
sendMessage(o_WatchdogAnswer);
}
@@ -604,9 +469,6 @@ void SClient::eventWatchdogLost() {
}
}
string SClient::getServerProjectID() { return mProcessor.getServerProjectID(); }
string SClient::getServerProjectName() { return mProcessor.getServerProjectName(); }
int SClient::getServerFramesPerSecond() { return mProcessor.getServerFramesPerSecond(); }
void SClient::sendProject(SClient *p_PtrSPIT_Client) {
// int intResult;
@@ -669,135 +531,8 @@ void SClient::sendProject(SClient *p_PtrSPIT_Client) {
// //Send act
}
/**
* 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 SClient::sendTypeInternal(SType &p_SPITType) {
Message::ReportType sMReportSPITType;
p_SPITType.fillMessageOP(sMReportSPITType);
return sendMessage(sMReportSPITType);
}
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::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 = mProcessor.mSpitTypes.getEntry(p_ID);
if (ptrSPITType == nullptr) {
auto spitType = make_unique<SType>(p_ID, p_GroupName, p_Name, p_FIxed, p_ProjectIndepended, p_DefaultDelay, p_DefaultDuration);
ptrSPITType = spitType.get();
mProcessor.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);
sendTypeInternal(*ptrSPITType);
return ptrSPITType;
}
int SClient::sendObjectInternal(SObject *ptrSPITObject) {
if (ptrSPITObject == nullptr)
return -1;
Message::ReportObject sMReportSPITObject;
ptrSPITObject->fillMessageOP(sMReportSPITObject);
return sendMessage(sMReportSPITObject);
}
/**
* 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 SClient::changeSPITObject(SObject *obj) {
if (obj == nullptr)
return false;
SObject *ptrSPITObject;
SType *ptrSPITType;
{
ptrSPITObject = mProcessor.mSpitObjects.getEntry(obj->getID());
if (ptrSPITObject == nullptr)
return false;
ptrSPITType = mProcessor.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);
sendObjectInternal(ptrSPITObject);
}
return true;
}
//--------- 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 SClient::sendRemoteObject(string p_SPITObjectID, int valuePpm, char valueFlag) {
SObject *ptrRemoteSPITObject = mProcessor.mRemoteSpitObjects.getEntry(p_SPITObjectID);
if (ptrRemoteSPITObject == nullptr)
return;
Message::PlayStart playSPITStart(mID, mProjName, PLAYERTYPE_DISCRETE);
playSPITStart.setPlayerIsRunning(false);
playSPITStart.setTime(0);
sendMessage(playSPITStart);
Message::PlayObject playSPITObject;
playSPITObject.setID(ptrRemoteSPITObject->getID());
playSPITObject.setPlayPrePosition(false);
playSPITObject.setPlayerID(mID);
playSPITObject.setValue(valuePpm);
playSPITObject.setValueFlag(valueFlag);
sendMessage(playSPITObject);
Message::PlayEnd playSPITEnd(mID);
sendMessage(playSPITEnd);
SType *SClient::createTypeFixed(string iD, string group, string name, uint64_t delay, uint64_t duration) {
return mProcessor.createType(iD, group, name, delay, duration, true, true);
}
fos::Semaphore SClient::sStartSad;
@@ -888,7 +623,7 @@ void SClient::processSocketTask(SClient &instance) {
ESP_LOGW(TAG, "Finished searching");
ESP_LOGW(TAG, "Start working");
auto nextWdTrigger = fos::Timing::getMilliSec() + WATCHDOGTIME;
auto nextWdCheck = nextWdTrigger + WATCHDOGTIME;
// auto nextWdCheck = nextWdTrigger + WATCHDOGTIME;
while (true) {
// auto time = fos::Timing::getMilliSec();
// if (time > nextWdTrigger) {
File diff suppressed because it is too large Load Diff
+33 -34
View File
@@ -1,3 +1,5 @@
-- COPY to: /usr/lib/x86_64-linux-gnu/wireshark/plugins/spit.lua
-- LiveShowSoftware SPIT-Protocol
spit_proto = Proto("spit", "LiveShowSoftware SPIT")
spit_sad_proto = Proto("spit_sad", "LiveShowSoftware SPIT SAD")
@@ -9,7 +11,7 @@ local f_hLen = ProtoField.uint32("spit.len", "Length")
local f_hSerId = ProtoField.string("spit.serverId", "ServerID")
local f_hCliId = ProtoField.string("spit.clientId", "ClientID")
local f_hType = ProtoField.uint8("spit.msgType", "MsgType")
local f_pLen = ProtoField.uint32("spit.paylen", "Length")
local f_pLen = ProtoField.uint32("spit.paylen", "Payload Length")
local f_pSession = ProtoField.string("spit.key", "Spit Session")
local f_pKey = ProtoField.string("spit.key", "Spit Key")
@@ -94,6 +96,17 @@ function extractVersionString(buffer)
end
function addBigEndianValue(tree, proto, buffer)
local val = -1;
-- local val = buffer(99,4):le_uint()
if proto.type == ftypes.UINT32 then
val = buffer:le_uint()
elseif proto.type == ftypes.UINT64 then
val = buffer:le_uint64()
end
tree:add(proto, buffer):set_text(proto.name .. ": " .. val)
end
-- Heuristic dissector function
function spit_proto.dissector(buffer, pinfo, tree)
if buffer:len() < 6 then return false end
@@ -114,8 +127,9 @@ function spit_proto.dissector(buffer, pinfo, tree)
hTree:add(f_hType, buffer(98,1))
local pTree = subtree:add("Payload")
local pLen = buffer(99,4):le_uint()
pTree:add(f_pLen, buffer(99,4)):set_text("Pyload Length: " .. pLen)
-- local pLen = buffer(99,4):le_uint()
-- pTree:add(f_pLen, buffer(99,4)):set_text("Pyload Length: " .. pLen)
addBigEndianValue(pTree, f_pLen, buffer(99,4))
local info_text = "Type: " .. type
if type == 1 then -- Connect
@@ -166,7 +180,7 @@ function spit_proto.dissector(buffer, pinfo, tree)
pTree:add(f_pProjectId, buffer(103,41))
pTree:add(f_pProjectName, buffer(144,64))
pTree:add(f_pFramesPerSec, buffer(208,4))
addBigEndianValue(pTree, f_pFramesPerSec, buffer(208,4))
info_text = string.format("%s -> %s | Report Project | Project: %s / %s",
sessionInfos[tostring(pinfo.src)], sessionInfos[tostring(pinfo.dst)], buffer(103,41):string(), buffer(144,64):string())
@@ -202,8 +216,8 @@ function spit_proto.dissector(buffer, pinfo, tree)
pTree:add(f_pProjIndep, buffer(147,1))
pTree:add(f_pTypeGroupName, buffer(148,39))
pTree:add(f_pTypeName, buffer(187,64))
pTree:add(f_pDelay, buffer(251,8))
pTree:add(f_pDuration, buffer(259,8))
addBigEndianValue(pTree, f_pDelay, buffer(251,8))
addBigEndianValue(pTree, f_pDuration, buffer(259,8))
local group = buffer(148,39):string()
local name = buffer(187,64):string()
@@ -226,17 +240,16 @@ function spit_proto.dissector(buffer, pinfo, tree)
pTree:add(f_pObjectName, buffer(147,64))
pTree:add(f_pTypeId, buffer(211,41))
pTree:add(f_pSrvParam, buffer(252,64))
pTree:add(f_pFrameStart, buffer(316,8))
pTree:add(f_pFrameLength, buffer(324,8))
pTree:add(f_pFrameFadeIn, buffer(332,8))
pTree:add(f_pFrameFadeOut, buffer(340,8))
local valueFactor = buffer(348,4):le_uint()
pTree:add(f_pValueFactor, buffer(348,4)):set_text("Value Factor" .. valueFactor)
addBigEndianValue(pTree, f_pFrameStart, buffer(316,8))
addBigEndianValue(pTree, f_pFrameLength, buffer(324,8))
addBigEndianValue(pTree, f_pFrameFadeIn, buffer(332,8))
addBigEndianValue(pTree, f_pFrameFadeOut, buffer(340,8))
addBigEndianValue(pTree, f_pValueFactor, buffer(348,4))
pTree:add(f_pValueUse, buffer(349,1))
pTree:add(f_pTrack, buffer(350,4))
addBigEndianValue(pTree, f_pTrack, buffer(350,4))
pTree:add(f_pRemark, buffer(354,64))
pTree:add(f_pDelay, buffer(418,8))
pTree:add(f_pDuration, buffer(426,8))
addBigEndianValue(pTree, f_pDelay, buffer(418,8))
addBigEndianValue(pTree, f_pDuration, buffer(426,8))
pTree:add(f_pAssigned, buffer(435,1))
local name = buffer(147,64):string()
@@ -257,17 +270,16 @@ function spit_proto.dissector(buffer, pinfo, tree)
pTree:add(f_pPlayerName, buffer(144,64))
pTree:add(f_pPlayerType, buffer(208,1))
pTree:add(f_pPlayerRunning, buffer(209,1))
pTree:add(f_pPlayerFrames, buffer(210,8))
addBigEndianValue(pTree, f_pPlayerFrames, buffer(210,8))
info_text = string.format("Play SPIT Start")
elseif type == 38 then -- Play Spit object
pTree:add(f_pSession, extractSession(buffer, pinfo))
pTree:add(f_pPlayerId, buffer(103,41))
pTree:add(f_pObjectId, buffer(144,41))
pTree:add(f_pObjectsFrames, buffer(185,8))
addBigEndianValue(pTree, f_pObjectsFrames, buffer(185,8))
pTree:add(f_pPlayerPrePos, buffer(193,1))
pTree:add(f_pValue, buffer(194,4))
addBigEndianValue(pTree, f_pValue, buffer(194,4))
pTree:add(f_pValueFlag, buffer(198,1))
local oId = buffer(144,41):string()
@@ -281,10 +293,9 @@ function spit_proto.dissector(buffer, pinfo, tree)
elseif type == 40 then
pTree:add(f_pSession, extractSession(buffer, pinfo))
pTree:add(f_pObjectId, buffer(103,41))
pTree:add(f_pObjectsFrames, buffer(144,8))
pTree:add(f_pValue, buffer(152,4))
addBigEndianValue(pTree, f_pObjectsFrames, buffer(144,8))
addBigEndianValue(pTree, f_pValue, buffer(152,4))
info_text = string.format("Report Play Status")
else
@@ -348,15 +359,3 @@ spit_proto:register_heuristic("udp", spit_proto.dissector)
spit_sad_proto:register_heuristic("udp", spit_sad_proto.dissector)
-- local f_pFramesPerSec = ProtoField.uint32("spit.framesPerSec", "Frames per second")
-- local f_pTrack = ProtoField.uint32("spit.track", "Track")
-- local f_pObjectsFrames = ProtoField.uint64("spit.ObjectFrames", "Object Frames")
-- local f_pValue = ProtoField.uint64("spit.Value", "Value")
-- local f_pFrameStart = ProtoField.uint64("spit.frameStart", "Frame Start")
-- local f_pFrameLength = ProtoField.uint64("spit.frameLength", "Frame Length")
-- local f_pFrameFadeIn = ProtoField.uint64("spit.fadeInLength", "Fade In Length")
-- local f_pFrameFadeOut = ProtoField.uint64("spit.fadeOutLength", "Fade Out Length")
-- local f_pDelay = ProtoField.uint64("spit.delay", "Delay")
-- local f_pDuration = ProtoField.uint64("spit.duration", "Duration")
-- local f_pPlayerFrames = ProtoField.uint64("spit.PlayerFrame", "Player Frames")
+177 -3
View File
@@ -46,6 +46,8 @@ class ClientMock {
class SpitClientFix {
protected:
std::vector<string> messages;
ClientMock client;
SProcessor::Callbacks callbacks{
.onServerEvent = [&](SProcessor::ServerEvent event, const SadDetectedServer &detectedServer) { client.onServerEvent(event, detectedServer); },
@@ -61,14 +63,15 @@ class SpitClientFix {
SProcessor::InternalCallbacks intCallbacks{
.delay = [&](int ms) { return; },
.sendMessage = [&](Message::OPPart &msg) { return 0; },
.sendTypeInternal = [&](SType &sType) { return 0; },
.sendObjectInternal = [&](SObject *sObject) { return 0; }
.parseMessage = [&](Message &msg) {
// auto o = fmt::format("msg-{}", msg.getHeader()->getMessageNumber());
// messages.push_back(o);
},
};
SProcessor sut{"sut", "sutProj", "dev", "##GUID##", callbacks, intCallbacks};
};
TEST_CASE_FIXTURE(SpitClientFix, "Spit types") {
{
Message::ReportType t;
t.setConfirmed(false);
@@ -174,3 +177,174 @@ TEST_CASE_FIXTURE(SpitClientFix, "Spit types") {
cbEvents.pop();
CHECK(cbEvents.empty());
}
TEST_CASE_FIXTURE(SpitClientFix, "Message Counter") {
Message::ReportType t1;
t1.setID("type#1");
t1.setServerRemote(true);
auto m1 = sut.createMessage(t1);
Message::ReportType t2;
t2.setID("type#2");
t2.setServerRemote(true);
auto m2 = sut.createMessage(t2);
Message::ReportType t3;
t3.setID("type#3");
t3.setServerRemote(true);
auto m3 = sut.createMessage(t3);
Message::ReportType t4;
t4.setID("type#4");
t4.setServerRemote(true);
auto m4 = sut.createMessage(t4);
Message::ReportType t5;
t5.setID("type#5");
t5.setServerRemote(true);
auto m5 = sut.createMessage(t5);
Message::ReportType t6;
t6.setID("type#6");
t6.setServerRemote(true);
auto m6 = sut.createMessage(t6);
CHECK(cbEvents.empty());
SUBCASE("Normal order") {
REQUIRE(cbEvents.size() == 0);
sut.checkParseMessageData(m1);
CHECK_MESSAGE(cbEvents.front() == "0: true type#1 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m2);
CHECK_MESSAGE(cbEvents.front() == "0: true type#2 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m3);
CHECK_MESSAGE(cbEvents.front() == "0: true type#3 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m4);
CHECK_MESSAGE(cbEvents.front() == "0: true type#4 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
}
CHECK(cbEvents.empty());
SUBCASE("overtakes one") {
REQUIRE(cbEvents.size() == 0);
sut.checkParseMessageData(m1);
CHECK_MESSAGE(cbEvents.front() == "0: true type#1 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m3);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m2);
CHECK_MESSAGE(cbEvents.front() == "0: true type#2 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#3 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m4);
CHECK_MESSAGE(cbEvents.front() == "0: true type#4 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
}
CHECK(cbEvents.empty());
SUBCASE("overtakes two") {
REQUIRE(cbEvents.size() == 0);
sut.checkParseMessageData(m1);
CHECK_MESSAGE(cbEvents.front() == "0: true type#1 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m4);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m2);
CHECK_MESSAGE(cbEvents.front() == "0: true type#2 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m3);
CHECK_MESSAGE(cbEvents.front() == "0: true type#3 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#4 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m5);
CHECK_MESSAGE(cbEvents.front() == "0: true type#5 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
}
CHECK(cbEvents.empty());
SUBCASE("many overtakes") {
REQUIRE(cbEvents.size() == 0);
sut.checkParseMessageData(m1);
CHECK_MESSAGE(cbEvents.front() == "0: true type#1 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m5);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m6);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m4);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m3);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m2);
CHECK_MESSAGE(cbEvents.front() == "0: true type#2 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#3 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#4 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#5 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#6 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
}
CHECK(cbEvents.empty());
SUBCASE("reverse order") {
REQUIRE(cbEvents.size() == 0);
sut.checkParseMessageData(m1);
CHECK_MESSAGE(cbEvents.front() == "0: true type#1 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
sut.checkParseMessageData(m6);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m5);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m4);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m3);
CHECK(cbEvents.empty());
sut.checkParseMessageData(m2);
CHECK_MESSAGE(cbEvents.front() == "0: true type#2 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#3 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#4 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#5 ", cbEvents.front());
cbEvents.pop();
CHECK_MESSAGE(cbEvents.front() == "0: true type#6 ", cbEvents.front());
cbEvents.pop();
CHECK(cbEvents.empty());
}
}
@@ -61,8 +61,7 @@ class SpitClientCmplsFix {
SProcessor::InternalCallbacks intCallbacks {
.delay = [&](int ms){ return ; },
.sendMessage = [&](Message::OPPart &msg){ return 0; },
.sendTypeInternal = [&](SType &sType) { return 0; },
.sendObjectInternal = [&](SObject *sObject) { return 0; }
.parseMessage = [&](Message &msg) { },
};
SProcessor sut{"sut", "sutProj", "dev", "##GUID##", callbacks, intCallbacks};
};
+13 -5
View File
@@ -3,15 +3,17 @@
#include "stepperDrv.hpp"
#include "stepperMotor.hpp"
#include <cmath>
#include "logging.hpp"
class WatchMotor {
static constexpr uint8_t Positions = 6;
public:
using AllmostFinishedCb = void (*)(uint8_t newIdx);
WatchMotor(IStepperMotor &stepper, AllmostFinishedCb onDone)
using AlmostFinishedCb = void (*)(uint8_t newIdx);
WatchMotor(IStepperMotor &stepper, AlmostFinishedCb onDone, ILogging &logger)
: _stepper(stepper),
_onFinCb(onDone) {
_onFinCb(onDone),
_logger(logger) {
}
void moveTo(uint8_t position, uint8_t profile, int minJumps, float accel, float speed) {
@@ -44,7 +46,12 @@ class WatchMotor {
ESP_LOGD("MV", "Moving to %d by %.2f + %.2f", sign, delta, corr);
_stepper.moveBy(delta + corr, profile, accel, speed, [&]() {
_stepper.moveBy(delta + corr, profile, accel, speed, [&](int diff) {
_logger.logv(ILogging::Severity::Debug,"Almost done with head=%i",diff);
if (diff < 6) {
_logger.logv(ILogging::Severity::Warning,"Low headroom in Profile pipeline=%i",diff);
}
if (_onFinCb) {
_onFinCb(position);
}
@@ -58,5 +65,6 @@ class WatchMotor {
private:
IStepperMotor &_stepper;
uint8_t _currentIndex{};
AllmostFinishedCb _onFinCb{};
AlmostFinishedCb _onFinCb{};
ILogging &_logger;
};
@@ -1,4 +1,5 @@
UnitTestsFrame()
target_link_libraries(${moduleName} PUBLIC
devHal
bases
)
@@ -19,7 +19,7 @@ class StepperMotorMock : public IStepperMotor {
lastAngle = angle;
lastProfile = profile;
}
void moveBy(float angle, uint8_t profile, float accel, float speed, std::function<void()> profileDone = nullptr) override {
void moveBy(float angle, uint8_t profile, float accel, float speed, std::function<void(int diff)> profileDone = nullptr) override {
lastAngle = angle;
lastProfile = profile;
}
@@ -37,6 +37,12 @@ class StepperMotorMock : public IStepperMotor {
float nextPos{};
};
class LoggerMock : public ILogging {
void output(Severity severity, std::string message) override {
// do nothing
}
};
void onFin(uint8_t idx) {
}
@@ -47,7 +53,8 @@ class WatchFaceFixture {
protected:
static constexpr int MicroSteps = 32;
StepperMotorMock motor;
WatchMotor sut{motor, onFin};
LoggerMock logger;
WatchMotor sut{motor, onFin, logger};
private:
};
+1 -1
Submodule core updated: e09e7dc576...37e288c012
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,7 @@ struct {
const char *mqttBroker = "mqttBroker"; // example: "172.16.16.10"
const char *mqttPrefix = "mqttPrefix"; // example: "SomeTag"
const char *spitServer = "spitServer"; // example: "172.16.16.10"
const char *motorPower = "motorPower"; // example: "50"
} ConfigKeys;
// MQTT Topics
+98 -22
View File
@@ -17,7 +17,7 @@
// activeState.speed = (min .5 / max 3)
#include "watchMain.hpp"
#include "interconConfig.hpp"
#include "config.hpp"
using namespace spit;
@@ -104,7 +104,7 @@ void testPictoIllum(Cli::CArgs args) {
int p = std::stoi(args[0]);
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(p));
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s and %s", args[0].c_str(), args[1].c_str());
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
@@ -132,6 +132,25 @@ void testMovement(Cli::CArgs args) {
}
}
void testFeedback(Cli::CArgs args) {
ESP_LOGI(TAG, "on triggerMovement:");
if (args.size() != 1) {
pShell->writeLine("need target position (1..6) or 0 for moving");
return;
}
try {
int p = std::stoi(args[0]);
if (p == 0) {
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StartMoving, 0));
} else {
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, p));
}
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
void setConfig(Cli::CArgs args) {
if (args.size() != 2) {
pShell->writeLine("Needs string key and value");
@@ -187,9 +206,22 @@ void showProcessValues(Cli::CArgs args) {
pShell->writeLine(std::string{" Provile: "} + std::to_string((int)activeState.profile));
}
void startDemoMovement(Cli::CArgs args) {
ESP_LOGI(TAG, "on startDemoMovement:");
commandQueue.enqueue(std::make_unique<MoveCommand>(MoveType::Demo));
void setSyslogLevel(Cli::CArgs args) {
if (args.size() != 1) {
pShell->writeLine("Needs SyslogLevel Warning = 4, Notice = 5, Informational = 6, Debug = 7");
return;
}
try {
auto lvl = std::stoi(args[0]);
if (lvl >= (int)Syslog::Severity::Warning && lvl <= (int)Syslog::Severity::Debug) {
Syslog::setSeverity((Syslog::Severity)lvl);
} else {
pShell->writeLine("New level was not accepted");
}
} catch (const std::exception &e) {
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
/**
@@ -209,8 +241,11 @@ static void telnetSocketTask(int addrFamily) {
{"update", "Start OTA-Update-Process",
[](Cli::CArgs a) { startUpdate(a); }});
pShell->addBinding(
{"logserver_set", "Set log server config ip",
{"setLogserver", "Set log server config ip",
[](Cli::CArgs a) { setLogServerConfig(a); }});
pShell->addBinding(
{"setLogLevel", "Set severity log server",
[](Cli::CArgs a) { setSyslogLevel(a); }});
pShell->addBinding(
{"getcfg", "Get configuration value for key",
@@ -220,7 +255,7 @@ static void telnetSocketTask(int addrFamily) {
[](Cli::CArgs a) { setConfig(a); }});
pShell->addBinding(
{"dyn_set", "set dynamics of movement (velocity,accelerations) as floats",
{"setDyn", "set dynamics of movement (velocity,accelerations) as floats",
[](Cli::CArgs a) { setDynamics(a); }});
pShell->addBinding(
{"tstMove", "start movement (profile-idx,steps) as integers ",
@@ -228,6 +263,9 @@ static void telnetSocketTask(int addrFamily) {
pShell->addBinding(
{"tstIllum", "test illumination command 0=off /1..6",
[](Cli::CArgs a) { testPictoIllum(a); }});
pShell->addBinding(
{"tstFb", "test feedback-channel to control 0=Move /1..6=FinalPos",
[](Cli::CArgs a) { testFeedback(a); }});
pShell->addBinding(
{"showData", "Show process values that are input by DMX, MQTT and SPIT",
[](Cli::CArgs a) { showProcessValues(a); }});
@@ -425,7 +463,7 @@ namespace Effect {
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
}
} // namespace Effect
void LightingTask() {
ESP_LOGI(TAG, "Start Lighting");
@@ -475,7 +513,7 @@ void LightingTask() {
};
while (true) {
auto onPos = pictoIllumQue.dequeue(0);
auto onPos = pictoIllumQue.tryDequeue();
if (onPos) {
ESP_LOGI(TAG, "Changing picto-Illum to pos = %i", onPos->pos);
ESP_LOGI(TAG, "Current color set r%i g%i b%i ",
@@ -520,7 +558,20 @@ void MovementTask() {
{LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3},
{GPIO_NUM_21, GPIO_NUM_20, GPIO_NUM_23, GPIO_NUM_22},
};
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps, 0.25F);
float power = 0.25F;
// try
// {
// auto pwr = store.getValue(ConfigKeys.motorPower);
// power = std::stof(pwr);
// }
// catch(...)
// {
// std::cerr << e.what() << '\n';
// ESP_LOGI("Stepper", "Applying default");
// }
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps, power);
stepperDriver.setPos(0);
StepperConfig stepperCfg{1.8F, MicroSteps};
@@ -534,10 +585,11 @@ void MovementTask() {
StepperMotor stepper(stepperCfg, stepperDriver, initSens);
SyslogInst logger;
WatchMotor watch(stepper, [](uint8_t newPos) {
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(newPos));
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, newPos));
});
}, logger);
ESP_LOGI("Stepper", "Find Home");
stepper.findRef();
@@ -583,6 +635,33 @@ void MovementTask() {
// pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(newPos));
// responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, newPos));
}
} else if (cmd->type == MoveType::Shuffle) {
Syslog::logv(Syslog::Severity::Informational,
"Starting Shuffle mode");
while (true) {
int pos = Random::randomWithIn(1,6);
int profile = Random::randomWithIn(0,3);
if (stepper.isIdle()) {
Syslog::logv(Syslog::Severity::Notice,
"Running Stepper to %i by min%i steps with prof=%i a=%.2f w=%.2f",
pos, activeState.minJumps, activeState.profile, activeState.accel, activeState.speed);
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(0));
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StartMoving, 0));
auto &as = activeState;
watch.moveTo(pos, profile, as.minJumps, as.accel, as.speed);
}
// int delay = Random::randomWithIn(20000,100000)/portTICK_PERIOD_MS;
int delay = Random::randomWithIn(2000,3000)/portTICK_PERIOD_MS;
Syslog::logv(Syslog::Severity::Informational,
"ShuffleMode Wait for %i", delay);
auto cmd = commandQueue.tryDequeueFor(delay);
if (cmd) {
if (cmd->type != MoveType::Shuffle) {
commandQueue.enqueue(std::move(cmd));
break;
}
}
}
} else if (cmd->type == MoveType::Demo) {
ESP_LOGI(TAG, "Running Demo");
for (size_t i = ProfileGenerator::Smooth; i < ProfileGenerator::NumProfiles; i++) {
@@ -776,14 +855,14 @@ void onPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_Pl
ESP_LOGD(TAG, "eventPlay Player: %s Runs: %d Time: %lld", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames);
switch (p_PlayerType) {
case SClient::PLAYERTYPE_MAIN:
case SClient::PlayerType::PTYPE_MAIN:
// p_FrameTimes contains the position inside the server's project, we can use it like a timecode
// int intMilliseconds = (int)(((double)p_TimeFrames / (double)m_ServerFramesPerSecond) * 1000);
break;
case SClient::PLAYERTYPE_CONTINOUS:
case SClient::PlayerType::PTYPE_CONTINOUS:
// The olayer is playing only single Object sequences sometime during the project
break;
case SClient::PLAYERTYPE_DISCRETE:
case SClient::PlayerType::PTYPE_DISCRETE:
// Only discrete values where submitted, e.g the fader position of remote faders.
break;
}
@@ -856,7 +935,7 @@ void SpitClientApp() {
for (auto &obj : ProvidedObj) {
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.setActionType(ptrSPITType1Fix->getID(), true); // should be executed whenever a SPITObject with this SPITType is played
}
spitClient.clientProjectLoaded();
spitClient.startServerAutoDetect();
@@ -913,12 +992,11 @@ void app_main(void) {
initialize_ethernet();
NvsApi::init();
static fos::Task lightingTask(LightingTask, "Lights", 0x8000uL);
static fos::Task movementTask(MovementTask, "Motor", 0x8000uL);
static fos::Task movementTask(MovementTask, "Motor", 0x8000uL, fos::Task::MAX_PRIORITY-4 );
etherActive.take();
fos::Task::delayMs(10000);
ESP_LOGI(TAG, "Start net services");
// esp_log_level_set("SPIT", esp_log_level_t::ESP_LOG_DEBUG);
static int ipVersion = AF_INET;
static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
@@ -942,10 +1020,8 @@ void app_main(void) {
while (true) {
fos::Task::delayMs(5000);
// ToDo send
Syslog::logv(Syslog::Severity::Notice, "Health state");
// ESP_LOGI(TAG, "Min heap size: %" PRIu32 " / FreeHeap %" PRIu32 "\n",
// ESP_LOGI(TAG, "Min heap size: %u / FreeHeap %lu",
// heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
// esp_get_free_heap_size());
Syslog::logv(Syslog::Severity::Notice, "Min heap size: %u / FreeHeap %lu",
heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT),
esp_get_free_heap_size());
}
}
+1 -16
View File
@@ -40,22 +40,7 @@
#include "nvsFunctions.hpp"
#include "mqttClient.hpp"
#include "watchFace.hpp"
// #include "esp_chip_info.h"
// #include "esp_flash.h"
// #include "esp_ota_ops.h"
// #include "esp_partition.h"
// #include "esp_random.h"
// #include "esp_system.h"
// #include "fileSystem.hpp"
// #include "lwip/apps/netbiosns.h"
// #include "mdns.h"
// #include "soc/soc_caps.h"
// #include "systemFunctions.hpp"
// #include <inttypes.h>
// #include <sys/param.h>
// #include <unistd.h>
#include "random.hpp"
#include "sad_DetectedServer.hpp"
#include "spit_object.hpp"
#include "spit_player.hpp"
+20
View File
@@ -0,0 +1,20 @@
.PHONY: start test clean
start:
./startCode
# testConfig: buildTestOnTarget
test:
cmake -DTgtEnv:STRING=Target -S . -B buildTestOnTarget
cmake --build buildTestOnTarget --parallel
idf.py -B buildTestOnTarget -p /dev/ttyACM0 flash monitor
uTest:
cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++ -DTgtEnv:STRING=Host -S . -B buildUTest
cmake --build buildUTest --parallel
ctest --test-dir buildUTest
clean:
rm -rf build buildTestOnTarget
+3 -3
View File
@@ -1,12 +1,12 @@
cmake_minimum_required(VERSION 3.16)
project(UnitTests)
include(../../core/test/unitOnHost/test_core.cmake)
UnitTestSetup()
enable_testing()
project(UnitTests)
addSubDirs_ofRoot("${CMAKE_CURRENT_LIST_DIR}/../../components")
addSubDirs_ofRoot("${CMAKE_CURRENT_LIST_DIR}/../../core/components")
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../core/test/unitOnHost/hwMock" hwMock)
# add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../core/test/unitOnHost/freeRtos" freeRtos)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../core/test/unitOnHost/netMock" netMock)
add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/../../core/test/unitOnHost/osMock" osMock)
File diff suppressed because it is too large Load Diff