refactor/bringup: Bringup full project
moving SPIT-App parts to main app LiveShowDemoProject added Debugging motor movements
This commit is contained in:
+431
-72
@@ -6,15 +6,18 @@
|
||||
* @copyright Copyright (c) 2024
|
||||
*/
|
||||
|
||||
// Conig-Key:
|
||||
//
|
||||
//
|
||||
//
|
||||
/* Watchface
|
||||
6/
|
||||
5 / 1
|
||||
4 2
|
||||
3
|
||||
*/
|
||||
|
||||
struct {
|
||||
const char *syslogDest = "syslogDst"; // example: "172.16.16.10"
|
||||
const char *mqttBroker = "mqttBroker"; // example: "172.16.17.62"
|
||||
const char *mqttBroker = "mqttBroker"; // example: "172.16.16.10"
|
||||
const char *mqttPrefix = "mqttPrefix"; // example: "SomeTag"
|
||||
const char *spitServer = "spitServer"; // example: "172.16.16.10"
|
||||
} ConfigKeys;
|
||||
|
||||
// MQTT Topics
|
||||
@@ -27,6 +30,33 @@ struct {
|
||||
const char *changingPosition = /* <mqttPrefix>/ */ "watch/changingPosition";
|
||||
} MqttTopics;
|
||||
|
||||
struct {
|
||||
const char *expectedServer = "";
|
||||
struct {
|
||||
const char *group = "CatasWatchMovement";
|
||||
const char *startShuffle = "ActionStartShuffle";
|
||||
const char *moveToX[6] = {
|
||||
"ActionMoveTo1",
|
||||
"ActionMoveTo2",
|
||||
"ActionMoveTo3",
|
||||
"ActionMoveTo4",
|
||||
"ActionMoveTo5",
|
||||
"ActionMoveTo6",
|
||||
};
|
||||
} Provided;
|
||||
struct {
|
||||
const char *changingPos = "ChangingPositionScene";
|
||||
const char *inPosX[6] = {
|
||||
"InPosition1Scene",
|
||||
"InPosition2Scene",
|
||||
"InPosition3Scene",
|
||||
"InPosition4Scene",
|
||||
"InPosition5Scene",
|
||||
"InPosition6Scene",
|
||||
};
|
||||
} Expected;
|
||||
} SpitTypes;
|
||||
|
||||
// ToDo:
|
||||
// - MQTT Integration
|
||||
// - OTA
|
||||
@@ -36,8 +66,8 @@ struct {
|
||||
|
||||
#include "watchMain.hpp"
|
||||
|
||||
string MyApp::s_ClientName = "CatasWatchDev";
|
||||
string MyApp::s_ProjectName = "CatastrphicProj";
|
||||
string ClientName = "CatasWatchDev";
|
||||
string ProjectName = "CatastrphicProj";
|
||||
|
||||
extern "C" { // This switch allows the ROS C-implementation to find this main
|
||||
void app_main(void);
|
||||
@@ -47,20 +77,29 @@ struct DeviceState {
|
||||
uint8_t minJumps{6};
|
||||
uint8_t maxJumps{32};
|
||||
uint8_t profile{};
|
||||
uint8_t restTime{};
|
||||
uint8_t shuffleRate{};
|
||||
float speed = 1.0; // Rad/sec
|
||||
float accel = 1.0; // Rad/sec^2
|
||||
Color color{0x80, 0x80, 0x80};
|
||||
uint8_t pictogram{}; // 0..5 active Pictogramm
|
||||
};
|
||||
|
||||
enum class MoveType {
|
||||
StepTo,
|
||||
Demo,
|
||||
Shuffle,
|
||||
Demo
|
||||
};
|
||||
enum class ResponseType {
|
||||
StepAt,
|
||||
StartMoving,
|
||||
};
|
||||
struct MoveCommand {
|
||||
MoveType type;
|
||||
// 1..6
|
||||
uint8_t pos;
|
||||
};
|
||||
struct WatchIndex {
|
||||
ResponseType type;
|
||||
// 1..6
|
||||
uint8_t pos;
|
||||
};
|
||||
struct PictoIllumCommand {
|
||||
@@ -68,6 +107,7 @@ struct PictoIllumCommand {
|
||||
};
|
||||
|
||||
static fos::Queue<MoveCommand> commandQueue(8);
|
||||
static fos::Queue<WatchIndex> responseQueue(8);
|
||||
static fos::Queue<PictoIllumCommand> pictoIllumQue(2);
|
||||
|
||||
DeviceState activeState;
|
||||
@@ -245,7 +285,7 @@ static void UniverseCallback(const uint8_t *data, const uint16_t size) {
|
||||
Syslog::logv(Syslog::Severity::Debug, "Got DMX: r%0x g%0x b%0x i%0x m%i M%i p%i a%i w%i r%i",
|
||||
/* RGB*/ data[0], data[1], data[2], /*Intens*/ data[3],
|
||||
/* MinMaxJumps */ data[4], data[5], /*profile*/ data[6], /*accel/speed*/ data[7], data[8],
|
||||
/*RestTime*/ data[9]);
|
||||
/*shuffleRate*/ data[9]);
|
||||
|
||||
float intens = (float)data[3] / UINT8_MAX;
|
||||
activeState.color = Color{
|
||||
@@ -263,7 +303,7 @@ static void UniverseCallback(const uint8_t *data, const uint16_t size) {
|
||||
activeState.accel = (float)accel / 100 + 0.5; // min .5 / max 3
|
||||
activeState.speed = (float)velo / 100 + 0.5; // min .5 / max 3
|
||||
|
||||
activeState.restTime = data[9];
|
||||
activeState.shuffleRate = data[9];
|
||||
}
|
||||
|
||||
void moveToSubs(std::string data) {
|
||||
@@ -346,6 +386,7 @@ static void dmxSocketTask(int addrFamily) {
|
||||
}
|
||||
|
||||
fos::Semaphore etherActive;
|
||||
fos::Semaphore spitProjectFinish;
|
||||
|
||||
/** Event handler for IP_EVENT_ETH_GOT_IP */
|
||||
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||
@@ -437,7 +478,7 @@ namespace Effect {
|
||||
};
|
||||
|
||||
const Macro macDemoFlicker = {
|
||||
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
|
||||
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
|
||||
{32, 1, StateMachine::UpdateFlicker, 0xFF},
|
||||
};
|
||||
}
|
||||
@@ -472,14 +513,23 @@ void LightingTask() {
|
||||
processors[5].setEffect(Effect::macDark, &colorSource, 0);
|
||||
|
||||
const std::array<Effect::Macro, 6> PictoEffects{
|
||||
Effect::macDemoPulse, // 1
|
||||
Effect::macDemoPulse,
|
||||
Effect::macDemoPulse,
|
||||
Effect::macDemoPulse,
|
||||
Effect::macDemoPulse,
|
||||
Effect::macDemoPulse,
|
||||
Effect::macStartFlicker};
|
||||
Effect::macStartFlicker,
|
||||
Effect::macDemoPulse}; // 6
|
||||
|
||||
uint8_t lastPicto = 0;
|
||||
uint8_t lastPicto = 1;
|
||||
|
||||
std::array<uint16_t *, 6> startPoints{
|
||||
&(values[0][4]), // 1
|
||||
&(values[1][12]),
|
||||
&(values[1][8]),
|
||||
&(values[1][4]),
|
||||
&(values[0][12]),
|
||||
&(values[0][8]), // 6
|
||||
};
|
||||
|
||||
while (true) {
|
||||
auto onPos = pictoIllumQue.dequeue(0);
|
||||
@@ -504,14 +554,6 @@ void LightingTask() {
|
||||
}
|
||||
}
|
||||
|
||||
std::array<uint16_t *, 6> startPoints{
|
||||
&(values[0][4]),
|
||||
&(values[0][8]),
|
||||
&(values[0][12]),
|
||||
&(values[1][4]),
|
||||
&(values[1][8]),
|
||||
&(values[1][12]),
|
||||
};
|
||||
for (size_t i = 0; i < processors.size(); i++) {
|
||||
auto col = processors[i].tick();
|
||||
auto sp = startPoints[i];
|
||||
@@ -533,7 +575,7 @@ void MovementTask() {
|
||||
StepperDriverDrv8833::Pins stepperPins{
|
||||
LEDC_TIMER_0,
|
||||
{LEDC_CHANNEL_0, LEDC_CHANNEL_1, LEDC_CHANNEL_2, LEDC_CHANNEL_3},
|
||||
{GPIO_NUM_23, GPIO_NUM_22, GPIO_NUM_21, GPIO_NUM_20},
|
||||
{GPIO_NUM_21, GPIO_NUM_20, GPIO_NUM_23, GPIO_NUM_22},
|
||||
};
|
||||
StepperDriverDrv8833 stepperDriver(stepperPins, MicroSteps, 0.25F);
|
||||
stepperDriver.setPos(0);
|
||||
@@ -549,25 +591,34 @@ void MovementTask() {
|
||||
|
||||
StepperMotor stepper(stepperCfg, stepperDriver, initSens);
|
||||
|
||||
WatchMotor watch(stepper, motorSleep);
|
||||
|
||||
ESP_LOGI("Stepper", "Find Home");
|
||||
stepper.findRef();
|
||||
// Illum 1
|
||||
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(1));
|
||||
// Todo Set by User-Interface
|
||||
for (size_t i = 0; i < 7; i++) {
|
||||
stepper.fullStep(1);
|
||||
fos::Task::delayMs(40);
|
||||
}
|
||||
(void)stepper.zeroPosition();
|
||||
while (!stepper.isIdle()) {
|
||||
fos::Task::delayMs(40);
|
||||
}
|
||||
// watch.moveTo(1, ProfileGenerator::Unitform);
|
||||
ESP_LOGI("Stepper", "Got to 1");
|
||||
// Illum 6
|
||||
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(0));
|
||||
|
||||
ESP_LOGI(TAG, "Fist Position is %f.2", stepper.getScaledPos() * 6);
|
||||
ESP_LOGI(TAG, "Fist Position is %.2f", watch.getScaled());
|
||||
fos::Task::delayMs(1000);
|
||||
|
||||
activeState.pictogram = 0;
|
||||
|
||||
while (true) {
|
||||
ESP_LOGD(TAG, "Waiting for command");
|
||||
auto cmd = commandQueue.dequeue();
|
||||
if (cmd->type == MoveType::StepTo) {
|
||||
if (stepper.isIdle()) {
|
||||
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(0));
|
||||
int newPos = cmd->pos;
|
||||
if ((newPos >= 1) && (newPos <= 6)) {
|
||||
auto idx = newPos - 1;
|
||||
Syslog::logv(Syslog::Severity::Informational,
|
||||
"Triggered movement to picto pos:%i ", newPos);
|
||||
} else {
|
||||
@@ -575,61 +626,368 @@ void MovementTask() {
|
||||
"Got invalid index for illuminated pictogram =%i ", newPos);
|
||||
continue;
|
||||
}
|
||||
int delta = newPos - activeState.pictogram;
|
||||
if (delta <= 0) {
|
||||
delta += 6;
|
||||
|
||||
int jumps = newPos - watch.getIndex();
|
||||
if (jumps <= 0) {
|
||||
jumps += 6;
|
||||
}
|
||||
delta = delta + (activeState.minJumps % 6) * 6;
|
||||
if (delta < activeState.minJumps) {
|
||||
delta += 6;
|
||||
jumps = jumps + (activeState.minJumps % 6) * 6;
|
||||
if (jumps < activeState.minJumps) {
|
||||
jumps += 6;
|
||||
}
|
||||
Syslog::logv(Syslog::Severity::Notice,
|
||||
"Running Stepper by %i steps with prof=%i a=%.2f w=%.2f",
|
||||
delta, activeState.profile, activeState.accel, activeState.speed);
|
||||
jumps, activeState.profile, activeState.accel, activeState.speed);
|
||||
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(0));
|
||||
stepper.moveBy(delta * std::numbers::pi / 3,
|
||||
activeState.profile, activeState.accel, activeState.speed);
|
||||
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StartMoving, 0));
|
||||
watch.moveTo(newPos, activeState.profile);
|
||||
|
||||
pictoIllumQue.enqueue(std::make_unique<PictoIllumCommand>(newPos));
|
||||
activeState.pictogram = newPos;
|
||||
responseQueue.enqueue(std::make_unique<WatchIndex>(ResponseType::StepAt, newPos));
|
||||
}
|
||||
} else if (cmd->type == MoveType::Demo) {
|
||||
int i = 0;
|
||||
while (i++ < 80) {
|
||||
stepperDriver.step(1);
|
||||
stepperDriver.getSubPos();
|
||||
fos::Task::delayMs(100);
|
||||
}
|
||||
ESP_LOGI("Stepper", "Find Home");
|
||||
stepper.findRef();
|
||||
activeState.pictogram = -1;
|
||||
stepper.findRef();
|
||||
fos::Task::delayMs(1000);
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
stepper.moveBy(std::numbers::pi / 3);
|
||||
while (!stepper.isIdle()) {
|
||||
fos::Task::delayMs(100);
|
||||
ESP_LOGI(TAG, "Running Demo");
|
||||
for (size_t i = ProfileGenerator::Smooth; i < ProfileGenerator::NumProfiles; i++) {
|
||||
ESP_LOGI(TAG, "Running Profile %d ", i);
|
||||
fos::Task::delayMs(1000);
|
||||
int steps[3]{4, 2, 0};
|
||||
for (size_t j = 0; j < 3; j++) {
|
||||
watch.moveTo(steps[j], i);
|
||||
fos::Task::delayMs(1000);
|
||||
}
|
||||
ESP_LOGI(TAG, "Position is %f.2", stepper.getScaledPos() * 6);
|
||||
}
|
||||
} else {
|
||||
fos::Task::delayMs(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
struct LocalSpitObj {
|
||||
string iD;
|
||||
string groupName;
|
||||
string name;
|
||||
};
|
||||
std::map<string, MoveCommand> ProvidedSpitActions;
|
||||
std::map<string, string> ExpectedObjects;
|
||||
|
||||
void onServerEvent(SPIT_Client::ServerEvent event, const SAD_DetectedServer &p_DetectedServer) {
|
||||
switch (event) {
|
||||
case SPIT_Client::ServerEvent::Detect:
|
||||
ESP_LOGI(TAG, "SERVER DETECTED");
|
||||
ESP_LOGI(TAG, " Name: %s", p_DetectedServer.getName().data());
|
||||
ESP_LOGI(TAG, " ID: %s", p_DetectedServer.getID().data());
|
||||
ESP_LOGI(TAG, " Computer: %s", p_DetectedServer.getComputerName().data());
|
||||
ESP_LOGI(TAG, " IP: %s", p_DetectedServer.getIP().data());
|
||||
ESP_LOGI(TAG, " Port: %s", p_DetectedServer.getPort().data());
|
||||
ESP_LOGI(TAG, " Addition: %s", p_DetectedServer.getAdditions().data());
|
||||
ESP_LOGI(TAG, " ClientIP: %s", p_DetectedServer.getClientIP().data());
|
||||
break;
|
||||
case SPIT_Client::ServerEvent::Lost:
|
||||
ESP_LOGW(TAG, "Server lost Name: %s IP: %s", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
|
||||
|
||||
break;
|
||||
case SPIT_Client::ServerEvent::Changed:
|
||||
ESP_LOGW(TAG, "Server lost Name: %s IP: %s", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void onConnectionStatus(string p_ServerID, string p_ServerComputerName, string p_ServerName, int p_ServerStepTime, int p_ConnectionStatus, int p_OldConnectionStatus) {
|
||||
ESP_LOGI(TAG, "MySPITApp: eventConnectionStatus %d ", p_ConnectionStatus);
|
||||
}
|
||||
|
||||
// The transfer of the server's SPITTypes and SPITObjects is finished.
|
||||
void onProjectUpdate(SPIT_Client::ProjUpdate state, string projectId) {
|
||||
|
||||
switch (state) {
|
||||
case SPIT_Client::ProjUpdate::ServerLoaded:
|
||||
ESP_LOGI(TAG, "eventProjectReport ID: %s ", projectId.data());
|
||||
break;
|
||||
case SPIT_Client::ProjUpdate::StartTransfer:
|
||||
ESP_LOGI(TAG, "eventStartProjectTransfer");
|
||||
break;
|
||||
case SPIT_Client::ProjUpdate::EndTransfer:
|
||||
ESP_LOGI(TAG, "eventEndProjectTransfer");
|
||||
spitProjectFinish.give();
|
||||
break;
|
||||
case SPIT_Client::ProjUpdate::ServerClosed:
|
||||
ESP_LOGI(TAG, "eventProjectClosed ID: %s", projectId.data());
|
||||
// If we don't save SPITServer's project specific information
|
||||
// perhaps close all SPITObjects and RemoteSPITObjects to avoid conflicts, when the SPITServer loads a new project
|
||||
// SPITObject::clearSPITObjects();
|
||||
// SPITObject::clearSPITObjectsRemote();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The SPITCLientInterface (implemented by this) will be asked to veto the SPITType while SPIT_Client.parseReportSPITType.<br>
|
||||
* @param p_ReportSPITType
|
||||
* @return false = the SPITType is denied, true = the SPITType is accepted
|
||||
*/
|
||||
bool onCheckSpitTypeVeto(SPIT_Message::ReportSPITType *p_ReportSPITType) {
|
||||
return true; // Bypass veto
|
||||
|
||||
if (p_ReportSPITType == NULL)
|
||||
return true;
|
||||
SPITType *ptrSPITType;
|
||||
ptrSPITType = SPITType::getSPITType(p_ReportSPITType->getID());
|
||||
|
||||
// Don't allow foreign SPITTypes
|
||||
if (ptrSPITType == NULL) {
|
||||
// ESP_LOGW(TAG, "ObjectVeto NoSpitType");
|
||||
return false;
|
||||
}
|
||||
if (ptrSPITType->getCreatedByClient() == false) {
|
||||
// ESP_LOGW(TAG, "getCreatedByClient");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onCheckSpitObjectVeto(SPIT_Message::ReportSPITObject *p_ReportSPITObject) {
|
||||
return true; // Bypass veto
|
||||
|
||||
if (p_ReportSPITObject == NULL)
|
||||
return true;
|
||||
SPITType *ptrSPITType = SPITType::getSPITType(p_ReportSPITObject->getSPITTypeID());
|
||||
if (ptrSPITType == NULL) {
|
||||
// ESP_LOGW(TAG, "ObjectVeto NoSpitObj");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't allow SPITObjects which refers to a SPITType which is not created by this client - other SPITTypes cannot be handled here
|
||||
if (ptrSPITType->getCreatedByClient() == false) {
|
||||
// ESP_LOGW(TAG, "getCreatedByClient");
|
||||
return false;
|
||||
}
|
||||
SPITObject *ptrSPITObject = SPITObject::getSPITObject(p_ReportSPITObject->getID());
|
||||
// Don't allow foreign SPITTypes
|
||||
if (ptrSPITObject == NULL) {
|
||||
// ESP_LOGE(TAG, "Unknown ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called when the server has created, loaded, changed or deleted a SPITType.
|
||||
// May also occur when the server confirms a SPITType created or changed by the client.
|
||||
void onSpitType(SPIT_Client::ObjectEvent event, const SPITType &p_SPITType) {
|
||||
if (event == SPIT_Client::ObjectEvent::Created) {
|
||||
// Whenever you provide an action for this SPITType take this over in your code.
|
||||
// call _SpitClient.setActionSPITType(p_SPITType.getID(), true);
|
||||
ESP_LOGI(TAG, "NEW SPIT-Type ID: %s GroupName: %s Name: %s confirmed: %d", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
} else if (event == SPIT_Client::ObjectEvent::Changed) {
|
||||
ESP_LOGI(TAG, "SPIT-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
} else if (event == SPIT_Client::ObjectEvent::Deleted) {
|
||||
ESP_LOGI(TAG, "SPIT-Type Removed ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server has created or changed a Remote SPITType.
|
||||
* Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer.
|
||||
* @param p_New true = server created a new SPITType / false = server changed a existing SPITType
|
||||
*/
|
||||
void onSpitTypeRemote(SPIT_Client::ObjectEvent event, const SPITType &p_SPITType) {
|
||||
if (event == SPIT_Client::ObjectEvent::Created) {
|
||||
ESP_LOGI(TAG, "NEW SPIT-REMOTE-Type ID: %s GroupName: %s Name: %s confirmed: %d", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
auto typeName = p_SPITType.getName();
|
||||
if (ExpectedObjects.contains(typeName)) {
|
||||
ExpectedObjects[typeName] = p_SPITType.getID();
|
||||
}
|
||||
} else if (event == SPIT_Client::ObjectEvent::Changed) {
|
||||
// we had to inform all Remote SPITObjects using the p_SPITType
|
||||
// perhaps the SPITObject uses information from the SPITType
|
||||
SPITObject *ptrSPITObject;
|
||||
int intSPITObjectCount;
|
||||
intSPITObjectCount = SPITObject::getSPITObjectRemoteCount();
|
||||
for (int intObject = 0; intObject < intSPITObjectCount; intObject++) {
|
||||
ptrSPITObject = SPITObject::getSPITObjectRemote(intObject);
|
||||
if (ptrSPITObject == NULL)
|
||||
continue;
|
||||
if (ptrSPITObject->getSPITTypeID() == p_SPITType.getID()) {
|
||||
// call ecentSPITObjectRemote
|
||||
// onSpitObjectRemote(SPIT_Client::ObjectEvent::Changed, p_SPITType, *ptrSPITObject);
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "SPIT-REMOTE-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data(), p_SPITType.getConfirmed());
|
||||
} else if (event == SPIT_Client::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-REMOTE-Type Removed ID: %s GroupName: %s Name: %s\n", p_SPITType.getID().data(), p_SPITType.getGroupName().data(), p_SPITType.getName().data());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server has created, loaded or changed a SPITObject.
|
||||
* May also occur when the server confirms a SPITObject created by the client, what the client should never do!!.
|
||||
* false = server changed a existing SPITObject
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.
|
||||
*/
|
||||
void onSpitObject(SPIT_Client::ObjectEvent event, const SPITType &p_SPITType, const SPITObject &p_SPITObject) {
|
||||
if (event == SPIT_Client::ObjectEvent::Created) {
|
||||
ESP_LOGI(TAG, "NEW SPIT-Object ID: %s Name: %s -> SPITType: %s", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
// check your actions
|
||||
// Whenever you provide an action for this SPITObject take this over in your code.
|
||||
// call _SpitClient.setActionSPITObject(p_SPITObject.getID(), true);
|
||||
|
||||
// for our little excample as described in loadClientProject:
|
||||
// We have only actions for SPITTypes - means every SPITObject with the associated "Actionx"-SPITTypes will trigger the action when it is played
|
||||
//-> no need to do something here, because setActionSPITType has been set prior and the SPITObject will automatically inherits this
|
||||
// SPITObjects with other SPITTypes asscciated will trigger no actions
|
||||
|
||||
} else if (event == SPIT_Client::ObjectEvent::Changed) {
|
||||
ESP_LOGI(TAG, "SPIT-Object CHANGED ID: %s Name: %s -> SPITType: %s", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
} else if (event == SPIT_Client::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-Object Removed ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data());
|
||||
// Check your actions
|
||||
// take the removal of the SPITObject over in your code
|
||||
|
||||
// CAUTION: Deleted SPITObjects can be added later again (perhaps per UNDO on the SPITServer)
|
||||
//-> don't remove your assigned action immediately - keep it to reassign it later
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Called when the server has created or changed a Remote SPITObject.
|
||||
* A Remote SPITObject is used to remote control the SPITServer.
|
||||
* @param p_New true = server created a new remote SPITObject
|
||||
* false = server changed a existing remote SPITObject
|
||||
* @param p_SPITType a reference to a copy of the associated SPITType instance.
|
||||
* @param p_SPITObject a reference to a copy of the SPITObject instance.
|
||||
*/
|
||||
void onSpitObjectRemote(SPIT_Client::ObjectEvent event, const SPITType &p_SPITType, const SPITObject &p_SPITObject) {
|
||||
if (event == SPIT_Client::ObjectEvent::Created) {
|
||||
ESP_LOGI(TAG, "NEW SPIT-REMOTE-Object ID: %s Name: %s -> SPITType: %s", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
// This is a remote SPITObject which can be used to remote control the server.
|
||||
// If you want you can list this for later use
|
||||
} else if (event == SPIT_Client::ObjectEvent::Changed) {
|
||||
ESP_LOGI(TAG, "SPIT-REMOTE-Object CHANGED ID: %s Name: %s -> SPITType: %s", p_SPITObject.getID().data(), p_SPITObject.getName().data(), p_SPITType.getName().data());
|
||||
} else if (event == SPIT_Client::ObjectEvent::Deleted) {
|
||||
ESP_LOGD(TAG, "SPIT-REMOTE-Object Removed ID: %s Name: %s\n", p_SPITObject.getID().data(), p_SPITObject.getName().data());
|
||||
// This is a remote SPITObject
|
||||
// If you have listet this prior you should remove it from the list
|
||||
}
|
||||
}
|
||||
|
||||
// SPITServer may use several methods for playing SPITObjects.
|
||||
// e.g. liveSHOWsoftware has the timeline and jingles which plays objects, where the timeline the main player is.
|
||||
// SPIT distinguishes between the different players. All eventPlay... functions contain the information which player plays the SPIT object.
|
||||
void onPlay(string p_PlayerID, string p_PlayerName, char p_PlayerType, bool p_PlayerIsRunning, long long p_TimeFrames) {
|
||||
ESP_LOGD(TAG, "eventPlay Player: %s Runs: %d Time: %lld", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames);
|
||||
|
||||
switch (p_PlayerType) {
|
||||
case SPIT_Client::PLAYERTYPE_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 SPIT_Client::PLAYERTYPE_CONTINOUS:
|
||||
// The olayer is playing only single Object sequences sometime during the project
|
||||
break;
|
||||
case SPIT_Client::PLAYERTYPE_DISCRETE:
|
||||
// Only discrete values where submitted, e.g the fader position of remote faders.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the SPITServer plays a SPITObject. For every played SPITObject one eventPlayObject is called.
|
||||
* You can decide here which action should be done or not.
|
||||
*/
|
||||
void onPlaySpitType(string p_PlayerID, string spitTypeId, bool p_PlayerIsRunning, bool p_Started, bool p_Ended, double p_Value) {
|
||||
// double doubleValue = ((double)p_PlayObject.getValue() / 1000000) * ((double)p_PlayObject.getValueFactor() / 1000000);
|
||||
|
||||
ESP_LOGD(TAG, "eventPlayObject Player: %s is running: %d Object Started: %d Stopped: %d", p_PlayerID.data(), p_PlayerIsRunning, p_Started, p_Ended);
|
||||
// ESP_LOGD(TAG, " SPITType: %s SPITObject: %s Position: %lld Value: %f\n", spitTypeId.data(), p_SPITObject.getName().data(), p_PlayObject.getFrameInside(), doubleValue);
|
||||
ESP_LOGD(TAG, " SPITType: %s Value: %f\n", spitTypeId.data(), p_Value);
|
||||
|
||||
if (!ProvidedSpitActions.contains(spitTypeId)) {
|
||||
ESP_LOGE(TAG, "SPIT ID %s is not accepted", spitTypeId.c_str());
|
||||
return;
|
||||
}
|
||||
if (p_Started == true) {
|
||||
auto command = ProvidedSpitActions[spitTypeId];
|
||||
ESP_LOGI(TAG, "Player: %s is running: %s Object", p_PlayerID.data(), spitTypeId.c_str());
|
||||
commandQueue.enqueue(std::make_unique<MoveCommand>(command));
|
||||
Syslog::logv(Syslog::Severity::Informational, "Got SPIT command for move ot : r%d", command.pos);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a remote SpitObject which value function is changed by the server.
|
||||
* This allows the Client to adjust its display for the remote command.
|
||||
* @param p_SPITType the assigned remote SPITType of p_SPITObject
|
||||
* @param p_SPITObject the remote SPITObject which is changed
|
||||
* @param p_FrameInsideObject can be discarded
|
||||
* @param p_Value the new value
|
||||
*/
|
||||
void onPlayRemoteObjectStatus(const SPITType &p_SPITType, const SPITObject &p_SPITObject, long long p_FrameInsideObject, int p_Value) {
|
||||
ESP_EARLY_LOGI(TAG, "eventPlayRemoteObjectStatus RemoteSPITType: %s RemoteSPITObject: %s Position: %lld Value: %d", p_SPITType.getName().data(), p_SPITObject.getName().data(), p_FrameInsideObject, p_Value);
|
||||
}
|
||||
|
||||
void SpitClientApp() {
|
||||
ESP_LOGI(TAG, "Starting SPIT task");
|
||||
auto ptrMyApp = std::make_unique<MyApp>();
|
||||
ESP_LOGI(TAG, "Starting SPIT task");
|
||||
|
||||
auto &provided = SpitTypes.Provided;
|
||||
auto &expected = SpitTypes.Expected;
|
||||
std::vector<LocalSpitObj> ProvidedObj;
|
||||
ProvidedSpitActions[provided.startShuffle] = MoveCommand{.type = MoveType::Shuffle, .pos = 0};
|
||||
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)};
|
||||
ExpectedObjects[expected.inPosX[i]] = "";
|
||||
}
|
||||
|
||||
// load a client project and start auto detection of SPITServers
|
||||
ptrMyApp->init();
|
||||
|
||||
while (true) {
|
||||
fos::Task::delayMs(10000);
|
||||
ESP_LOGI(TAG, "Test LiveShow");
|
||||
ptrMyApp->testLiveShowRemote(); //This is an excample how to remote control the liveSHOWsoftware
|
||||
}
|
||||
SPIT_Client spitClient(ClientName, ProjectName,
|
||||
{
|
||||
.onServerEvent = onServerEvent,
|
||||
.onConnectionStatus = onConnectionStatus,
|
||||
.onProjectUpdate = onProjectUpdate,
|
||||
.onSpitType = onSpitType,
|
||||
.onSpitTypeRemote = onSpitTypeRemote,
|
||||
.onSpitObject = onSpitObject,
|
||||
.onSpitObjectRemote = onSpitObjectRemote,
|
||||
.onPlay = onPlay,
|
||||
.onPlaySpitType = onPlaySpitType,
|
||||
.onPlayRemoteObjectStatus = onPlayRemoteObjectStatus,
|
||||
.onCheckSpitTypeVeto = onCheckSpitTypeVeto,
|
||||
.onCheckSpitObjectVeto = onCheckSpitObjectVeto,
|
||||
});
|
||||
|
||||
for (auto &obj : ProvidedObj) {
|
||||
SPITType *ptrSPITType1Fix = spitClient.createSPITTypeFixed(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();
|
||||
spitClient.startServerAutoDetect();
|
||||
|
||||
spitProjectFinish.take();
|
||||
string serverProjectID = spitClient.getServerProjectID();
|
||||
string serverProjectName = spitClient.getClientProjectName();
|
||||
int serverFramesPerSecond = spitClient.getServerFramesPerSecond(); // set when the server reports his project, see eventProjectReport
|
||||
ESP_LOGI(TAG, "eventProjectReport ID: %s Name: %s FramesPerSecond: %d", serverProjectID.data(), serverProjectName.data(), serverFramesPerSecond);
|
||||
|
||||
for (auto &&obj : ExpectedObjects) {
|
||||
if (obj.second == "") {
|
||||
ESP_LOGE(TAG, "No matching Remote ID for %s", obj.first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
auto res = responseQueue.dequeue();
|
||||
if (res->type == ResponseType::StartMoving) {
|
||||
spitClient.sendRemoteObject(ExpectedObjects[expected.changingPos]);
|
||||
} else if (res->type == ResponseType::StepAt) {
|
||||
spitClient.sendRemoteObject(ExpectedObjects[expected.inPosX[res->pos - 1]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
@@ -641,17 +999,18 @@ void app_main(void) {
|
||||
ESP_ERROR_CHECK(ret);
|
||||
initialize_ethernet();
|
||||
NvsApi::init();
|
||||
static fos::Task lightingTask(LightingTask, "Lights", 0x4000uL);
|
||||
static fos::Task movementTask(MovementTask, "Motor", 0x4000uL);
|
||||
static fos::Task lightingTask(LightingTask, "Lights", 0x8000uL);
|
||||
static fos::Task movementTask(MovementTask, "Motor", 0x8000uL);
|
||||
|
||||
etherActive.take();
|
||||
fos::Task::delayMs(10000);
|
||||
ESP_LOGI(TAG, "Start net services");
|
||||
|
||||
static int ipVersion = AF_INET;
|
||||
static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
|
||||
static fos::TaskT<int> dmxNode(dmxSocketTask, ipVersion, "dmxNode", 4096);
|
||||
// static Task otaUpdate(SystemFunctions::OtaTaskEntry, "otaTask", 8192);
|
||||
static fos::Task spit(SpitClientApp,"SpitClient");
|
||||
static fos::Task spit(SpitClientApp, "SpitClient");
|
||||
|
||||
auto &store = NvsApi::getInstance();
|
||||
auto logger = store.getValue(ConfigKeys.syslogDest);
|
||||
|
||||
Reference in New Issue
Block a user