changing app

This commit is contained in:
2026-10-18 16:26:44 +02:00
parent 348a1a1e14
commit c247b38f7b
14 changed files with 1183 additions and 1646 deletions
+3 -5
View File
@@ -2,17 +2,15 @@
"configurations": [
{
"name": "ESP-IDF",
"compileCommands": "/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build/compile_commands.json",
"compilerPath": "C:\\Espressif\\tools\\xtensa-esp-elf\\esp-14.2.0_20250730\\xtensa-esp-elf\\bin\\xtensa-esp32-elf-gcc.exe",
"compileCommands": "${config:idf.buildPath}/compile_commands.json",
"intelliSenseMode": "gcc-x86",
"includePath": [
"${config:idf.espIdfPath}/components/**",
"${config:idf.espIdfPathWin}/components/**",
"${workspaceFolder}/**",
"${workspaceFolder}/core/**"
],
"browse": {
"path": [
"${config:idf.espIdfPath}/components",
"${config:idf.espIdfPathWin}/components",
"${workspaceFolder}",
"${workspaceFolder}/core"
],
-5
View File
@@ -5,11 +5,6 @@
"type": "gdbtarget",
"request": "attach",
"name": "Eclipse CDT GDB Adapter"
},
{
"type": "espidf",
"name": "Launch",
"request": "launch"
}
]
}
+30 -6
View File
@@ -4,16 +4,19 @@
"idf.customExtraVars": {
"OPENOCD_SCRIPTS": "/home/gustice/tools/.espressif/tools/openocd-esp32/v0.12.0-esp32-20241016/openocd-esp32/share/openocd/scripts/",
"IDF_CCACHE_ENABLE": "1",
"ESP_ROM_ELF_DIR": "/home/gustice/tools/.espressif/tools/esp-rom-elfs/20241011/"
"ESP_ROM_ELF_DIR": "/home/gustice/tools/.espressif/tools/esp-rom-elfs/20241011/",
"IDF_TARGET": "esp32"
},
"idf.openOcdConfigs": [
"board/esp32c6-builtin.cfg"
"interface/ftdi/esp_ftdi.cfg",
"target/esp32.cfg"
// "board/esp32-wrover-kit-3.3v.cfg"
],
"idf.flashType": "UART",
"C_Cpp.autoAddFileAssociations": false,
"project.deviceIp": "172.16.17.56",
"sonarlint.pathToCompileCommands": "${workspaceFolder}\\build\\compile_commands.json",
"idf.port": "/dev/ttyACM0",
"idf.portWin": "COM4",
"cmake.showSystemKits": false,
"cmake.defaultVariants": {
"buildType": {
@@ -33,12 +36,16 @@
}
}
},
"clangd.path": "/home/gustice/.espressif/tools/esp-clang/esp-18.1.2_20240912/esp-clang/bin/clangd",
"clangd.path": "C:\\Espressif\\tools\\esp-clang\\esp-18.1.2_20240912\\esp-clang\\bin\\clangd.exe",
"clangd.arguments": [
"--background-index",
"--query-driver=/home/gustice/.espressif/tools/riscv32-esp-elf/esp-14.2.0_20241119/riscv32-esp-elf/bin/riscv32-esp-elf-gcc",
"--compile-commands-dir=/home/gustice/jobs/projects/Proj_Zwickau_waitingRoom/FW_X_WatchController/build"
"--query-driver=**",
"--compile-commands-dir=c:\\Users\\Jakob\\hello_world\\build"
],
"cmake.configureOnOpen": false,
"cmake.configureOnEdit": false,
"cmake.automaticReconfigure": false,
"cmake.autoSelectActiveFolder": false,
"cmake.debugConfig": {
"setupCommands": [
{
@@ -54,5 +61,22 @@
"text": "skip namespace std"
}
]
},
"cmake.options.advanced": {
"build": {
"statusBarVisibility": "inherit",
"inheritDefault": "hidden"
},
"launch": {
"statusBarVisibility": "inherit",
"inheritDefault": "hidden"
},
"debug": {
"statusBarVisibility": "inherit",
"inheritDefault": "hidden"
}
},
"idf.currentSetup": "C:\\esp\\v5.4.3\\esp-idf",
"idf.port": "COM4"
}
+1
View File
@@ -15,6 +15,7 @@ else()
else()
set(EXTRA_COMPONENT_DIRS
"core/components"
"core/components_extern"
"core/managed_components"
)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+1 -1
View File
@@ -159,7 +159,7 @@ int SProcessor::sendOvertakingMessage(int msgNumRec) {
if (msgNum == msgNumNext) {
msgNumRec = msgNum;
mInternCallbacks.parseMessage(*overtakingMessage);
parseMessage(*overtakingMessage);
mOvertakingMessages.erase(it);
it = mOvertakingMessages.begin();
} else {
+1 -1
Submodule core updated: 37e288c012...e584259b31
+3 -3
View File
@@ -12,10 +12,10 @@ dependencies:
idf:
source:
type: idf
version: 5.4.1
version: 5.4.3
direct_dependencies:
- frozen-eye/esp_telnet
- idf
manifest_hash: 8e2a908d16408b9cafcd4c4b109b841acfca6e660d2500fc6d1362f0f143376c
target: esp32c6
manifest_hash: f3dbb2beffe19f6e4fa3818b79ea2bfac679eaaf47effee78f152007a2be54f5
target: esp32
version: 2.0.0
+1 -1
View File
@@ -1,2 +1,2 @@
idf_component_register(SRCS "watchMain.cpp"
idf_component_register(SRCS "lightsMain.cpp"
INCLUDE_DIRS ".")
+4 -22
View File
@@ -13,36 +13,18 @@ struct {
// MQTT Topics
struct {
// Subscriptions:
const char *moveTo = /* <mqttPrefix>/ */ "watch/moveTo";
const char *startShuffle = /* <mqttPrefix>/ */ "watch/startShuffle";
const char *startShow = /* <mqttPrefix>/ */ "elixirLights/startShow";
// Publishes:
const char *inPosition = /* <mqttPrefix>/ */ "watch/inPosition";
const char *changingPosition = /* <mqttPrefix>/ */ "watch/changingPosition";
const char *showDone = /* <mqttPrefix>/ */ "elixirLights/showDone";
} MqttTopics;
struct {
const char *expectedServer = "";
struct {
const char *group = "CatasWatchMovement";
const char *startShuffle = "ActionStartShuffle";
const char *moveToX[6] = {
"ActionMoveTo1",
"ActionMoveTo2",
"ActionMoveTo3",
"ActionMoveTo4",
"ActionMoveTo5",
"ActionMoveTo6",
};
const char *startShow = "StartShow";
} Provided;
struct {
const char *changingPos = "ChangingPositionScene";
const char *inPosX[6] = {
"InPosition1Scene",
"InPosition2Scene",
"InPosition3Scene",
"InPosition4Scene",
"InPosition5Scene",
"InPosition6Scene",
};
const char *showDone = "ShowDone";
} Expected;
} SpitTypes;
+2 -4
View File
@@ -17,15 +17,12 @@
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_private/wifi.h"
#include "ethernet_init.h"
#include "ethernet.hpp"
#include "esp_netif.h"
#include "esp_eth.h"
// Component header
#include "Task.hpp"
#include "pwmExpanderPca9685.hpp"
#include "stepperDrv.hpp"
#include "stepperMotor.hpp"
#include "cliWrapper.hpp"
#include "udpSockets.hpp"
#include "tcpSockets.hpp"
@@ -49,3 +46,4 @@
#include <chrono>
#include <string>
#include <map>
#include <vector>
+651
View File
@@ -0,0 +1,651 @@
/**
* @author Gustice
* @brief ChaosWatch Application
*/
// using Elite2D-EXMU
// Gledopto Series With Ethernet
// { // 13
// 1, // eth_address,
// 5, // eth_power,
// 23, // eth_mdc,
// 33, // eth_mdio,
// ETH_PHY_LAN8720, // eth_type,
// ETH_CLOCK_GPIO0_IN // eth_clk_mode as input
// },
#include "config.hpp"
#include "lighsMain.hpp"
using namespace spit;
using namespace std;
string ClientName = "LeoLightsDev";
string ProjectName = "LeoLightsProj";
extern "C" { // This switch allows the ROS C-implementation to find this main
void app_main(void);
}
struct DeviceState {
Color color{0x80, 0x80, 0x80};
vector<uint8_t> counts;
vector<uint8_t> times;
};
struct StartCommand {
uint8_t pos; // 0 for none / Valid indexes 1 .. 6
};
static fos::Queue<StartCommand> commandQ(2);
DeviceState State;
static const char* TAG = "Light";
unique_ptr<Cli> pShell;
void onCommand(string name, Cli::CArgs args) {
ESP_LOGI(TAG, "Invoking: %s", name.c_str());
}
void startUpdate(Cli::CArgs args) {
ESP_LOGI(TAG, "Invoking Update");
if (args.size() != 1) {
pShell->writeLine("Need URL to application");
return;
}
// @ToDo: Start Update here
}
void getConfig(Cli::CArgs args) {
if (args.size() != 1) {
pShell->writeLine("Needs string key for query");
return;
}
auto key = args[0];
auto& store = NvsApi::getInstance();
auto val = store.getValue(key);
pShell->writeLine(key + ": " + val + "");
}
void setConfig(Cli::CArgs args) {
if (args.size() != 2) {
pShell->writeLine("Needs string key and value");
return;
}
auto key = args[0];
auto val = args[1];
auto& store = NvsApi::getInstance();
pShell->writeLine(string{"Storing value = '"} + val + "'");
store.setValue(key, val);
}
void setLogServerConfig(Cli::CArgs args) {
ESP_LOGI(TAG, "on showLogServerConfig:");
auto& store = NvsApi::getInstance();
if (args.size() != 1) {
auto logger = store.getValue("syslogDst");
pShell->writeLine(string{"syslog destination = '"} + logger + "'");
pShell->writeLine("provide argument to change syslog server");
return;
}
pShell->writeLine(string{"setting syslog destination to = '"} + args[0] + "'");
store.setValue("syslogDst", args[0]);
}
void testLights(Cli::CArgs args) {
ESP_LOGI(TAG, "on testLights:");
commandQ.enqueue(make_unique<StartCommand>());
}
void showProcessValues(Cli::CArgs args) {
pShell->writeLine("Process values:");
char buff[256];
sprintf(buff, "%02x,%02x,%02x", State.color.getRed(), State.color.getGreen(), State.color.getBlue());
std::stringstream ssC;
for (auto& c : State.counts) {
ssC << string{c} << ",";
}
std::stringstream ssT;
for (auto& t : State.times) {
ssT << string{t} << ",";
}
pShell->writeLine(string{" Color RGB: "} + buff);
pShell->writeLine(string{" LED-Counts: "} + ssC.str());
pShell->writeLine(string{" Switch-Times: "} + ssT.str());
}
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 = 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 exception& e) {
ESP_LOGI(TAG, "Failed to parse %s", args[0].c_str());
}
}
/**
* @brief Telnet socket via TCP/IP
*
* @details The ini-file for TeraTerm only changes CRReceive and CRSend values both to "=CR"
* @param arg ignored task argument
*/
static void telnetSocketTask(int addrFamily) {
ESP_LOGI(TAG, "Starting Telnet task");
try {
TelnetServer telnet(addrFamily);
telnet.run(
[](TcpSession& session) {
pShell = make_unique<Cli>(session, [](string n, Cli::CArgs a) { onCommand(n, a); });
pShell->addBinding(
{"update", "Start OTA-Update-Process",
[](Cli::CArgs a) { startUpdate(a); }});
pShell->addBinding(
{"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",
[](Cli::CArgs a) { getConfig(a); }});
pShell->addBinding(
{"setcfg", "Set configuration value by key and value",
[](Cli::CArgs a) { setConfig(a); }});
pShell->addBinding(
{"setDyn", "set dynamics of movement (velocity,accelerations) as floats",
[](Cli::CArgs a) { testLights(a); }});
pShell->addBinding(
{"showData", "Show process values that are input by DMX, MQTT and SPIT",
[](Cli::CArgs a) { showProcessValues(a); }});
},
[](TcpSession& session) {
pShell->process();
Syslog::setupTask(session.getOther());
});
} catch (const exception& e) {
ESP_LOGE("TCP", "%s", e.what());
}
vTaskDelete(NULL);
}
void startShow(string data) {
ESP_LOGI(TAG, "StartShuffle command %s", data.c_str());
try {
Syslog::logv(Syslog::Severity::Informational, "got Shuffle-Command");
commandQ.enqueue(make_unique<StartCommand>());
} catch (const exception& e) {
ESP_LOGE(TAG, "Error to process data %s, with ex: %s", data.c_str(), e.what());
}
}
/**
* @brief DMX-Socket for ArtNet TCP/IP
*
* @details Tested with [Q Light Controller+](https://www.qlcplus.org/)
* @param args ignored task argument
*/
static void dmxSocketSenderTask(UdpSocket& socket) {
try {
ArtnetSender artnet(socket);
array<uint8_t, 16> data;
while (socket.isActive()) {
data[0]++;
artnet.send("", 0, data.data(), data.size());
fos::Task::delayMs(500);
}
} catch (const exception& e) {
ESP_LOGE("UDP", "%s", e.what());
}
}
fos::Semaphore etherActive;
fos::Semaphore spitProjectFinish;
/** Event handler for IP_EVENT_ETH_GOT_IP */
void got_ip_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*)event_data;
const esp_netif_ip_info_t* ip_info = &event->ip_info;
ESP_LOGI(TAG, "Ethernet Got IP Address");
ESP_LOGI(TAG, "~~~~~~~~~~~");
ESP_LOGI(TAG, "ETHIP:" IPSTR, IP2STR(&ip_info->ip));
ESP_LOGI(TAG, "ETHMASK:" IPSTR, IP2STR(&ip_info->netmask));
ESP_LOGI(TAG, "ETHGW:" IPSTR, IP2STR(&ip_info->gw));
ESP_LOGI(TAG, "~~~~~~~~~~~");
etherActive.give();
}
static void initialize_ethernet(void) {
uint8_t eth_port_cnt = 0;
esp_eth_handle_t* eth_handles;
ESP_ERROR_CHECK(eth_init(&eth_handles, &eth_port_cnt));
if (eth_port_cnt > 1) {
ESP_LOGW(TAG, "multiple Ethernet devices detected, the first initialized is to be used!");
}
static esp_eth_handle_t s_eth_handle = NULL;
s_eth_handle = eth_handles[0];
free(eth_handles);
// Initialize TCP/IP network interface aka the esp-netif (should be called only once in application)
ESP_ERROR_CHECK(esp_netif_init());
// Create default event loop that running in background
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and you don't need to modify
// default esp-netif configuration parameters.
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t* eth_netif = esp_netif_new(&cfg);
// Attach Ethernet driver to TCP/IP stack
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(s_eth_handle)));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, eth_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
ESP_ERROR_CHECK(esp_eth_start(s_eth_handle));
}
namespace Effect {
extern const WaveForm_t OffsetPulseWave{gau8_offsetPulse, cu16_TemplateLength};
extern const WaveForm_t InitSlopeWave{gau8_initSlope, cu16_TemplateLength};
extern const WaveForm_t OffsetSlopeWave{gau8_offsetSlope, cu16_TemplateLength};
extern const WaveForm_t FullSlopeWave{gau8_fullSlope, cu16_TemplateLength};
extern const WaveForm_t FullPulseWave{gau8_fullPulse, cu16_TemplateLength};
const Macro macDemoStart = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateIdle, 0xFF},
};
const Macro macDemoPulse = {
{64, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 2, StateMachine::UpdateIdle, 0xFF},
{64, 1, &OffsetPulseWave, StateMachine::UpdateWave, 0xFF},
};
const Macro macDemoFlicker = {
{16, 1, &InitSlopeWave, StateMachine::UpdateWave, 0xFF},
{32, 1, StateMachine::UpdateFlicker, 0xFF},
};
} // namespace Effect
void LightingTask() {
ESP_LOGI(TAG, "Start Lighting");
auto const& colorSource = State.color;
array<Effect::EffectProcessor, 2> processors{
Effect::EffectProcessor(8),
Effect::EffectProcessor(8)};
processors[0].setEffect(Effect::macDark, &colorSource, 0);
processors[1].setEffect(Effect::macDark, &colorSource, 0);
const array<Effect::Macro, 2> PictoEffects{
Effect::macDemoPulse,
Effect::macDemoPulse};
while (true) {
// ESP_LOGI(TAG, "Current color set r%i g%i b%i ",
// State.color.getRed(), State.color.getGreen(), State.color.getBlue());
// processors[0].setEffect(Effect::macDark, &colorSource, 0);
// auto idx = 0;
// Syslog::logv(Syslog::Severity::Informational, "Running show");
// processors[idx].setEffect(PictoEffects[idx], &colorSource, 0);
// for (size_t i = 0; i < processors.size(); i++) {
// auto col = processors[i].tick();
// }
// fos::Task::delayMs(40);
static int cnt{};
fos::Task::delayMs(1000);
printf("running %d\n", cnt++);
}
}
struct LocalSpitObj {
string iD;
string groupName;
string name;
};
map<string, StartCommand> ProvidedSpitActions;
map<string, string> ExpectedObjects;
void onServerEvent(SClient::ServerEvent event, const SadDetectedServer& p_DetectedServer) {
switch (event) {
case SClient::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 SClient::ServerEvent::Lost:
ESP_LOGW(TAG, "Server lost Name: %s IP: %s", p_DetectedServer.getName().data(), p_DetectedServer.getIP().data());
break;
case SClient::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,
SClient::Connection p_ConnectionStatus, SClient::Connection p_OldConnectionStatus) {
ESP_LOGI(TAG, "MySPITApp: eventConnectionStatus %d->%d ", (int)p_OldConnectionStatus, (int)p_ConnectionStatus);
}
// The transfer of the server's SPITTypes and SPITObjects is finished.
void onProjectUpdate(SClient::ProjUpdate state, string projectId) {
switch (state) {
case SClient::ProjUpdate::ServerLoaded:
ESP_LOGI(TAG, "eventProjectReport ID: %s ", projectId.data());
break;
case SClient::ProjUpdate::StartTransfer:
ESP_LOGI(TAG, "eventStartProjectTransfer");
break;
case SClient::ProjUpdate::EndTransfer:
ESP_LOGI(TAG, "eventEndProjectTransfer");
spitProjectFinish.give();
break;
case SClient::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;
}
}
bool onCheckSpitTypeVeto(bool knownType, bool createdByClient) {
return true; // Bypass veto
if (!knownType || !createdByClient) { // Don't allow foreign SPITTypes
return false;
}
return true;
}
bool onCheckSpitObjectVeto(bool knownType) {
return true; // Bypass veto
if (!knownType) { // Don't allow objects of unregistered SPITTypes
return false;
}
return true;
}
// Called when the server has created, loaded, changed or deleted a (Remote) SPITType.
// Remote SPITType are used in Remote SPITObjects. A Remote SPITObject is used to remote control the SPITServer.
// May also occur when the server confirms a SPITType created or changed by the client.
void onSpitType(SClient::ObjectEvent event, bool isRemote, const SType& sType) {
if (isRemote) {
if (event == SClient::ObjectEvent::Created) {
ESP_LOGI(TAG, "NEW SPIT-REMOTE-Type ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
auto typeName = sType.Name.get();
if (ExpectedObjects.contains(typeName)) {
ExpectedObjects[typeName] = sType.getID();
}
} else if (event == SClient::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 == nullptr)
// continue;
// if (ptrSPITObject->getSPITTypeID() == p_SPITType.getID()) {
// // call ecentSPITObjectRemote
// // onSpitObjectRemote(SClient::ObjectEvent::Changed, p_SPITType, *ptrSPITObject);
// }
// }
// ESP_LOGI(TAG, "SPIT-REMOTE-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
} else if (event == SClient::ObjectEvent::Deleted) {
ESP_LOGD(TAG, "SPIT-REMOTE-Type Removed ID: %s GroupName: %s Name: %s\n", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data());
}
} else {
if (event == SClient::ObjectEvent::Created) {
// Whenever you provide an action for this SPITType take this over in your code.
// call _SpitClient.setActionSPITType(sType.getID(), true);
// ESP_LOGI(TAG, "NEW SPIT-Type ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
} else if (event == SClient::ObjectEvent::Changed) {
// ESP_LOGI(TAG, "SPIT-Type CHANGED ID: %s GroupName: %s Name: %s confirmed: %d", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data(), sType.getConfirmed());
} else if (event == SClient::ObjectEvent::Deleted) {
// ESP_LOGI(TAG, "SPIT-Type Removed ID: %s GroupName: %s Name: %s\n", sType.getID().data(), sType.GroupName.get().data(), sType.Name.get().data());
}
}
}
// Called when the server has created, loaded or changed a SPITObject.
// A Remote SPITObject is used to remote control the SPITServer.
// 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(SClient::ObjectEvent event, bool isRemote, const SType& sType, const SObject& sObject) {
if (isRemote) {
if (event == SClient::ObjectEvent::Created) {
// ESP_LOGI(TAG, "NEW SPIT-REMOTE-Object ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().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 == SClient::ObjectEvent::Changed) {
// ESP_LOGI(TAG, "SPIT-REMOTE-Object CHANGED ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
} else if (event == SClient::ObjectEvent::Deleted) {
ESP_LOGD(TAG, "SPIT-REMOTE-Object Removed ID: %s Name: %s\n", sObject.getID().data(), sObject.Name.get().data());
// This is a remote SPITObject
// If you have listet this prior you should remove it from the list
}
} else {
if (event == SClient::ObjectEvent::Created) {
// ESP_LOGI(TAG, "NEW SPIT-Object ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
// check your actions
// Whenever you provide an action for this SPITObject take this over in your code.
// call _SpitClient.setActionSPITObject(sObject.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 == SClient::ObjectEvent::Changed) {
// ESP_LOGI(TAG, "SPIT-Object CHANGED ID: %s Name: %s -> SPITType: %s", sObject.getID().data(), sObject.Name.get().data(), sType.Name.get().data());
} else if (event == SClient::ObjectEvent::Deleted) {
ESP_LOGD(TAG, "SPIT-Object Removed ID: %s Name: %s\n", sObject.getID().data(), sObject.Name.get().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
}
}
}
// 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, uint64_t p_TimeFrames) {
ESP_LOGD(TAG, "eventPlay Player: %s Runs: %d Time: %lld", p_PlayerName.data(), p_PlayerIsRunning, p_TimeFrames);
switch (p_PlayerType) {
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::PTYPE_CONTINOUS:
// The olayer is playing only single Object sequences sometime during the project
break;
case SClient::PlayerType::PTYPE_DISCRETE:
// Only discrete values where submitted, e.g the fader position of remote faders.
break;
}
}
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());
commandQ.enqueue(make_unique<StartCommand>());
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 SType& sType, const SObject& sObject, uint64_t frameInsideObject, int value) {
ESP_EARLY_LOGD(TAG, "eventPlayRemoteObjectStatus RemoteSPITType: %s RemoteSPITObject: %s Position: %lld Value: %d", sType.Name.get().data(), sObject.Name.get().data(), frameInsideObject, value);
}
// void SpitClientApp() {
// ESP_LOGI(TAG, "Starting SPIT task");
// auto& provided = SpitTypes.Provided;
// auto& expected = SpitTypes.Expected;
// 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++) {
// ProvidedSpitActions[provided.moveToX[i]] = MoveCommand{.type = MoveType::StepTo, .pos = (uint8_t)(i + 1)};
// ProvidedObj.push_back(LocalSpitObj{.iD = provided.moveToX[i], .groupName = provided.group, .name = provided.moveToX[i]});
// ExpectedObjects[expected.inPosX[i]] = "";
// }
// auto ip = spit::Socket::getAdaptersInfo();
// spit::Socket socket(ip);
// SClient spitClient(ClientName, ProjectName, socket,
// {
// .onServerEvent = onServerEvent,
// .onConnectionStatus = onConnectionStatus,
// .onProjectUpdate = onProjectUpdate,
// .onSpitType = onSpitType,
// .onSpitObject = onSpitObject,
// .onPlay = onPlay,
// .onPlaySpitType = onPlaySpitType,
// .onPlayRemoteObjectStatus = onPlayRemoteObjectStatus,
// .onCheckSpitTypeVeto = onCheckSpitTypeVeto,
// .onCheckSpitObjectVeto = onCheckSpitObjectVeto,
// });
// for (auto& obj : ProvidedObj) {
// SType* ptrSPITType1Fix = spitClient.createTypeFixed(obj.iD, obj.groupName, obj.name, 0, 0);
// spitClient.setActionType(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 MqttThread() {
// ESP_LOGI(TAG, "Starting MQTT task");
// auto& store = NvsApi::getInstance();
// auto broker = store.getValue(ConfigKeys.mqttBroker);
// if (broker != "") {
// ESP_LOGI(TAG, "Initializing MQTT");
// auto prefix = store.getValue(ConfigKeys.mqttPrefix);
// auto& client = MqttClient::init(broker, prefix);
// if (!client.isRunning()) {
// client.addSubscription(MqttTopics.moveTo, [](string d) { startShuffle(d); });
// client.start();
// }
// while (true) {
// auto res = responseQueue.dequeue();
// if (res->type == ResponseType::StartMoving) {
// client.publish(MqttTopics.showDone, "");
// } else if (res->type == ResponseType::StepAt) {
// client.publish(MqttTopics.inPosition, to_string(res->pos));
// }
// }
// }
// }
void app_main(void) {
initialize_ethernet();
NvsApi::init();
static fos::Task lightingTask(LightingTask, "Lights", 0x8000uL);
etherActive.take();
ESP_LOGI(TAG, "Start net services");
// static int ipVersion = AF_INET;
// static fos::TaskT<int> telnetSocket(telnetSocketTask, ipVersion, "tcpServer", 4096);
// static fos::Task spit(SpitClientApp, "SpitClient");
// // static fos::Task mqtt(MqttThread, "MqttEndpoint");
// // static Task otaUpdate(SystemFunctions::OtaTaskEntry, "otaTask", 8192);
auto& store = NvsApi::getInstance();
auto logger = store.getValue(ConfigKeys.syslogDest);
if (logger != "") {
Syslog::setupTask(IpAdr{logger, 0});
}
ESP_LOGI(TAG, "Configuration");
ESP_LOGI(TAG, "%s: %s", ConfigKeys.syslogDest, store.getValue(ConfigKeys.syslogDest).c_str());
ESP_LOGI(TAG, "%s: %s", ConfigKeys.mqttBroker, store.getValue(ConfigKeys.mqttBroker).c_str());
ESP_LOGI(TAG, "%s: %s", ConfigKeys.mqttPrefix, store.getValue(ConfigKeys.mqttPrefix).c_str());
ESP_LOGI(TAG, "%s: %s", ConfigKeys.spitServer, store.getValue(ConfigKeys.spitServer).c_str());
while (true) {
fos::Task::delayMs(5000);
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());
}
}
-1027
View File
File diff suppressed because it is too large Load Diff
+477 -540
View File
File diff suppressed because it is too large Load Diff
+8 -30
View File
@@ -2,32 +2,6 @@
# Compiler options
#
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_LWIP_LOCAL_HOSTNAME="ChaosWatch"
#
# Ethernet Configuration
#
CONFIG_USE_SPI_ETHERNET=y
CONFIG_SPI_ETHERNETS_NUM=1
# CONFIG_USE_DM9051 is not set
# CONFIG_USE_KSZ8851SNL is not set
CONFIG_USE_W5500=y
CONFIG_ETH_SPI_HOST=1
CONFIG_ETH_SPI_SCLK_GPIO=6
CONFIG_ETH_SPI_MOSI_GPIO=7
CONFIG_ETH_SPI_MISO_GPIO=2
CONFIG_ETH_SPI_CLOCK_MHZ=16
CONFIG_ETH_SPI_CS0_GPIO=3
CONFIG_ETH_SPI_INT0_GPIO=4
CONFIG_ETH_SPI_POLLING0_MS=0
CONFIG_ETH_SPI_PHY_RST0_GPIO=-1
CONFIG_ETH_SPI_PHY_ADDR0=1
# end of Ethernet Configuration
#
# Ethernet
#
CONFIG_ETH_SPI_ETHERNET_W5500=y
#
# Wi-Fi
@@ -37,11 +11,15 @@ CONFIG_ETH_SPI_ETHERNET_W5500=y
#
# LWIP
#
CONFIG_LWIP_LOCAL_HOSTNAME="ChaosWatch"
CONFIG_LWIP_LOCAL_HOSTNAME="LeoLights"
#
# Serial flasher config
# Ethernet
#
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
CONFIG_USE_INTERNAL_ETHERNET=y
CONFIG_ETH_PHY_LAN87XX=y
CONFIG_ETH_MDC_GPIO=23
CONFIG_ETH_MDIO_GPIO=33
CONFIG_ETH_PHY_RST_GPIO=5
CONFIG_ETH_PHY_ADDR=1