Skip to content

Commit

Permalink
Merge pull request #2 from Citrullin/migration
Browse files Browse the repository at this point in the history
change links into forms and minor alligment changes
  • Loading branch information
relu91 authored Aug 18, 2021
2 parents 98b916e + d5511fc commit 1e1d8d7
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 1,011 deletions.
157 changes: 6 additions & 151 deletions ESPWebThingAdapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class WebThingAdapter {
}

MDNS.addService("webthing", "tcp", port);
MDNS.addServiceTxt("webthing", "tcp", "path", "/");
MDNS.addServiceTxt("webthing", "tcp", "path", "/.well-known/wot-thing-description");

DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Methods",
Expand All @@ -70,7 +70,7 @@ class WebThingAdapter {
this->server.on("/*", HTTP_OPTIONS,
std::bind(&WebThingAdapter::handleOptions, this,
std::placeholders::_1));
this->server.on("/", HTTP_GET,
this->server.on("/.well-known/wot-thing-description", HTTP_GET,
std::bind(&WebThingAdapter::handleThings, this,
std::placeholders::_1));

Expand Down Expand Up @@ -158,15 +158,6 @@ class WebThingAdapter {
void update() {
#ifdef ESP8266
MDNS.update();
#endif
#ifndef WITHOUT_WS
// * Send changed properties as defined in "4.5 propertyStatus message"
// Do this by looping over all devices and properties
ThingDevice *device = this->firstDevice;
while (device != nullptr) {
sendChangedProperties(device);
device = device->next;
}
#endif
}

Expand All @@ -178,19 +169,6 @@ class WebThingAdapter {
this->lastDevice->next = device;
this->lastDevice = device;
}

#ifndef WITHOUT_WS
// Initiate the websocket instance
AsyncWebSocket *ws = new AsyncWebSocket("/things/" + device->id);
device->ws = ws;
// AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType
// type, void * arg, uint8_t *data, size_t len, ThingDevice* device
ws->onEvent(std::bind(
&WebThingAdapter::handleWS, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5, std::placeholders::_6, device));
this->server.addHandler(ws);
#endif
}

private:
Expand Down Expand Up @@ -228,118 +206,6 @@ class WebThingAdapter {
return false;
}

#ifndef WITHOUT_WS
void sendErrorMsg(DynamicJsonDocument &prop, AsyncWebSocketClient &client,
int status, const char *msg) {
prop["error"] = msg;
prop["status"] = status;
String jsonStr;
serializeJson(prop, jsonStr);
client.text(jsonStr.c_str(), jsonStr.length());
}

void handleWS(AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, const uint8_t *rawData,
size_t len, ThingDevice *device) {
if (type == WS_EVT_DISCONNECT || type == WS_EVT_ERROR) {
device->removeEventSubscriptions(client->id());
return;
}

// Ignore all others except data packets
if (type != WS_EVT_DATA)
return;

// Only consider non fragmented data
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (!info->final || info->index != 0 || info->len != len)
return;

// Web Thing only specifies text, not binary websocket transfers
if (info->opcode != WS_TEXT)
return;

// In theory we could just have one websocket for all Things and react on
// the server->url() to route data. Controllers will however establish a
// separate websocket connection for each Thing anyway as of in the spec.
// For now each Thing stores its own Websocket connection object therefore.

// Parse request
DynamicJsonDocument newProp(SMALL_JSON_DOCUMENT_SIZE);
auto error = deserializeJson(newProp, rawData, len);
if (error) {
sendErrorMsg(newProp, *client, 400, "Invalid json");
return;
}

String messageType = newProp["messageType"].as<String>();
JsonVariant dataVariant = newProp["data"];
if (!dataVariant.is<JsonObject>()) {
sendErrorMsg(newProp, *client, 400, "data must be an object");
return;
}

JsonObject data = dataVariant.as<JsonObject>();

if (messageType == "setProperty") {
for (JsonPair kv : data) {
device->setProperty(kv.key().c_str(), kv.value());
}
} else if (messageType == "requestAction") {
for (JsonPair kv : data) {
DynamicJsonDocument *actionRequest =
new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE);

JsonObject actionObj = actionRequest->to<JsonObject>();
JsonObject nested = actionObj.createNestedObject(kv.key());

for (JsonPair kvInner : kv.value().as<JsonObject>()) {
nested[kvInner.key()] = kvInner.value();
}

ThingActionObject *obj = device->requestAction(actionRequest);
if (obj != nullptr) {
obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus,
device, std::placeholders::_1));
device->sendActionStatus(obj);

obj->start();
}
}
} else if (messageType == "addEventSubscription") {
for (JsonPair kv : data) {
ThingEvent *event = device->findEvent(kv.key().c_str());
if (event) {
device->addEventSubscription(client->id(), event->id);
}
}
}
}

void sendChangedProperties(ThingDevice *device) {
// Prepare one buffer per device
DynamicJsonDocument message(LARGE_JSON_DOCUMENT_SIZE);
message["messageType"] = "propertyStatus";
JsonObject prop = message.createNestedObject("data");
bool dataToSend = false;
ThingItem *item = device->firstProperty;
while (item != nullptr) {
ThingDataValue *value = item->changedValueOrNull();
if (value) {
dataToSend = true;
item->serializeValue(prop);
}
item = item->next;
}
if (dataToSend) {
String jsonStr;
serializeJson(message, jsonStr);
// Inform all connected ws clients of a Thing about changed properties
((AsyncWebSocket *)device->ws)->textAll(jsonStr);
}
}
#endif

void handleUnknown(AsyncWebServerRequest *request) {
if (!verifyHost(request)) {
return;
Expand All @@ -362,16 +228,15 @@ class WebThingAdapter {
request->beginResponseStream("application/json");

DynamicJsonDocument buf(LARGE_JSON_DOCUMENT_SIZE);
JsonArray things = buf.to<JsonArray>();
JsonObject thing = buf.to<JsonObject>();
ThingDevice *device = this->firstDevice;
while (device != nullptr) {
JsonObject descr = things.createNestedObject();
device->serialize(descr, ip, port);
descr["href"] = "/things/" + device->id;
device->serialize(thing, ip, port);
thing["href"] = "/things/" + device->id;
device = device->next;
}

serializeJson(things, *response);
serializeJson(thing, *response);
request->send(response);
}

Expand Down Expand Up @@ -513,11 +378,6 @@ class WebThingAdapter {
return;
}

#ifndef WITHOUT_WS
obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus, device,
std::placeholders::_1));
#endif

DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE);
JsonObject item = respBuffer.to<JsonObject>();
obj->serialize(item, device->id);
Expand Down Expand Up @@ -624,11 +484,6 @@ class WebThingAdapter {
return;
}

#ifndef WITHOUT_WS
obj->setNotifyFunction(std::bind(&ThingDevice::sendActionStatus, device,
std::placeholders::_1));
#endif

DynamicJsonDocument respBuffer(SMALL_JSON_DOCUMENT_SIZE);
JsonObject item = respBuffer.to<JsonObject>();
obj->serialize(item, device->id);
Expand Down
Loading

0 comments on commit 1e1d8d7

Please sign in to comment.