diff --git a/src/Actuators.h b/src/Actuators.h new file mode 100644 index 00000000..496201c9 --- /dev/null +++ b/src/Actuators.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +enum ACTUATOR_TYPE{ + SERVO, + STEPPER +}; + +/** + * All actuators eg. Servos, Steppers, etc. use this to allow for max control + */ +class Actuator{ + public: + Actuator(ACTUATOR_TYPE actType, int instance) { + instance_num = instance; + type = actType; + }; + + /** + * Called when a packet is received that needs to move the actuator + * @param json The parameters that can change + */ + virtual void control(JsonArray json) = 0; + + /** + * Convert the type of actuator to a String + */ + String typeToString(){ + switch(type){ + case SERVO: + return "Servo"; + case STEPPER: + return "Stepper"; + } + }; + + /** + * Get the instance number of the actuator + */ + int get_instance_num() { return instance_num; }; + + private: + int instance_num; // Instance number of the Actuator + ACTUATOR_TYPE type; // Type of actuator +}; \ No newline at end of file diff --git a/src/Internet/PublishingPlatforms/Loom_Max.cpp b/src/Internet/PublishingPlatforms/Loom_Max.cpp index adefc023..d5fe722b 100644 --- a/src/Internet/PublishingPlatforms/Loom_Max.cpp +++ b/src/Internet/PublishingPlatforms/Loom_Max.cpp @@ -15,6 +15,15 @@ Loom_Max::~Loom_Max() { } ////////////////////////////////////////////////////////////////////////////////////////////////////// +void Loom_Max::package(){ + JsonArray tmp = manInst->getDocument()["id"].createNestedArray("ip"); + IPAddress ip = wifiInst->getIPAddress(); + tmp.add(ip[0]); + tmp.add(ip[1]); + tmp.add(ip[2]); + tmp.add(ip[3]); +} + ////////////////////////////////////////////////////////////////////////////////////////////////////// void Loom_Max::initialize(){ @@ -40,7 +49,6 @@ bool Loom_Max::publish(){ } size_t size = serializeJson(manInst->getDocument(), (*udpSend)); - Serial.println(size); if(size <= 0){ printModuleName(); Serial.println("An error occurred when attempting to write the JSON packet to the UDP stream"); @@ -72,16 +80,40 @@ bool Loom_Max::subscribe(){ return false; } - printModuleName(); Serial.println("Packet received from: " + Loom_WIFI::IPtoString(udpRecv->remoteIP())); - printModuleName(); Serial.println("Message Json: "); - serializeJsonPretty(messageJson, Serial); - Serial.println("\n"); - - // DISPATCH HERE + // If there are actuators supplied control those if not just print the packet + if(actuators.size() > 0){ + if(messageJson["type"].as() == "command"){ + // Loop over each command being sent to the device + for(int j = 0; j < messageJson["commands"].as().size(); j++){ + // Loop over each actuator to find the right one + String type = messageJson["commands"][j]["module"].as(); + int instanceNum = messageJson["commands"][j]["params"][0].as(); + + // Loop over each actuator + for(int i = 0; i < actuators.size(); i++){ + + // If the current actuator is the one we want to control + if(actuators[i]->typeToString() == type && actuators[i]->get_instance_num() == instanceNum){ + + // Pass the parameters field to the actuator + actuators[i]->control(messageJson["commands"][j]["params"].as()); + } + } + } + } + } + else{ + printModuleName(); Serial.println("Packet received from: " + Loom_WIFI::IPtoString(udpRecv->remoteIP())); + printModuleName(); Serial.println("Message Json: "); + serializeJsonPretty(messageJson, Serial); + Serial.println("\n"); + } return true; } + printModuleName(); Serial.println("No message received!"); + return false; } diff --git a/src/Loom_Max.h b/src/Loom_Max.h index 98bb7ee8..f8348334 100644 --- a/src/Loom_Max.h +++ b/src/Loom_Max.h @@ -2,7 +2,10 @@ #include "Module.h" #include "Loom_Wifi.h" +#include "Actuators.h" + #include +#include #include // Base ports to send and receive on @@ -19,7 +22,7 @@ class Loom_Max : public Module{ void print_measurements() override {}; void power_up() override {}; void power_down() override {}; - void package() override {}; + void package() override; public: /// Close the socket and delete the UDP object when the unique ptr dissapears @@ -54,6 +57,38 @@ class Loom_Max : public Module{ */ Loom_Max(Manager& man, Loom_WIFI& wifi); + /** + * Construct a new instance of the the Max MSP Pub/Sub protocol + * @param man Reference to the manager + * @param wifi Reference to the Wifi manager for getting UDP communication streams + * @param firstAct The first actuator to add to the list + */ + template + Loom_Max(Manager& man, Loom_WIFI& wifi, T firstAct) : Module("Max Pub/Sub"), manInst(&man), wifiInst(&wifi){ + + actuators.push_back(&firstAct); + + udpSend = UDPPtr(wifiInst->getUDP()); + udpRecv = UDPPtr(wifiInst->getUDP()); + manInst->registerModule(this); + }; + + /** + * Construct a new instance of the the Max MSP Pub/Sub protocol + * @param man Reference to the manager + * @param wifi Reference to the Wifi manager for getting UDP communication streams + * @param firstAct The first actuator to add to the list + * @param additionalActuators This takes any number of actuators + */ + template + Loom_Max(Manager& man, Loom_WIFI& wifi, T firstAct, Args... additionalActuators) : Module("Max Pub/Sub"), manInst(&man), wifiInst(&wifi){ + get_variadic_parameters(firstAct, additionalActuators...); + + udpSend = UDPPtr(wifiInst->getUDP()); + udpRecv = UDPPtr(wifiInst->getUDP()); + manInst->registerModule(this); + }; + ~Loom_Max(); private: @@ -72,6 +107,26 @@ class Loom_Max : public Module{ void setIP(); // Set the remote IP to send the packets too StaticJsonDocument<1000> messageJson; // Response packet + + std::vector actuators; // List of actuators we want to control with max + + + /* + * The following two functions are some sorcery to get the variadic parameters without the need for passing in a size variable + * I don't fully understand it so don't touch it just works + * Based off: https://eli.thegreenplace.net/2014/variadic-templates-in-c/ + */ + template + T get_variadic_parameters(T v) { + actuators.push_back(&v); + return v; + }; + + template + T get_variadic_parameters(T first, Args... args) { + actuators.push_back(&first); + return get_variadic_parameters(args...); + }; }; \ No newline at end of file