Refactor endpoints
parent
8e8070e7b6
commit
dad701045c
|
@ -0,0 +1,48 @@
|
||||||
|
#include <SpejsNode.h>
|
||||||
|
#include <Endpoint.h>
|
||||||
|
|
||||||
|
void Endpoint::bind(String key, SpejsNode* _parent) {
|
||||||
|
parent = _parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Endpoint::notify(String value) {
|
||||||
|
/*if(parent)
|
||||||
|
parent->notify(this, value);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> void InputEndpoint<T>::updateValue(T newValue) {
|
||||||
|
value = newValue;
|
||||||
|
//if(parent)
|
||||||
|
// parent->notify(String("xD"), String(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
EndpointResult ControlEndpoint::onValue(String key, String value) {
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
if (value == "ota") {
|
||||||
|
return 200;
|
||||||
|
} else if(value == "restart") {
|
||||||
|
return 200;
|
||||||
|
} else {
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OutputEndpoint::fillValue(JsonObject& obj) {
|
||||||
|
obj["value"] = currentValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EndpointResult OutputEndpoint::onValue(String key, String value) {
|
||||||
|
if (value == "1" or value == "on") {
|
||||||
|
currentValue = 1;
|
||||||
|
} else if (value == "0" or value == "off") {
|
||||||
|
currentValue = 0;
|
||||||
|
} else if (value == "toggle") {
|
||||||
|
currentValue = !currentValue;
|
||||||
|
} else {
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(pin, inverted ^ currentValue);
|
||||||
|
return 200;
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
#ifndef ENDPOINT_H
|
||||||
|
#define ENDPOINT_H
|
||||||
|
|
||||||
|
#include <SmingCore/SmingCore.h>
|
||||||
|
|
||||||
|
class SpejsNode;
|
||||||
|
|
||||||
|
class EndpointResult {
|
||||||
|
public:
|
||||||
|
int status;
|
||||||
|
String description;
|
||||||
|
|
||||||
|
EndpointResult(int _status) : status(_status) {}
|
||||||
|
EndpointResult(int _status, String _description) :
|
||||||
|
status(_status), description(_description) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Endpoint {
|
||||||
|
protected:
|
||||||
|
const SpejsNode* parent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
String type;
|
||||||
|
|
||||||
|
Endpoint(String _type = "unknown") : type(_type) { }
|
||||||
|
|
||||||
|
virtual void bind(String key, SpejsNode* _parent);
|
||||||
|
void notify(String value);
|
||||||
|
|
||||||
|
virtual EndpointResult onValue(String key, String value) {
|
||||||
|
return 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void fillValue(JsonObject& obj) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ControlEndpoint : public Endpoint {
|
||||||
|
public:
|
||||||
|
ControlEndpoint() : Endpoint("control") {}
|
||||||
|
EndpointResult onValue(String key, String value);
|
||||||
|
};
|
||||||
|
|
||||||
|
class OutputEndpoint : public Endpoint {
|
||||||
|
private:
|
||||||
|
int pin;
|
||||||
|
bool inverted;
|
||||||
|
bool currentValue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OutputEndpoint(int _pin, bool _inverted = false) :
|
||||||
|
Endpoint("output"), pin(_pin), inverted(_inverted), currentValue(inverted) {
|
||||||
|
pinMode(pin, OUTPUT);
|
||||||
|
digitalWrite(pin, currentValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EndpointResult onValue(String key, String value);
|
||||||
|
void fillValue(JsonObject& obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> class InputEndpoint : public Endpoint {
|
||||||
|
protected:
|
||||||
|
T value;
|
||||||
|
void updateValue(T newValue);
|
||||||
|
|
||||||
|
public:
|
||||||
|
InputEndpoint(String _type) : Endpoint(_type) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#include <Libraries/DHT/DHT.h>
|
||||||
|
|
||||||
|
class DHT22Endpoint : public InputEndpoint<int> {
|
||||||
|
private:
|
||||||
|
DHT sensor;
|
||||||
|
Timer samplingTimer;
|
||||||
|
int samplingRate;
|
||||||
|
|
||||||
|
public:
|
||||||
|
DHT22Endpoint(int _pin, int _samplingRate = 10000) :
|
||||||
|
InputEndpoint("dht22"), sensor(_pin), samplingRate(_samplingRate) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,4 +1,5 @@
|
||||||
#include <SpejsNode.h>
|
#include <SpejsNode.h>
|
||||||
|
#include <Endpoint.h>
|
||||||
#include <ver.h>
|
#include <ver.h>
|
||||||
|
|
||||||
void SpejsNode::init() {
|
void SpejsNode::init() {
|
||||||
|
@ -15,10 +16,9 @@ void SpejsNode::init() {
|
||||||
Serial.print(deviceID);
|
Serial.print(deviceID);
|
||||||
Serial.printf(", current rom: %d\r\n", currentSlot);
|
Serial.printf(", current rom: %d\r\n", currentSlot);
|
||||||
|
|
||||||
WifiStation.config(WIFI_SSID, WIFI_PWD);
|
|
||||||
WifiStation.enable(true);
|
|
||||||
|
|
||||||
WifiAccessPoint.enable(false);
|
WifiAccessPoint.enable(false);
|
||||||
|
WifiStation.enable(true);
|
||||||
|
WifiStation.config(WIFI_SSID, WIFI_PWD);
|
||||||
|
|
||||||
WifiStation.waitConnection(
|
WifiStation.waitConnection(
|
||||||
ConnectionDelegate(&SpejsNode::onConnected, this),
|
ConnectionDelegate(&SpejsNode::onConnected, this),
|
||||||
|
@ -26,7 +26,7 @@ void SpejsNode::init() {
|
||||||
Serial.println("Connection failed");
|
Serial.println("Connection failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
inputs["control"] = MqttStringSubscriptionCallback(&SpejsNode::controlHandler, this);
|
registerEndpoint("control", new ControlEndpoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpejsNode::keepAliveHandler() {
|
void SpejsNode::keepAliveHandler() {
|
||||||
|
@ -50,6 +50,7 @@ void SpejsNode::keepAliveHandler() {
|
||||||
|
|
||||||
void SpejsNode::httpIndex(HttpRequest &request, HttpResponse &response)
|
void SpejsNode::httpIndex(HttpRequest &request, HttpResponse &response)
|
||||||
{
|
{
|
||||||
|
response.sendString("This is spejsiot device, take a look at: https://wiki.hackerspace.pl/projects:spejsiot");
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpejsNode::httpMetadata(HttpRequest &request, HttpResponse &response)
|
void SpejsNode::httpMetadata(HttpRequest &request, HttpResponse &response)
|
||||||
|
@ -61,10 +62,15 @@ void SpejsNode::httpMetadata(HttpRequest &request, HttpResponse &response)
|
||||||
json["device_type"] = deviceType;
|
json["device_type"] = deviceType;
|
||||||
json["rom_slot"] = currentSlot;
|
json["rom_slot"] = currentSlot;
|
||||||
json["rom_rev"] = BUILD_ID;
|
json["rom_rev"] = BUILD_ID;
|
||||||
|
json["uptime"] = millis();
|
||||||
|
|
||||||
JsonArray& endpoints = json.createNestedArray("endpoints");
|
JsonArray& endpoints_list = json.createNestedArray("endpoints");
|
||||||
for(unsigned int i = 0; i < inputs.count(); i++) {
|
for(unsigned int i = 0; i < endpoints.count(); i++) {
|
||||||
endpoints.add(inputs.keyAt(i));
|
JsonObject& obj = endpoints_list.createNestedObject();
|
||||||
|
obj["name"] = endpoints.keyAt(i);
|
||||||
|
obj["type"] = endpoints.valueAt(i)->type;
|
||||||
|
|
||||||
|
endpoints.valueAt(i)->fillValue(obj);
|
||||||
}
|
}
|
||||||
response.sendJsonObject(stream);
|
response.sendJsonObject(stream);
|
||||||
}
|
}
|
||||||
|
@ -81,13 +87,13 @@ void SpejsNode::httpFile(HttpRequest &request, HttpResponse &response)
|
||||||
String key = req.substring(0, req.indexOf("/"));
|
String key = req.substring(0, req.indexOf("/"));
|
||||||
String value = req.substring(req.indexOf("/") + 1);
|
String value = req.substring(req.indexOf("/") + 1);
|
||||||
|
|
||||||
if(key.length() == 0 || value.length() == 0 || !inputs.contains(key)) {
|
if(key.length() == 0 || value.length() == 0 || !endpoints.contains(key)) {
|
||||||
response.badRequest();
|
response.badRequest();
|
||||||
} else {
|
} else {
|
||||||
inputs[key](key, value);
|
EndpointResult result = endpoints[key]->onValue(key, value);
|
||||||
JsonObjectStream* stream = new JsonObjectStream();
|
JsonObjectStream* stream = new JsonObjectStream();
|
||||||
JsonObject& json = stream->getRoot();
|
JsonObject& json = stream->getRoot();
|
||||||
json["status"] = (bool)true;
|
json["status"] = result.status;
|
||||||
response.sendJsonObject(stream);
|
response.sendJsonObject(stream);
|
||||||
}
|
}
|
||||||
} else if (file[0] == '.') {
|
} else if (file[0] == '.') {
|
||||||
|
@ -112,10 +118,8 @@ void SpejsNode::onConnected() {
|
||||||
mqtt.connect("iot-" + deviceID);
|
mqtt.connect("iot-" + deviceID);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/control");
|
for(unsigned int i = 0 ; i < endpoints.count() ; i++) {
|
||||||
|
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/" + endpoints.keyAt(i));
|
||||||
for(unsigned int i = 0 ; i < inputs.count() ; i++) {
|
|
||||||
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/" + inputs.keyAt(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mqtt.publish(TOPIC_PREFIX + deviceID + "/state", "online");
|
mqtt.publish(TOPIC_PREFIX + deviceID + "/state", "online");
|
||||||
|
@ -130,20 +134,20 @@ void SpejsNode::onConnected() {
|
||||||
|
|
||||||
http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this));
|
http.setDefaultHandler(HttpPathDelegate(&SpejsNode::httpFile, this));
|
||||||
|
|
||||||
static struct mdns_info info;// *info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
|
static struct mdns_info *info = (struct mdns_info *)os_zalloc(sizeof(struct mdns_info));
|
||||||
char tmp_name[32];
|
char tmp_name[32];
|
||||||
("iot-" + deviceID).toCharArray(tmp_name, 32);
|
("iot-" + deviceID).toCharArray(tmp_name, 32);
|
||||||
info.host_name = tmp_name; // You can replace test with your own host name
|
info->host_name = tmp_name; // You can replace test with your own host name
|
||||||
info.ipAddr = WifiStation.getIP();
|
info->ipAddr = WifiStation.getIP();
|
||||||
info.server_name = (char *) "spejsiot";
|
info->server_name = (char *) "spejsiot";
|
||||||
info.server_port = 80;
|
info->server_port = 80;
|
||||||
info.txt_data[0] = (char *) "version = now";
|
info->txt_data[0] = (char *) "version = now";
|
||||||
|
|
||||||
char tmp_type[32] = "type = ";
|
char tmp_type[32] = "type = ";
|
||||||
deviceType.toCharArray(tmp_type + 7, 32-7);
|
deviceType.toCharArray(tmp_type + 7, 32-7);
|
||||||
info.txt_data[1] = tmp_type;
|
info->txt_data[1] = tmp_type;
|
||||||
|
|
||||||
espconn_mdns_init(&info);
|
espconn_mdns_init(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpejsNode::notify(String key, String value) {
|
bool SpejsNode::notify(String key, String value) {
|
||||||
|
@ -155,8 +159,9 @@ bool SpejsNode::notify(String key, String value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpejsNode::registerInput(String key, MqttStringSubscriptionCallback callback) {
|
void SpejsNode::registerEndpoint(String key, Endpoint* endpoint) {
|
||||||
inputs[key] = callback;
|
endpoints[key] = endpoint;
|
||||||
|
endpoint->bind(key, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpejsNode::mqttCallback(String origtopic, String value) {
|
void SpejsNode::mqttCallback(String origtopic, String value) {
|
||||||
|
@ -172,8 +177,8 @@ void SpejsNode::mqttCallback(String origtopic, String value) {
|
||||||
Serial.println(topic);
|
Serial.println(topic);
|
||||||
Serial.println(value);
|
Serial.println(value);
|
||||||
|
|
||||||
if(inputs.contains(topic)) {
|
if(endpoints.contains(topic)) {
|
||||||
inputs[topic](origtopic, value);
|
endpoints[topic]->onValue(origtopic, value);
|
||||||
} else {
|
} else {
|
||||||
Serial.println("unknown topic?");
|
Serial.println("unknown topic?");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
|
#ifndef SPEJSNODE_H
|
||||||
|
#define SPEJSNODE_H
|
||||||
|
|
||||||
#include <user_config.h>
|
#include <user_config.h>
|
||||||
#include <common_config.h>
|
#include <common_config.h>
|
||||||
#include <SmingCore/SmingCore.h>
|
#include <SmingCore/SmingCore.h>
|
||||||
|
#include <Endpoint.h>
|
||||||
|
|
||||||
class SpejsNode {
|
class SpejsNode {
|
||||||
protected:
|
protected:
|
||||||
|
@ -14,13 +18,14 @@ protected:
|
||||||
|
|
||||||
rBootHttpUpdate* otaUpdater = 0;
|
rBootHttpUpdate* otaUpdater = 0;
|
||||||
|
|
||||||
HashMap<String, MqttStringSubscriptionCallback> inputs;
|
HashMap<String, Endpoint*> endpoints;
|
||||||
|
|
||||||
void onConnected();
|
void onConnected();
|
||||||
void startOTA();
|
void startOTA();
|
||||||
void keepAliveHandler();
|
void keepAliveHandler();
|
||||||
|
|
||||||
uint8_t currentSlot;
|
uint8_t currentSlot;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SpejsNode(String _deviceType) :
|
SpejsNode(String _deviceType) :
|
||||||
mqtt(MQTT_BROKER, MQTT_PORT, MqttStringSubscriptionCallback(&SpejsNode::mqttCallback, this)),
|
mqtt(MQTT_BROKER, MQTT_PORT, MqttStringSubscriptionCallback(&SpejsNode::mqttCallback, this)),
|
||||||
|
@ -30,7 +35,7 @@ public:
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
bool notify(String key, String value);
|
bool notify(String key, String value);
|
||||||
void registerInput(String key, MqttStringSubscriptionCallback cb);
|
void registerEndpoint(String key, Endpoint* cb);
|
||||||
void mqttCallback(String, String);
|
void mqttCallback(String, String);
|
||||||
void controlHandler(String, String);
|
void controlHandler(String, String);
|
||||||
void otaUpdateCallback(rBootHttpUpdate& updater, bool result);
|
void otaUpdateCallback(rBootHttpUpdate& updater, bool result);
|
||||||
|
@ -38,3 +43,5 @@ public:
|
||||||
void httpIndex(HttpRequest &request, HttpResponse &response);
|
void httpIndex(HttpRequest &request, HttpResponse &response);
|
||||||
void httpMetadata(HttpRequest &request, HttpResponse &response);
|
void httpMetadata(HttpRequest &request, HttpResponse &response);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -4,15 +4,5 @@ SpejsNode node("switch");
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
node.init();
|
node.init();
|
||||||
node.registerInput("relay", *[](String key, String value) {
|
node.registerEndpoint("relay", new OutputEndpoint(5));
|
||||||
Serial.println("handler");
|
|
||||||
digitalWrite(5, value == "1" ? HIGH : LOW);
|
|
||||||
});
|
|
||||||
pinMode(5, OUTPUT);
|
|
||||||
digitalWrite(5, LOW);
|
|
||||||
attachInterrupt(BTN_PIN, *[] {
|
|
||||||
node.notify("btn", String(digitalRead(BTN_PIN)));
|
|
||||||
}, CHANGE);
|
|
||||||
//node.registerInputGPIO("btn", BTN_PIN);
|
|
||||||
//node.registerOutputGPIO("led", LED_PIN);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue