Converted servocontroller to protobufs + persistance defaults
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
#define ServoController_h
|
||||
|
||||
#include <peripherals/drivers/pca9685.h>
|
||||
#include <template/stateful_persistence.h>
|
||||
#include <template/stateful_persistence_pb.h>
|
||||
#include <template/stateful_proto_endpoint.h>
|
||||
#include <template/stateful_service.h>
|
||||
#include <template/stateful_endpoint.h>
|
||||
#include <utils/math_utils.h>
|
||||
#include <settings/servo_settings.h>
|
||||
#include <platform_shared/api.pb.h>
|
||||
|
||||
#ifndef FACTORY_SERVO_PWM_FREQUENCY
|
||||
#define FACTORY_SERVO_PWM_FREQUENCY 50
|
||||
@@ -16,13 +16,47 @@
|
||||
#define FACTORY_SERVO_OSCILLATOR_FREQUENCY 27000000
|
||||
#endif
|
||||
|
||||
#define SERVO_SETTINGS_FILE "/config/servoSettings.pb"
|
||||
|
||||
enum class SERVO_CONTROL_STATE { DEACTIVATED, PWM, ANGLE };
|
||||
|
||||
using ServoSettings = api_ServoSettings;
|
||||
|
||||
inline ServoSettings ServoSettings_defaults() {
|
||||
ServoSettings settings = {};
|
||||
settings.servos_count = 12;
|
||||
const api_Servo defaults[12] = {
|
||||
{306, -1, 0, 2.2f, "Servo1"}, {306, 1, -45, 2.1055555f, "Servo2"},
|
||||
{306, 1, 90, 1.96923f, "Servo3"}, {306, -1, 0, 2.2f, "Servo4"},
|
||||
{306, -1, 45, 2.1055555f, "Servo5"}, {306, -1, -90, 1.96923f, "Servo6"},
|
||||
{306, 1, 0, 2.2f, "Servo7"}, {306, 1, -45, 2.1055555f, "Servo8"},
|
||||
{306, 1, 90, 1.96923f, "Servo9"}, {306, 1, 0, 2.2f, "Servo10"},
|
||||
{306, -1, 45, 2.1055555f, "Servo11"}, {306, -1, -90, 1.96923f, "Servo12"}
|
||||
};
|
||||
for (int i = 0; i < 12; i++) {
|
||||
settings.servos[i] = defaults[i];
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
inline void ServoSettings_read(const ServoSettings &settings, ServoSettings &proto) {
|
||||
proto = settings;
|
||||
}
|
||||
|
||||
inline StateUpdateResult ServoSettings_update(const ServoSettings &proto, ServoSettings &settings) {
|
||||
settings = proto;
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
|
||||
class ServoController : public StatefulService<ServoSettings> {
|
||||
public:
|
||||
ServoController()
|
||||
: endpoint(ServoSettings::read, ServoSettings::update, this),
|
||||
_persistence(ServoSettings::read, ServoSettings::update, this, SERVO_SETTINGS_FILE) {}
|
||||
: protoEndpoint(ServoSettings_read, ServoSettings_update, this,
|
||||
API_REQUEST_EXTRACTOR(servo_settings, ServoSettings),
|
||||
API_RESPONSE_ASSIGNER(servo_settings, ServoSettings)),
|
||||
_persistence(ServoSettings_read, ServoSettings_update, this,
|
||||
SERVO_SETTINGS_FILE, api_ServoSettings_fields, api_ServoSettings_size,
|
||||
ServoSettings_defaults()) {}
|
||||
|
||||
void begin() {
|
||||
_persistence.readFromFS();
|
||||
@@ -78,8 +112,8 @@ class ServoController : public StatefulService<ServoSettings> {
|
||||
for (int i = 0; i < 12; i++) {
|
||||
angles[i] = lerp(angles[i], target_angles[i], 0.1);
|
||||
auto &servo = state().servos[i];
|
||||
float angle = servo.direction * angles[i] + servo.centerAngle;
|
||||
uint16_t pwm = angle * servo.conversion + servo.centerPwm;
|
||||
float angle = servo.direction * angles[i] + servo.center_angle;
|
||||
uint16_t pwm = angle * servo.conversion + servo.center_pwm;
|
||||
pwms[i] = pwm = std::clamp<uint16_t>(pwm, 125, 600);
|
||||
}
|
||||
_pca.setMultiplePWM(pwms, 12);
|
||||
@@ -89,7 +123,7 @@ class ServoController : public StatefulService<ServoSettings> {
|
||||
if (control_state == SERVO_CONTROL_STATE::ANGLE) calculatePWM();
|
||||
}
|
||||
|
||||
StatefulHttpEndpoint<ServoSettings> endpoint;
|
||||
StatefulProtoEndpoint<ServoSettings, ServoSettings> protoEndpoint;
|
||||
|
||||
private:
|
||||
void initializePCA() {
|
||||
@@ -98,7 +132,7 @@ class ServoController : public StatefulService<ServoSettings> {
|
||||
_pca.setPWMFreq(FACTORY_SERVO_PWM_FREQUENCY);
|
||||
_pca.sleep();
|
||||
}
|
||||
FSPersistence<ServoSettings> _persistence;
|
||||
FSPersistencePB<ServoSettings> _persistence;
|
||||
|
||||
PCA9685Driver _pca;
|
||||
|
||||
|
||||
@@ -63,6 +63,19 @@ inline uint32_t parseIPv4(const char *str) {
|
||||
|
||||
using APSettings = api_APSettings;
|
||||
|
||||
inline APSettings APSettings_defaults() {
|
||||
APSettings settings = {};
|
||||
settings.provision_mode = FACTORY_AP_PROVISION_MODE;
|
||||
strncpy(settings.ssid, FACTORY_AP_SSID, sizeof(settings.ssid) - 1);
|
||||
strncpy(settings.password, FACTORY_AP_PASSWORD, sizeof(settings.password) - 1);
|
||||
settings.channel = FACTORY_AP_CHANNEL;
|
||||
settings.ssid_hidden = FACTORY_AP_SSID_HIDDEN;
|
||||
settings.max_clients = FACTORY_AP_MAX_CLIENTS;
|
||||
settings.local_ip = parseIPv4(FACTORY_AP_LOCAL_IP);
|
||||
settings.gateway_ip = parseIPv4(FACTORY_AP_GATEWAY_IP);
|
||||
settings.subnet_mask = parseIPv4(FACTORY_AP_SUBNET_MASK);
|
||||
return settings;
|
||||
}
|
||||
|
||||
inline void APSettings_read(const APSettings &settings, APSettings &proto) {
|
||||
proto = settings;
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
#include <template/state_result.h>
|
||||
|
||||
typedef struct {
|
||||
float centerPwm;
|
||||
float direction;
|
||||
float centerAngle;
|
||||
float conversion;
|
||||
const char *name;
|
||||
// bool enable;
|
||||
} servo_settings_t;
|
||||
|
||||
class ServoSettings {
|
||||
public:
|
||||
servo_settings_t servos[12] = {
|
||||
{306, -1, 0, 2.2, "Servo1"}, {306, 1, -45, 2.1055555, "Servo2"}, {306, 1, 90, 1.96923, "Servo3"},
|
||||
{306, -1, 0, 2.2, "Servo4"}, {306, -1, 45, 2.1055555, "Servo5"}, {306, -1, -90, 1.96923, "Servo6"},
|
||||
{306, 1, 0, 2.2, "Servo7"}, {306, 1, -45, 2.1055555, "Servo8"}, {306, 1, 90, 1.96923, "Servo9"},
|
||||
{306, 1, 0, 2.2, "Servo10"}, {306, -1, 45, 2.1055555, "Servo11"}, {306, -1, -90, 1.96923, "Servo12"}};
|
||||
static void read(ServoSettings &settings, JsonVariant &root) {
|
||||
JsonArray servos = root["servos"].to<JsonArray>();
|
||||
for (auto &servo : settings.servos) {
|
||||
JsonVariant newServo = servos.add<JsonVariant>();
|
||||
newServo["center_pwm"] = servo.centerPwm;
|
||||
newServo["direction"] = servo.direction;
|
||||
newServo["center_angle"] = servo.centerAngle;
|
||||
newServo["conversion"] = servo.conversion;
|
||||
}
|
||||
}
|
||||
static StateUpdateResult update(JsonVariant &root, ServoSettings &settings) {
|
||||
if (root["servos"].is<JsonArray>()) {
|
||||
JsonArray servosJson = root["servos"];
|
||||
int i = 0;
|
||||
for (auto servo : servosJson) {
|
||||
JsonVariant servoObject = servo.as<JsonVariant>();
|
||||
uint8_t servoId = i; // servoObject["id"].as<uint8_t>();
|
||||
settings.servos[servoId].centerPwm = servoObject["center_pwm"].as<float>();
|
||||
settings.servos[servoId].centerAngle = servoObject["center_angle"].as<float>();
|
||||
settings.servos[servoId].direction = servoObject["direction"].as<float>();
|
||||
settings.servos[servoId].conversion = servoObject["conversion"].as<float>();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
ESP_LOGI("ServoController", "Updating servo data");
|
||||
return StateUpdateResult::CHANGED;
|
||||
};
|
||||
};
|
||||
@@ -22,13 +22,15 @@ class FSPersistencePB {
|
||||
|
||||
FSPersistencePB(ProtoStateReader stateReader, ProtoStateUpdater stateUpdater,
|
||||
StatefulService<T> *statefulService, const char *filePath,
|
||||
const pb_msgdesc_t *msgDescriptor, size_t maxSize)
|
||||
const pb_msgdesc_t *msgDescriptor, size_t maxSize,
|
||||
const T &defaultState)
|
||||
: _stateReader(stateReader),
|
||||
_stateUpdater(stateUpdater),
|
||||
_statefulService(statefulService),
|
||||
_filePath(filePath),
|
||||
_msgDescriptor(msgDescriptor),
|
||||
_maxSize(maxSize),
|
||||
_defaultState(defaultState),
|
||||
_updateHandlerId(0) {
|
||||
enableUpdateHandler();
|
||||
}
|
||||
@@ -115,6 +117,7 @@ class FSPersistencePB {
|
||||
const char *_filePath;
|
||||
const pb_msgdesc_t *_msgDescriptor;
|
||||
size_t _maxSize;
|
||||
T _defaultState;
|
||||
HandlerId _updateHandlerId;
|
||||
|
||||
void mkdirs() {
|
||||
@@ -127,9 +130,8 @@ class FSPersistencePB {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void applyDefaults() {
|
||||
T defaultState = {};
|
||||
void applyDefaults() {
|
||||
_statefulService->updateWithoutPropagation(
|
||||
[this, &defaultState](T &state) { return _stateUpdater(defaultState, state); });
|
||||
[this](T &state) { return _stateUpdater(_defaultState, state); });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include <template/stateful_service.h>
|
||||
#include <communication/native_server.h>
|
||||
#include <communication/webserver.h>
|
||||
#include <platform_shared/api.pb.h>
|
||||
#include <pb_encode.h>
|
||||
#include <pb_decode.h>
|
||||
@@ -95,7 +95,7 @@ class StatefulProtoEndpoint {
|
||||
_statefulService->read([this, &protoState](const T& settings) { _stateReader(settings, protoState); });
|
||||
_responseAssigner(res, protoState);
|
||||
|
||||
return NativeServer::sendProto(request, 200, res, api_Response_fields);
|
||||
return WebServer::sendProto(request, 200, res, api_Response_fields);
|
||||
}
|
||||
|
||||
/** Sends error wrapped in Response */
|
||||
@@ -103,7 +103,7 @@ class StatefulProtoEndpoint {
|
||||
api_Response res = api_Response_init_zero;
|
||||
res.status_code = statusCode;
|
||||
res.error_message = (char*)message;
|
||||
return NativeServer::sendProto(request, statusCode == 200 ? 200 : 400, res, api_Response_fields);
|
||||
return WebServer::sendProto(request, statusCode == 200 ? 200 : 400, res, api_Response_fields);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user