-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migration to W3C WoT standard #140
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above. |
||
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)); | ||
Comment on lines
-134
to
-144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this remove all the |
||
|
||
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<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); | ||
Comment on lines
-365
to
-374
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this remove support for having multiple web things per device? I would actually support that change since I never liked that feature, but it's a bit strange to only support one thing but still use If the others do not agree and this feature is kept, we should in future consider supporting the Directory Service API and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I removed that, because it produces an array as output, which isn't WoT compliant. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The resource returned from the /things endpoint doesn't need to be a valid Thing Description because it isn't a Thing Description. It's more like a directory.
There are two other options:
As I said I personally don't mind removing this feature (as long as the rest of the URL structure is cleaned up), but others may not agree. |
||
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,31 +476,19 @@ 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); | ||
delete newBuffer; | ||
return; | ||
} | ||
|
||
JsonObject newAction = newBuffer->as<JsonObject>(); | ||
|
||
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<JsonArray>(); | ||
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<JsonObject>(); | ||
|
||
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<JsonObject>(); | ||
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(); | ||
} | ||
Comment on lines
-570
to
-645
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned above, for the gateway we left the existing actions API in place so as not to remove features, and only modified the payload of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actions under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If you remove the |
||
|
||
void handleThingEventsGet(AsyncWebServerRequest *request, | ||
void handleThingEventsGet(AsyncWebServerRequest *request, | ||
ThingDevice *device) { | ||
if (!verifyHost(request)) { | ||
return; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,8 +99,7 @@ class ThingActionObject { | |
JsonObject data = obj.createNestedObject(name); | ||
|
||
JsonObject actionObj = actionRequest->as<JsonObject>(); | ||
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>(); | ||
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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I've understood correctly, you should also rename variable names from "links" to "forms". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ohh well, I guess I forgot to cherry pick that commit. Will do. |
||
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"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here, the variable names should be renamed. |
||
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; | ||
Comment on lines
-463
to
-464
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for removing the timestamp? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, it was never a real timestamp. So, I don't see any value in keeping it, if it only reflects the time since bootup or something random. I don't remember anymore. It was just not the real time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps the clock is wrong on your device, I don't know. But the timestamp is still useful for determining the order of events, even if the time is not correct. See w3c/wot-profile#100 |
||
} | ||
}; | ||
|
||
|
@@ -696,9 +692,11 @@ class ThingDevice { | |
} | ||
|
||
void serialize(JsonObject descr, String ip, uint16_t port) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok please squash commit in previous one there is no value in keeping the mistake if more changes can be squashed please do There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, in other projects it is common practice to squash everything in one commit for the feature/bugfix. I can also just follow that and squash everything together, if you want to. I am not very opinionated about this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
descr["id"] = this->id; | ||
descr["id"] = "uri:" + this->id; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So that it actually is a valid uri. The spec requires it to be a valid URI and not some random ID. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a hack and prevents users from supplying their own URI (e.g. an https:// or urn: URI) as an ID as in the current examples, which is the current intended use. If you want to ensure that ID is a valid URI then check that it's a valid URI, don't just prepend a made-up URI scheme. |
||
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"); | ||
Comment on lines
+697
to
+699
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see that you removed the We are planning to do this in the gateway too once the gateway's Thing Descriptions are fully W3C compliant, but please note that in order for web things using the webthing-arduino library to use any of the capability schemas from I suggest including both contexts in an array if webthings.io semantic annotations are used by the web thing (e.g. We could alternatively use a prefix (e.g. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thing Descriptions are not required to be valid JSON-LD, the default serialisation is plain JSON. In WebThings we just use this as a hint to the consumer and have historically not provided a JSON-LD representation of the schemas. If we want to fix that issue then the solution is not to forbid users from using the existing webthings.io schemas (which as I mentioned is a significant and necessary feature of the WebThings platform), but to make that URL return a valid JSON-LD document when the relevant Accept headers are included in a request. That's going to be a bit tricky to fix because it's currently hosted in GitHub pages. Removing this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can understand both views. https://webthings.io/schemas/ has no alternate RDF-based representation in the background, that is the reason why every JSON-LD parser would result into a fetch error. @benfrancis is right that TD can also simple be parsed with a JSON parser and the context interpretation can be done in an application specific style. However, the cleanest solution would be this one: For the future it would be great if https://webthings.io/schemas/ would be also available as RDF model. Maybe this can also be merged with iotschema.org. If there is an interest I can check if I find a student to work on that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestions @sebastiankb.
That is certainly an option. Note that currently I think it's the case that WebThings Gateway would recognise the semantic annotations if both contexts were included anonymously, but unfortunately would not recognise them if a prefix is used. Therefore this option would require implementation work on WebThings Gateway in order for web things using this library to continue to benefit from the enhanced user experience these schemas provide. It would probably be easier to just serve a JSON-LD file from this URL, but we may need to switch hosting providers in order to support HTTP content negotiation. I'm curious why JSON-LD parsers do not try to fetch prefix defined namespaces BTW?
This is definitely a long term goal. However, the webthings.io schemas are currently used by around 100 gateway add-ons and an unknown number of web things built with the WebThings Framework. Therefore it's not really possible for one person to simply "merge" the schemas and for the issue to go away since all those implementations would need to be updated too. I think what we'd need to do is add support for iotschema.org schemas (including suggesting new ones that we think are missing) to WebThings Gateway and support both schema repositories to begin with. We could then try to encourage developers to migrate to using iotschema.org over time. Note that this would require a significant amount of UI design work in addition to development, since currently every one of the 23 device capabilities, 29 property types, 4 action types and 5 event types each has its own dedicated UI design in WebThings, implemented as web components. (See the UI designs below for a taste of what's involved). It could certainly be helpful for a student to create an RDF model from the current human-readable schema repository though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I would also just see this as an interim solution until a RDF support of
OK, I will check to see who can look at it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I see. Well if that is the only goal then as I mentioned, making the webthings.io/schemas URL resolve to a valid JSON-LD resource is not actually necessary to make the Thing Descriptions exposed by this library W3C compliant. If your goal is to address the issues with this PR in order that it can land, that's really not the biggest problem in my view. The much bigger problem is the unnecessary and indiscriminate removal of all features which can't be described by a WoT Thing Description 1.0 Thing Description. That's inconsistent with the much more careful and considered approach we are taking elsewhere in the platform, which is something I've offered to discuss in more depth to ensure we are being consistent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Prefix would be fine as well, since it doesn't result in a resolve. Please correct me if I am wrong, but that is not an option as well, because you need to implement something in the Gateway, right?
Do you mean the endpoints /actions and /properties? If so, all the properties and actions are already listed in the TD itself. So, you would just duplicate the information. I mean fine with me to add it though. I don't have hard feelings about it. Or do you to always return an array with multiple TDs in it? That wouldn't be TD compliant, even not with TD 1.1 as far as I know. And implementing TDD in Arduino would really be an overkill. Can you list your must haves in order to make it mergeable? I am getting really confused, because there are so many things you mentioned. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, we just discussed that above.
We've already discussed all of this, but I will summarise it all again below. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I may have stumbled across a solution to the context issue in w3c/wot-thing-description#442 Apparently because of the issues with content negotiation it is common practice to use one URI for the ontology which resolves to a human readable resource, then a second URI with a versioned subdirectory for the JSON-LD context. On GitHub Pages it should be possible to use:
Although this means that implementations using the existing This seems like a reasonable compromise to me, so if someone wants to provide a JSON-LD context file, then we can certainly host it at |
||
|
||
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"); | ||
Comment on lines
+716
to
+717
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason for making this an array? A string should also be valid (see https://w3c.github.io/wot-thing-description/#thing). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, then I don't need to worry, if it is one of multiple security schema. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand your response. It seems this is another unnecessary change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes it easier to add another security schema. But I think I did that because of some compatibility issues. I am not sure anymore. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the Thing Description is valid and there are compatibility issues then that's surely a bug in the consumer, not the producer. |
||
|
||
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"; | ||
} | ||
Comment on lines
-734
to
-744
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the gateway we've turned these links into forms using I would at least suggest keeping the /actions endpoint using the Events are a bit trickier since there's not really a W3C compliant way to describe the current Events resource in the API which is more like an event log. For the gateway what we decided to do is to implement implement Server-Sent Events and expose those endpoints in the Thing Description instead. I would suggest doing this in webthing-arduino too, but I think in the meantime it's reasonable to remove this. That does raise the question of how you're describing the Event resources though? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I removed it, because it made the application crash when querying certain things. I don't think the Arduino Library needs to be a feature complete library with the old Mozilla WebThings. The important requirement was to migrate it to the W3C WoT TD 1.0 standard. Which I completed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm afraid that's not really your decision, it is the decision of the module owner. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You didn't answer how you are describing the Event resources in the TD. I don't know of a W3C valid way of describing the current API, see w3c/wot-thing-description#892 |
||
|
||
#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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forms don't need a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought I should keep it for compatibility with Mozilla WebThings. But I guess at that point the compatibility is already gone anyways. |
||
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"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this commented line |
||
|
||
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); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 { | ||
Comment on lines
-311
to
-334
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest at least the /properties and /actions endpoints should be kept. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let me test it. If it doesn't break anything, I am fine with it. |
||
} | ||
} else { | ||
ThingProperty *property = device->firstProperty; | ||
while (property != nullptr) { | ||
String propertyBase = deviceBase + "/properties/" + property->id; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume this is following the proposed well-known URI in the WoT Discovery specification. This is a bit risky since that is still tentative. For the gateway we opted to implement the WoT Thing Description specification first, and implement the WoT Discovery specification later once it's a bit more solid, including DNS-based discovery and the Directory Service API.
I would suggest holding back on this for now, but if you are going to start implementing parts of the WoT Discovery specification now then it might also make sense to change the mDNS service name to
_wot
which is also (tentatively) defined in that specification.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's just the path. Even if the path changes. It really isn't such a big deal to change that. Well the mDNS part for HTTP makes trouble. I don't remember the exact problem, but there are some.
I didn't wanted to touch more than really necessary to make it WoT TD 1.0 compliant. The compliance doesn't change, if it is a different URI. The WoT TD 1.0 doesn't even define where to find the TD. So, using the endpoint in the discovery spec kind of makes sense to use here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't want to make changes that are not necessary to be W3C compliant then there's no need to change the URL.
Also please note that it's not possible to make WebThings libraries WoT TD 1.0 compliant because version 1.0 lacks the necessary semantics. The goal is to make them WoT TD 1.1 compliant, since 1.1 includes several new features added to make this possible, such as new operation types.
I personally do not like the well-known URL because it's much neater for the Thing Description to be served as the root document of the API, from
/
, like an index.html for the Web of Things. I suggest that if well-known URL is implemented in the future it should be an alias, not the canonical URL of the Thing Description.You are correct that the Thing Description specification doesn't define discovery, that's what the WoT Discovery specification is for.
WebThings Gateway consumes web things created using this library using either the existing DNS-based discovery or using the "Add Thing by URL" feature where the URL is provided manually. (This is explained in the text in the README that you are proposing to remove https://github.com/WebThingsIO/webthing-arduino/blob/master/README.md).
As you hopefully know, WebThings Gateway will consume these W3C compliant web things using the new wot-adapter which has now been plugged into that "Add Thing by URL" feature of the gateway.