♻️ Major clean up of project structure

This commit is contained in:
Rune Harlyk
2025-09-11 17:14:31 +02:00
committed by Rune Harlyk
parent 26c36b8302
commit 7fd35f3f48
25 changed files with 370 additions and 890 deletions
+4 -4
View File
@@ -14,9 +14,9 @@ typedef std::function<void(const String &originId, bool sync)> SubscribeCallback
class EventSocket {
public:
EventSocket();
EventSocket(PsychicHttpServer &server, const char *route = "/api/ws");
PsychicWebSocketHandler *getHandler() { return &_socket; }
void begin();
bool hasSubscribers(const char *event);
@@ -28,6 +28,8 @@ class EventSocket {
private:
PsychicWebSocketHandler _socket;
PsychicHttpServer &_server;
const char *_route;
std::map<String, std::list<int>> client_subscriptions;
std::map<String, std::list<EventCallback>> event_callbacks;
@@ -41,6 +43,4 @@ class EventSocket {
esp_err_t onFrame(PsychicWebSocketRequest *request, httpd_ws_frame *frame);
};
extern EventSocket socket;
#endif
+1 -1
View File
@@ -4,7 +4,7 @@
#include <LittleFS.h>
#define ESPFS LittleFS
#define ESP_FS LittleFS
#define AP_SETTINGS_FILE "/config/apSettings.json"
#define CAMERA_SETTINGS_FILE "/config/cameraSettings.json"
-24
View File
@@ -1,24 +0,0 @@
#pragma once
#include <Arduino.h>
#include <WiFi.h>
#include <ArduinoJson.h>
#include <event_socket.h>
#include <PsychicHttp.h>
#include <HTTPClient.h>
#include <HTTPUpdate.h>
#include <task_manager.h>
#define EVENT_DOWNLOAD_OTA "otastatus"
#define OTA_TASK_STACK_SIZE 9216
class DownloadFirmwareService {
public:
DownloadFirmwareService();
esp_err_t handleDownloadUpdate(PsychicRequest *request, JsonVariant &json);
private:
};
-32
View File
@@ -1,32 +0,0 @@
#ifndef FirmwareUploadService_h
#define FirmwareUploadService_h
#include <Arduino.h>
#include <Update.h>
#include <WiFi.h>
#include <PsychicHttp.h>
#include <system_service.h>
#include <event_socket.h>
enum FileType { ft_none = 0, ft_firmware = 1, ft_md5 = 2 };
class FirmwareUploadService {
public:
FirmwareUploadService();
void begin();
PsychicUploadHandler *getHandler() { return &uploadHandler; }
private:
PsychicUploadHandler uploadHandler;
esp_err_t handleUpload(PsychicRequest *request, const String &filename, uint64_t index, uint8_t *data, size_t len,
bool final);
esp_err_t uploadComplete(PsychicRequest *request);
esp_err_t handleError(PsychicRequest *request, int code);
esp_err_t handleEarlyDisconnect();
};
#endif // end FirmwareUploadService_h
+14 -32
View File
@@ -13,33 +13,13 @@
#include <motion_states/rest_state.h>
#include <message_types.h>
#define DEFAULT_STATE false
#define ANGLES_EVENT "angles"
#define INPUT_EVENT "input"
#define MODE_EVENT "mode"
#define WALK_GAIT_EVENT "walk_gait"
enum class MOTION_STATE { DEACTIVATED, IDLE, CALIBRATION, REST, STAND, WALK };
class MotionService {
public:
MotionService(ServoController *servoController, Peripherals *peripherals)
: _servoController(servoController), _peripherals(peripherals) {}
MotionService() {}
void begin() {
socket.onEvent(INPUT_EVENT, [&](JsonVariant &root, int originId) { handleInput(root, originId); });
socket.onEvent(MODE_EVENT, [&](JsonVariant &root, int originId) { handleMode(root, originId); });
socket.onEvent(WALK_GAIT_EVENT, [&](JsonVariant &root, int originId) { handleWalkGait(root, originId); });
socket.onEvent(ANGLES_EVENT, [&](JsonVariant &root, int originId) { anglesEvent(root, originId); });
socket.onSubscribe(ANGLES_EVENT,
std::bind(&MotionService::syncAngles, this, std::placeholders::_1, std::placeholders::_2));
body_state.updateFeet(KinConfig::default_feet_positions);
}
void begin() { body_state.updateFeet(KinConfig::default_feet_positions); }
void anglesEvent(JsonVariant &root, int originId) {
JsonArray array = root.as<JsonArray>();
@@ -50,12 +30,14 @@ class MotionService {
}
void setState(MotionState *newState) {
_servoController->activate();
if (state) {
state->end();
}
state = newState;
if (state) state->begin();
if (state) {
_servoController->activate();
state->begin();
}
}
void handleInput(JsonVariant &root, int originId) {
@@ -89,7 +71,7 @@ class MotionService {
JsonDocument doc;
doc.set(static_cast<int>(mode));
JsonVariant data = doc.as<JsonVariant>();
socket.emit(MODE_EVENT, data, String(originId).c_str());
// socket.emit(MODE_EVENT, data, String(originId).c_str());
}
void emitAngles(const String &originId = "", bool sync = false) {
@@ -97,7 +79,7 @@ class MotionService {
auto arr = doc.to<JsonArray>();
for (int i = 0; i < 12; i++) arr.add(angles[i]);
JsonVariant data = doc.as<JsonVariant>();
socket.emit(ANGLES_EVENT, data, originId.c_str());
// socket.emit(ANGLES_EVENT, data, originId.c_str());
}
void syncAngles(const String &originId = "", bool sync = false) {
@@ -105,8 +87,7 @@ class MotionService {
_servoController->setAngles(angles);
}
void handleGestures() {
const gesture_t ges = _peripherals->takeGesture();
void handleGestures(const gesture_t ges) {
if (ges != gesture_t::eGestureNone) {
ESP_LOGI("Motion", "Gesture: %d", ges);
switch (ges) {
@@ -120,13 +101,13 @@ class MotionService {
}
}
bool updateMotion() {
handleGestures();
bool update(Peripherals *peripherals) {
handleGestures(peripherals->takeGesture());
if (!state) return false;
unsigned long now = millis();
float dt = (now - lastUpdate) / 1000.0f;
lastUpdate = now;
state->updateImuOffsets(_peripherals->angleY(), _peripherals->angleX());
state->updateImuOffsets(peripherals->angleY(), peripherals->angleX());
state->step(body_state, dt);
kinematics.calculate_inverse_kinematics(body_state, new_angles);
@@ -147,9 +128,10 @@ class MotionService {
float *getAngles() { return angles; }
inline bool isActive() { return state != nullptr; }
private:
ServoController *_servoController;
Peripherals *_peripherals;
Kinematics kinematics;
CommandMsg command = {0, 0, 0, 0, 0, 0, 0};
+1 -1
View File
@@ -161,7 +161,7 @@ class GestureSensor {
gesture_t getGesture() { return msg.gesture; }
gesture_t takeGesture() {
gesture_t const takeGesture() {
const auto g = msg.gesture;
msg.gesture = eGestureNone;
return g;
+19 -12
View File
@@ -49,15 +49,15 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
_eventEndpoint.begin();
_persistence.readFromFS();
socket.onEvent(EVENT_I2C_SCAN, [&](JsonVariant &root, int originId) {
scanI2C();
emitI2C();
});
// socket.onEvent(EVENT_I2C_SCAN, [&](JsonVariant &root, int originId) {
// scanI2C();
// emitI2C();
// });
socket.onSubscribe(EVENT_I2C_SCAN, [&](const String &originId, bool sync) {
scanI2C();
emitI2C(originId, sync);
});
// socket.onSubscribe(EVENT_I2C_SCAN, [&](const String &originId, bool sync) {
// scanI2C();
// emitI2C(originId, sync);
// });
updatePins();
@@ -79,6 +79,13 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
#endif
};
void update() {
readIMU();
readMag();
// _peripherals.readBMP();
EXECUTE_EVERY_N_MS(100, { readGesture(); });
}
void loop() {
EXECUTE_EVERY_N_MS(_updateInterval, {
beginTransaction();
@@ -112,7 +119,7 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
}
ESP_LOGI("Peripherals", "Emitting I2C scan results, %s %d", originId.c_str(), sync);
JsonVariant data = doc.as<JsonVariant>();
socket.emit(EVENT_I2C_SCAN, data, originId.c_str(), sync);
// socket.emit(EVENT_I2C_SCAN, data, originId.c_str(), sync);
}
void scanI2C(uint8_t lower = 1, uint8_t higher = 127) {
@@ -197,7 +204,7 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
// float angleZ() { return _imu.getAngleZ(); }
gesture_t takeGesture() {
gesture_t const takeGesture() {
return
#if FT_ENABLED(USE_PAJ7620U2)
_gesture.takeGesture();
@@ -225,7 +232,7 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
#endif
#if FT_ENABLED(USE_MPU6050 || USE_BNO055) || FT_ENABLED(USE_HMC5883)
JsonVariant data = doc.as<JsonVariant>();
socket.emit(EVENT_IMU, data);
// socket.emit(EVENT_IMU, data);
#endif
}
@@ -235,7 +242,7 @@ class Peripherals : public StatefulService<PeripheralsConfiguration> {
JsonArray root = doc.to<JsonArray>();
root[0] = _left_distance, root[1] = _right_distance;
JsonVariant data = doc.as<JsonVariant>();
socket.emit("sonar", data);
// socket.emit("sonar", data);
#endif
}
+8 -8
View File
@@ -32,16 +32,16 @@ class ServoController : public StatefulService<ServoSettings> {
_persistence(ServoSettings::read, ServoSettings::update, this, SERVO_SETTINGS_FILE) {}
void begin() {
socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS,
[&](JsonVariant &root, int originId) { servoEvent(root, originId); });
socket.onEvent(EVENT_SERVO_STATE, [&](JsonVariant &root, int originId) { stateUpdate(root, originId); });
// socket.onEvent(EVENT_SERVO_CONFIGURATION_SETTINGS,
// [&](JsonVariant &root, int originId) { servoEvent(root, originId); });
// socket.onEvent(EVENT_SERVO_STATE, [&](JsonVariant &root, int originId) { stateUpdate(root, originId); });
_persistence.readFromFS();
initializePCA();
socket.onEvent(EVENT_SERVO_STATE, [&](JsonVariant &root, int originId) {
is_active = root["active"] | false;
is_active ? activate() : deactivate();
});
// socket.onEvent(EVENT_SERVO_STATE, [&](JsonVariant &root, int originId) {
// is_active = root["active"] | false;
// is_active ? activate() : deactivate();
// });
}
void pcaWrite(int index, int value) {
@@ -110,7 +110,7 @@ class ServoController : public StatefulService<ServoSettings> {
_pca.setMultiplePWM(pwms, 12);
}
void updateServoState() {
void update() {
if (control_state == SERVO_CONTROL_STATE::ANGLE) calculatePWM();
}
-114
View File
@@ -1,114 +0,0 @@
#ifndef Spot_h
#define Spot_h
#include <Arduino.h>
#include <PsychicHttp.h>
#include <ESPmDNS.h>
#include <WiFi.h>
#include <Wire.h>
#include <filesystem.h>
#include <firmware_download_service.h>
#include <firmware_upload_service.h>
#include <peripherals/peripherals.h>
#include <peripherals/servo_controller.h>
#include <peripherals/led_service.h>
#include <peripherals/camera_service.h>
#include <event_socket.h>
#include <features.h>
#include <motion.h>
#include <task_manager.h>
#include <wifi_service.h>
#include <ap_service.h>
#include <mdns_service.h>
#ifdef EMBED_WWW
#include <WWWData.h>
#endif
#ifndef APP_VERSION
#define APP_VERSION "v1"
#endif
#ifndef APP_NAME
#define APP_NAME "SpotMicro"
#endif
#ifndef APPLICATION_CORE
#define APPLICATION_CORE -1
#endif
class Spot {
public:
Spot();
void initialize();
// sense
void readSensors() {
_peripherals.readIMU();
_peripherals.readMag();
_peripherals.readBMP();
EXECUTE_EVERY_N_MS(100, { _peripherals.readGesture(); });
}
// plan
void planMotion() { updatedMotion = _motionService.updateMotion(); }
// act
void updateActuators() {
if (updatedMotion) _servoController.setAngles(_motionService.getAngles());
updatedMotion = false;
_servoController.updateServoState();
#if FT_ENABLED(USE_WS2812)
_ledService.loop();
#endif
}
// communicate
void emitTelemetry() {
if (updatedMotion) EXECUTE_EVERY_N_MS(100, { _motionService.emitAngles(); });
EXECUTE_EVERY_N_MS(250, { _peripherals.emitIMU(); });
// _peripherals.emitSonar();
}
private:
PsychicHttpServer _server;
WiFiService _wifiService;
APService _apService;
EventSocket _socket;
MDNSService _mdnsService;
#if FT_ENABLED(USE_UPLOAD_FIRMWARE)
FirmwareUploadService _uploadFirmwareService;
#endif
#if FT_ENABLED(USE_DOWNLOAD_FIRMWARE)
DownloadFirmwareService _downloadFirmwareService;
#endif
#if FT_ENABLED(USE_MOTION)
MotionService _motionService;
#endif
#if FT_ENABLED(USE_CAMERA)
Camera::CameraService _cameraService;
#endif
Peripherals _peripherals;
ServoController _servoController;
#if FT_ENABLED(USE_WS2812)
LEDService _ledService;
#endif
bool updatedMotion = false;
const char *_appName = APP_NAME;
const u_int16_t _numberEndpoints = 137 + 36;
const u_int32_t _maxFileUpload = 2300000; // 2.3 MB
const uint16_t _port = 80;
protected:
void loop();
static void _loopImpl(void *_this) { static_cast<Spot *>(_this)->loop(); }
void setupServer();
void startServices();
};
#endif
+1 -1
View File
@@ -5,7 +5,7 @@
#include <PsychicHttp.h>
#include <WiFi.h>
#include <task_manager.h>
#include <event_socket.h>
// #include <event_socket.h>
#include <filesystem.h>
#include <global.h>
@@ -90,7 +90,7 @@ class FSPersistence {
JsonStateReader<T> _stateReader;
JsonStateUpdater<T> _stateUpdater;
StatefulService<T> *_statefulService;
FS *_fs {&ESPFS};
FS *_fs {&ESP_FS};
const char *_filePath;
size_t _bufferSize;
HandlerId _updateHandlerId;
+6 -6
View File
@@ -2,7 +2,7 @@
#include <PsychicHttp.h>
#include <event_socket.h>
// #include <event_socket.h>
#include <template/stateful_service.h>
template <class T>
@@ -15,10 +15,10 @@ class EventEndpoint {
}
void begin() {
socket.onEvent(_event,
std::bind(&EventEndpoint::updateState, this, std::placeholders::_1, std::placeholders::_2));
socket.onSubscribe(_event,
std::bind(&EventEndpoint::syncState, this, std::placeholders::_1, std::placeholders::_2));
// socket.onEvent(_event,
// std::bind(&EventEndpoint::updateState, this, std::placeholders::_1, std::placeholders::_2));
// socket.onSubscribe(_event,
// std::bind(&EventEndpoint::syncState, this, std::placeholders::_1, std::placeholders::_2));
}
private:
@@ -35,6 +35,6 @@ class EventEndpoint {
JsonDocument jsonDocument;
JsonVariant root = jsonDocument.to<JsonVariant>();
_statefulService->read(root, _stateReader);
socket.emit(_event, root, originId.c_str(), sync);
// socket.emit(_event, root, originId.c_str(), sync);
}
};
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <PsychicHttp.h>
#include "WWWData.h"
void mountStaticAssets(PsychicHttpServer& s);