diff --git a/ESPWebThingAdapter.h b/ESPWebThingAdapter.h index 6d96fcf..56f3535 100644 --- a/ESPWebThingAdapter.h +++ b/ESPWebThingAdapter.h @@ -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", @@ -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)); @@ -131,17 +131,7 @@ class WebThingAdapter { std::bind(&WebThingAdapter::handleThingPropertiesGet, this, std::placeholders::_1, device->firstProperty)); - this->server.on((deviceBase + "/actions").c_str(), HTTP_GET, - std::bind(&WebThingAdapter::handleThingActionsGet, this, - std::placeholders::_1, device)); - this->server.on((deviceBase + "/actions").c_str(), HTTP_POST, - std::bind(&WebThingAdapter::handleThingActionsPost, this, - std::placeholders::_1, device), - NULL, - std::bind(&WebThingAdapter::handleBody, this, - std::placeholders::_1, std::placeholders::_2, - std::placeholders::_3, std::placeholders::_4, - std::placeholders::_5)); + this->server.on((deviceBase + "/events").c_str(), HTTP_GET, std::bind(&WebThingAdapter::handleThingEventsGet, this, std::placeholders::_1, device)); @@ -362,16 +352,15 @@ class WebThingAdapter { request->beginResponseStream("application/json"); DynamicJsonDocument buf(LARGE_JSON_DOCUMENT_SIZE); - JsonArray things = buf.to(); + JsonObject thing = buf.to(); 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); } @@ -474,6 +463,7 @@ class WebThingAdapter { void handleThingActionPost(AsyncWebServerRequest *request, ThingDevice *device, ThingAction *action) { if (!verifyHost(request)) { + Serial.println("Invalid Host"); return; } @@ -486,6 +476,7 @@ class WebThingAdapter { new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE); auto error = deserializeJson(*newBuffer, (const char *)body_data); if (error) { // unable to parse json + Serial.println("Unable to parse JSON"); b_has_body_data = false; memset(body_data, 0, sizeof(body_data)); request->send(500); @@ -493,24 +484,11 @@ class WebThingAdapter { return; } - JsonObject newAction = newBuffer->as(); - - if (!newAction.containsKey(action->id)) { - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - request->send(400); - delete newBuffer; - return; - } - - ThingActionObject *obj = device->requestAction(newBuffer); - + ThingActionObject *obj = action->create(newBuffer); if (obj == nullptr) { - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - request->send(500); - delete newBuffer; - return; + memset(body_data, 0, sizeof(body_data)); + request->send(500); + return; } #ifndef WITHOUT_WS @@ -567,84 +545,7 @@ class WebThingAdapter { request->send(response); } - void handleThingActionsGet(AsyncWebServerRequest *request, - ThingDevice *device) { - if (!verifyHost(request)) { - return; - } - AsyncResponseStream *response = - request->beginResponseStream("application/json"); - - DynamicJsonDocument doc(LARGE_JSON_DOCUMENT_SIZE); - JsonArray queue = doc.to(); - device->serializeActionQueue(queue); - serializeJson(queue, *response); - request->send(response); - } - - void handleThingActionsPost(AsyncWebServerRequest *request, - ThingDevice *device) { - if (!verifyHost(request)) { - return; - } - - if (!b_has_body_data) { - request->send(422); // unprocessable entity (b/c no body) - return; - } - - DynamicJsonDocument *newBuffer = - new DynamicJsonDocument(SMALL_JSON_DOCUMENT_SIZE); - auto error = deserializeJson(*newBuffer, (const char *)body_data); - if (error) { // unable to parse json - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - request->send(500); - delete newBuffer; - return; - } - - JsonObject newAction = newBuffer->as(); - - if (newAction.size() != 1) { - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - request->send(400); - delete newBuffer; - return; - } - - ThingActionObject *obj = device->requestAction(newBuffer); - - if (obj == nullptr) { - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - request->send(500); - delete newBuffer; - 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(); - obj->serialize(item, device->id); - String jsonStr; - serializeJson(item, jsonStr); - AsyncWebServerResponse *response = - request->beginResponse(201, "application/json", jsonStr); - request->send(response); - - b_has_body_data = false; - memset(body_data, 0, sizeof(body_data)); - - obj->start(); - } - - void handleThingEventsGet(AsyncWebServerRequest *request, +void handleThingEventsGet(AsyncWebServerRequest *request, ThingDevice *device) { if (!verifyHost(request)) { return; diff --git a/Thing.h b/Thing.h index 25a6ea3..ee539a9 100644 --- a/Thing.h +++ b/Thing.h @@ -99,8 +99,7 @@ class ThingActionObject { JsonObject data = obj.createNestedObject(name); JsonObject actionObj = actionRequest->as(); - JsonObject inner = actionObj[name]; - data["input"] = inner["input"]; + data["input"] = actionObj; data["status"] = status; data["timeRequested"] = timeRequested; @@ -126,8 +125,7 @@ class ThingActionObject { setStatus("pending"); JsonObject actionObj = actionRequest->as(); - JsonObject inner = actionObj[name]; - start_fn(inner["input"]); + start_fn(actionObj); finish(); } @@ -197,7 +195,7 @@ class ThingAction { // 2.11 Action object: A links array (An array of Link objects linking // to one or more representations of an Action resource, each with an // implied default rel=action.) - JsonArray inline_links = obj.createNestedArray("links"); + JsonArray inline_links = obj.createNestedArray("forms"); JsonObject inline_links_prop = inline_links.createNestedObject(); inline_links_prop["href"] = "/things/" + deviceId + "/actions/" + id; } @@ -297,7 +295,7 @@ class ThingItem { // 2.9 Property object: A links array (An array of Link objects linking // to one or more representations of a Property resource, each with an // implied default rel=property.) - JsonArray inline_links = obj.createNestedArray("links"); + JsonArray inline_links = obj.createNestedArray("forms"); JsonObject inline_links_prop = inline_links.createNestedObject(); inline_links_prop["href"] = "/things/" + deviceId + "/" + resourceType + "/" + id; @@ -460,8 +458,6 @@ class ThingEventObject { data["data"] = *this->getValue().string; break; } - - data["timestamp"] = timestamp; } }; @@ -696,9 +692,11 @@ class ThingDevice { } void serialize(JsonObject descr, String ip, uint16_t port) { - descr["id"] = this->id; + descr["id"] = "uri:" + this->id; descr["title"] = this->title; - descr["@context"] = "https://webthings.io/schemas"; + + JsonArray context = descr.createNestedArray("@context"); + context.add("https://www.w3.org/2019/wot/td/v1"); if (this->description != "") { descr["description"] = this->description; @@ -715,7 +713,8 @@ class ThingDevice { descr.createNestedObject("securityDefinitions"); JsonObject nosecSc = securityDefinitions.createNestedObject("nosec_sc"); nosecSc["scheme"] = "nosec"; - descr["security"] = "nosec_sc"; + JsonArray securityJson = descr.createNestedArray("security"); + securityJson.add("nosec_sc"); JsonArray typeJson = descr.createNestedArray("@type"); const char **type = this->type; @@ -724,43 +723,33 @@ class ThingDevice { type++; } - JsonArray links = descr.createNestedArray("links"); - { - JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "properties"; - links_prop["href"] = "/things/" + this->id + "/properties"; - } - - { - JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "actions"; - links_prop["href"] = "/things/" + this->id + "/actions"; - } - - { - JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "events"; - links_prop["href"] = "/things/" + this->id + "/events"; - } - -#ifndef WITHOUT_WS - { - JsonObject links_prop = links.createNestedObject(); - links_prop["rel"] = "alternate"; - - if (port != 80) { - char buffer[33]; - itoa(port, buffer, 10); - links_prop["href"] = - "ws://" + ip + ":" + buffer + "/things/" + this->id; - } else { - links_prop["href"] = "ws://" + ip + "/things/" + this->id; - } - } -#endif - ThingProperty *property = this->firstProperty; if (property != nullptr) { + JsonArray forms = descr.createNestedArray("forms"); + JsonObject forms_prop = forms.createNestedObject(); + forms_prop["rel"] = "properties"; + JsonArray context = forms_prop.createNestedArray("op"); + context.add("readallproperties"); + context.add("writeallproperties"); + forms_prop["href"] = "/things/" + this->id + "/properties"; + + + #ifndef WITHOUT_WS + { + JsonObject forms_prop = forms.createNestedObject(); + //links_prop["rel"] = "alternate"; + + if (port != 80) { + char buffer[33]; + itoa(port, buffer, 10); + forms_prop["href"] = + "ws://" + ip + ":" + buffer + "/things/" + this->id; + } else { + forms_prop["href"] = "ws://" + ip + "/things/" + this->id; + } + } + #endif + JsonObject properties = descr.createNestedObject("properties"); while (property != nullptr) { JsonObject obj = properties.createNestedObject(property->id); diff --git a/WiFi101WebThingAdapter.h b/WiFi101WebThingAdapter.h index dc0fc5a..4a2cee3 100644 --- a/WiFi101WebThingAdapter.h +++ b/WiFi101WebThingAdapter.h @@ -308,30 +308,8 @@ class WebThingAdapter { handleError(); } return; - } else if (uri == deviceBase + "/properties") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingPropertiesGet(device->firstProperty); - } else { - handleError(); - } - return; - } else if (uri == deviceBase + "/actions") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingActionsGet(device); - } else if (method == HTTP_POST) { - handleThingActionsPost(device); - } else { - handleError(); - } - return; - } else if (uri == deviceBase + "/events") { - if (method == HTTP_GET || method == HTTP_OPTIONS) { - handleThingEventsGet(device); - } else { - handleError(); - } - return; - } else { + } + } else { ThingProperty *property = device->firstProperty; while (property != nullptr) { String propertyBase = deviceBase + "/properties/" + property->id;