Development moved to Eclipse! see https://github.com/eclipse/thingweb.node-wot/
thingweb / thingweb-directory Goto Github PK
View Code? Open in Web Editor NEWW3C WoT Thing Directory implementation
License: Other
W3C WoT Thing Directory implementation
License: Other
Development moved to Eclipse! see https://github.com/eclipse/thingweb.node-wot/
The following was returned when trying to delete a TD:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
<title>Error 500 </title>
</head>
<body>
<h2>HTTP ERROR: 500</h2>
<p>Problem accessing /td/c99c005e. Reason:
<pre> org.eclipse.rdf4j.repository.RepositoryException: org.eclipse.rdf4j.sail.SailException: java.lang.OutOfMemoryError: Java heap space</pre></p>
<hr /><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.6.v20151106</a><hr/>
</body>
</html>
After installing the binary release following the instructions, localhost:8080 always gives a 500 error. Here is an example (all other URLs give the same response);
HTTP ERROR: 500
Problem accessing /api.json. Reason:
javax.servlet.http.HttpServletRequest.isAsyncStarted()Z
Powered by Jetty://
The TDs in the samples folder are not defined as in the Web Description document (https://w3c.github.io/wot-thing-description/):
Both of the following files defined a "metadata" object that is not defined anywhere in the standard document:
thingweb-directory/src/main/resources/samples/ledActuatorTD.jsonld
thingweb-directory/src/main/resources/samples/fan.jsonld
Besides, the "ledActuatorTD.jsonld" file should include its interactions inside an "interaction" array.
After registering the following TD with a successful "Created" response, the lookup as well as the direct URI under /td/ returns a groovy.lang.MissingPropertyException: No such property: @id for class: java.lang.String
500 error.
TD:
{
"id": "urn:dev:wot:siemens:unicorn",
"name": "Unicorn",
"@context": "https://w3c.github.io/wot/w3c-wot-td-context.jsonld",
"@type": "Thing",
"security": [ ],
"properties": {
"brightness": {
"type": "integer",
"minimum": 0,
"maximum": 255,
"writable": true,
"forms": [
{
"href": "http://192.168.1.23:8080/Unicorn/properties/brightness",
"mediaType": "application/json"
},
{
"href": "coap://192.168.1.23:5683/Unicorn/properties/brightness",
"mediaType": "application/json"
}
]
},
"color": {
"type": "object",
"properties": {
"r": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"g": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"b": {
"type": "integer",
"minimum": 0,
"maximum": 255
}
},
"writable": true,
"forms": [
{
"href": "http://192.168.1.23:8080/Unicorn/properties/color",
"mediaType": "application/json"
},
{
"href": "coap://192.168.1.23:5683/Unicorn/properties/color",
"mediaType": "application/json"
}
]
}
},
"actions": {
"gradient": {
"input": {
"type": "array",
"items": {
"type": "object",
"properties": {
"r": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"g": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"b": {
"type": "integer",
"minimum": 0,
"maximum": 255
}
}
},
"minItems": 2
},
"forms": [
{
"href": "http://192.168.1.23:8080/Unicorn/actions/gradient",
"mediaType": "application/json"
},
{
"href": "coap://192.168.1.23:5683/Unicorn/actions/gradient",
"mediaType": "application/json"
}
]
},
"forceColor": {
"input": {
"type": "object",
"properties": {
"r": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"g": {
"type": "integer",
"minimum": 0,
"maximum": 255
},
"b": {
"type": "integer",
"minimum": 0,
"maximum": 255
}
}
},
"forms": [
{
"href": "http://192.168.1.23:8080/Unicorn/actions/forceColor",
"mediaType": "application/json"
},
{
"href": "coap://192.168.1.23:5683/Unicorn/actions/forceColor",
"mediaType": "application/json"
}
]
},
"cancel": {
"forms": [
{
"href": "http://192.168.1.23:8080/Unicorn/actions/cancel",
"mediaType": "application/json"
},
{
"href": "coap://192.168.1.23:5683/Unicorn/actions/cancel",
"mediaType": "application/json"
}
]
}
},
"events": { },
"links": [ ]
}
Returned TDs do not follow the array convention, meaning to also wrap single values in an arrays structure, e.g.:
"@type": "Property"
Maybe we should just drop it as discussed in w3c/wot-thing-description#103 ?
Thing IDs often use URIs/URNs. When displaying them as the link to their TD, the URI should be decoded to get rid of percent encoding (urn%3A...
).
The semantic look-up query uses graph patterns, but there are no good examples on how to achieve intended results.
Please provide examples and links on how to use.
The lack of documentation renders the feature unusable for many, hence bug level issue.
I created Postman client based on Swagger documentation (api.json file) and tried to list available things (expecting empty list) and I got 405 ERROR.
(I set up version 10 according to this guideline #33)
The startup command as given does not work. It can't find the JAR file, and even if you are in the same directory as the JAR file (it's hidden down under build/libs) you need a version number. From the directory where I ran "gradle build", I used the following command to start the server:
java -jar build/libs/thingweb-directory*.jar `pwd`
Maybe (eg for security reasons) I don't want to run the service over CoAP, or over HTTP (eg just one of the two). There should be a documented way to disable each interface (perhaps by assigning a port of 0).
A workaround exists: run inside a firewall and block those ports. But it would be better to have the option to not start them at the source in the first place.
Note as well that if HTTPS (or CoAPS) is added, I may still want to run an HTTP or CoAP interface in parallel. The reason is that I may have local processes running on the same computer (eg inside the firewall) and don't want to have to fuss with certificates etc (which may be broken anyway in the case the device is temporarily offline). In this case I might open the HTTPS port to the outside but block the HTTP port using the firewall so it is only accessible to internal processes. I might also do this on a local network and block external access to HTTP using the NAT firewall.
So in the long run the system may have four separate network interfaces (CoAP, CoAPS, HTTP, HTTPS) and I would like to selectively enable and disable each one.
Currently the search APIs always return the full TD for each result. This could be a lot, especially when performing a full list.
It would be very useful (even for the default Web UI) to have some means to return a list of Things only together with the links to retrieve the full TDs.
gradle build fails (checkout from git of version 10.0.0) with the following output:
Task :directory-core:test
org.eclipse.thingweb.directory.rdf.FrameFilterTest > testFilter FAILED
java.lang.AssertionError at FrameFilterTest.groovy:25
21 tests completed, 1 failed, 3 skipped
Task :directory-core:test FAILED
FAILURE: Build failed with an exception.
There were failing tests. See the report at: file:///home/mmccool/Devel/thingweb-directory/directory-core/build/reports/tests/test/index.html
The TD returned is quite polluted with useless blank node @id
s... could be prettier.
{
"@id": "_:b0",
"@type": "Thing",
"interaction": {
"@id": "_:b1",
"@type": "Property",
"form": {
"@id": "_:b2",
"href": "coap://x.x.x.x/3303/0/5700",
"td:mediaType": "text/plain"
},
"td:name": "temperature",
"observable": "true",
"schema": {
"@id": "_:b3",
"type": "string"
},
"writable": "false"
},
"td:name": "LwM2MWoTThing"
}
Support (or document them if they already exist) options use HTTPS. This should also support specifying the path to and the names of the certificate and private key files (rather than using fixed names and locations, since they have to be managed by a different subsystem for renewal, eg certbot, and be shared by multiple web services).
There should also be options to support CoAPS, or disable CoAP, or disable HTTP.
It would also be handy to be able to choose the ports used.
Hi,
The issue is about registering TDs in the ThingWeb directory. Right now, if the TD is already registered, the operation returns a 400 response code. However, the operation does not return the URI path in this case.
In the particular case that a different node registers the same TD, the node will know that the TD is in the system but it won’t be able to access it (or modified it) since it does not know its URI path.
Thus, I would expect a 400 response code in CoAP with the URI path included. Likewise in HTTP.
Oscar
Tried to register a TD with a 60 second lifetime and it remains discoverable and accessible after several minutes
A TD registered with correct name
fields becomes
{
"@id": "_:b0",
"@type": "Thing",
"interaction": {
"@id": "_:b1",
"@type": "Property",
"form": {
"@id": "_:b2",
"href": "coap://x.x.x.x/3303/0/5700",
"td:mediaType": "text/plain"
},
"td:name": "temperature",
"observable": "true",
"schema": {
"@id": "_:b3",
"type": "string"
},
"writable": "false"
},
"td:name": "LwM2MWoTThing"
}
For some reason, the name
is prefixed with td:
.
The registered TD spec example contains:
"td:mediaType": "application/json",
"td:rel": [
"readProperty",
"writeProperty"
]
On Windows 10 machine with Java 8 installed, starting the batch file of the release delivery results in error "Input string too long". A workaround for this is to use wildcarded classpath specification: set CLASSPATH=%APP_HOME%\lib*
If accepted content type is an RDF format, an empty payload is returned.
See stack trace when accepted content type is application/td+json
:
java.lang.NullPointerException
at com.github.jsonldjava.core.JsonLdApi.filterNodes(JsonLdApi.java:1697)
at com.github.jsonldjava.core.JsonLdApi.frame(JsonLdApi.java:1402)
at com.github.jsonldjava.core.JsonLdApi.frame(JsonLdApi.java:1353)
at com.github.jsonldjava.core.JsonLdProcessor.frame(JsonLdProcessor.java:330)
at com.github.jsonldjava.core.JsonLdProcessor$frame.call(Unknown Source)
at org.eclipse.thingweb.directory.rdf.TDSerializer.writeContent(TDSerializer.groovy:113)
at org.eclipse.thingweb.directory.ResourceSerializer$writeContent$0.call(Unknown Source)
at org.eclipse.thingweb.directory.ResourceManager.get(ResourceManager.groovy:146)
at org.eclipse.thingweb.directory.servlet.RegistrationHandleServlet.doGet(RegistrationHandleServlet.java:57)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:812)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1669)
at org.eclipse.thingweb.directory.filter.ContentNegotiationFilter.doFilter(ContentNegotiationFilter.java:127)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1652)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:585)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:577)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:223)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1127)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:515)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:185)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1061)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:499)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:258)
at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555)
at java.lang.Thread.run(Thread.java:745)
When trying to update (using PUT) a TD previously created with POST via the HTTP interface, the following error is received. I am getting this with my OCF metadata bridge, where I want to update TDs "in place". As a workaround for now I will use POST/DELETE in place of PUT, but this is inelegant (and is not exactly equivalent, as it also changes the keys to the entry in the Thing Directory...).
PUT does seem to work through CoAP, so this may be a HTTP/CoAP bridge issue.
WOT-OCF-GEN-DEBUG 11409: Status: 405
WOT-OCF-GEN-DEBUG 11409: Headers: {"date":"Sun, 05 Nov 2017 22:35:45 GMT","cache-control":"must-revalidate,no-cache,no-store","content-type":"text/html;charset=iso-8859-1","content-length":"361","connection":"close","server":"Jetty(9.3.z-SNAPSHOT)"}
WOT-OCF-GEN-DEBUG 11409: Thing Directory PUT Response: 405
WOT-OCF-GEN-DEBUG 11409: Error updating TD Intel-OCF-fb6481e0-79e1-4be0-99c1-df9bcbb898a0
Body:
Problem accessing /td/a45b5e29. Reason:
HTTP method PUT is not supported by this URL
All the URLs in the base field of the jsonld examples have three slashes instead of two:
"base" : "coap:///...
instead of
"base" : "coap://...
Be explicit for us non-Java users (I had to go dig through a gradle tutorial to find out the following):
gradle build
It would also be good to document requirements, specifically the minimum version of Java needed, whether OpenJDK works, etc.
I've downloaded and started directory 0.9.0.
When upload a JSON (with type JSON-LD) the upload is succesfull.
When uploading a JSON-LD (from Thing Description specification draft Example 2 from 24. January 2019). The TD is valid, regarding thingweb playground, which is using the TD specification from 17. January 2019
{ "@context": [ "http://www.w3.org/ns/td", {"http": "http://www.w3.org/2011/http#"} ], "id": "urn:dev:wot:com:example:servient:lamp", "name": "MyLampThing", "securityDefinitions": {"basic_sc": { "scheme": "basic", "in": "header" }}, "security": ["basic_sc"], "properties": { "status": { "readOnly": false, "writeOnly": false, "observable": false, "type": "string", "forms": [{ "href": "https://mylamp.example.com/status", "http:methodName": "GET", "contentType": "application/json" }] } }, "actions": { "toggle": { "idempotent": false, "safe": false, "forms": [{ "href": "https://mylamp.example.com/toggle", "http:methodName": "POST", "contentType": "application/json" }] } }, "events": { "overheating": { "data": {"type": "string"}, "forms": [{ "href": "https://mylamp.example.com/oh", "subprotocol": "longpoll", "contentType": "application/json" }] } } }
I'm getting this error:
javax.servlet.ServletException: org.eclipse.rdf4j.rio.RDFParseException: Could not parse JSONLD
After using DELETE on a previously created TD seems to delete it from the database as the direct URL no longer works. However, if you ask for ALL the TDs using the /td root URL, the deleted TD is still shown. This seems to happen only with the HTTP interface (we checked under CoAP and the deleted TDs are NOT listed) so it's probably a caching issue (e.g. the CoAP/HTTP proxy is incorrectly caching the overall TD list).
content="text/html;charset=ISO-8859-1"/>↵<title>Error 500 </title>↵↵↵
Problem accessing /td/b7d57b02. Reason:↵
javax.servlet.ServletException: org.eclipse.rdf4j.rio.RDFParseException: Could not parse JSONLD↵
org.eclipse...
com.onto...
Hi guys,
There is an error in the function named 'get' in the class TDLookUpEPHandler. After finding a TD, the code adds a comma (line 62) after every TD.
However, in the case where there are no more TDs matching our query, the comma remains there and it is not deleted creating a malformed JSON.
The code should check in line 78, if there is a comma and remove it before adding the closing bracket ('}'). Right now, the code only omit the comma in case the TD is the last one from the list which is just one specific corner case.
Error in this line:
Thanks,
Oscar
use either the standard Eclipse.org footer template, or a footer that prominently contains a copyright notice, and the following set of links:
According to the W3C, the link field of a TD should have an array of values. However, the examples in the samples folder show an object instead. The link field should be changed from:
"link": {
"href": "val",
"mediaType": "application/json"
}
To:
"link": [{
"href": "val",
"mediaType": "application/json"
}]
In all the samples.
When registering a TD, certain fields are not stored in the thingweb directory. E.g. the created
, lastModified
and version
fields are lost and not visible when retrieving a TD. The same applies to securityDefinitions
.
I propose to keep all fields of a TD, even those which are currently unknown to the thingweb directory.
Fields in other (user-defined) namespaces are kept, however a prefix used is expanded using the information from @context
. This might be correct, but I would prefer to get the original prefixed version back on retrieval.
We might point out that using PUT on a registered TD location with an empty payload refreshes the lifetime of the TD on the server, without changing the registered TD.
A good way to manage TD lifetime is to set up your registration client to periodically refresh the lifetime of all currently exposed thing TDs by sending a PUT to each TD location e.g. every 300 seconds.
Then, set the lifetime to something greater, like 600 seconds (?lt=600)
If the server dies or shuts down, the registration will eventually time out.
It's a good idea to track your TDs and delete them when you're shutting down the server also.
Hi,
we have got an error message when creating (using POST with the payload containing the content of the TemperatureSensorTD.jsonld found in the "samples" directory) the TemperatureSensorTD. Here is the begining of the payload:
{
"@context": [
"http://w3c.github.io/wot/w3c-wot-td-context.jsonld",
{
"saref": "http://uri.etsi.org/m2m/saref#",
"Sensor": "saref:Sensor",
"Temperature": "saref:Temperature",
"unit": "saref:isMeasuredIn",
"celsius": "http://www.wurvoc.org/vocabularies/om-1.8/degree_Celsius"
}
],
"@type": "Sensor",
"name": "myTempSensor5",
"base" : "coap:///www.example.com:5687/temp",
"interaction": [
{
Here is the error message:
<title>Error 500 </title>Problem accessing /td. Reason:
<pre> javax.servlet.ServletException: No instance of td:Thing found in the RDF payload</pre>
</p>
<hr />
<a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.6.v20151106</a>
<hr/>
</body>
when replacing the line "@type": "Sensor",
with :
"@type": ["Thing", "Sensor"]
Or
"@type": ["Thing"]
(found in other TD json files)
It works
We also noticed that the description of the thing (using the GET method) is slimmer than the description we provided (the payload of the POST method)
Any idea why?
When a name conflict occur in a TD, the method TDTransform.asJsonLd11ForType()
runs into an infinite loop. E.g. (conflictingName
used twice):
{
"id": "tag:something",
"properties":
"conflictingName": {
"type": "object",
"properties": {
"conflictingName": {
"type": "string"
}
}
}
}
The IoT REST API Server, used by OCF to convert OCF resources from CoAP to HTTP, also wants to bind port 5683 for CoAP services. Trying to start the thing directory on the same computer an iot-rest-api-server is also running causes an error when the thing directory tries to bind the same port. This is non-fatal (the http server still comes up) but is problematic, especially if both the thing directory and the iot-rest-api-server are started automatically (in which case there would be a race condition on who can grab the port first...).
As a workaround, the COAP_PORT property in Californium.properties
can be changed to avoid a conflict (I changed mine to 5684).
COAP_PORT=5684
[EDIT: See below, this a poor choice, as it conflicts with COAPS. 15683 is what I am trying to use now.]
Of course this may cause issues with devices looking for CoAP resource directories in a certain place... to discuss.
As a related issue, gateways are often (should be) running firewalls. You may have to explictly open the relevant ports to make the thing directory service available locally to other devices. I used the following, (similar to what is described in the iot-rest-api-server documentation) to open my (re-defined) CoAP port:
sudo iptables -A INPUT -p udp --dport 5684 -j ACCEPT
The default HTTP ports don't conflict since iot-rest-api-server uses 8000 by default (for HTTPS too) and the thing directory uses 8080.
Writing URI queries is quite tedious. Thus, it would be better, when also a POST (and CoAP FETCH) would be allowed to the semantic look-up resource with a full SPARQL query in the request body.
The Directory Web frontend is very nice. Unfortunately, the XHR object does not have an error handler that would inform about errors such as the (limited..) 500 response when the TD is somehow incorrect.
Since the user cannot know what is going wrong and people tried reloading the frontend and sending again, I classify this as a bug.
The assumption should be that the custom context does not include any mapping for the TD vocab, in which case parsing is unambiguous.
I want this to start as a service whenever the gateway reboots. To get this to work some specific settings are needed. It would be useful to include a systemd service file in the distribution and some instructions on how to install it. I'm using the following but it may or may not have all the things needed (for example, cleanup of the db on shutdown, restart on crash, etc):
[Unit]
Description=Thing Directory
Requires=network.target
After=network.target
[Service]
#Restart=always
#RestartSec=20
User=thingdirectory
ExecStart=/usr/bin/java -jar /opt/thingweb-directory/build/libs/thingweb-directory-0.7.jar -c 15683 -h 8080 -d /opt/thingweb-directory/db -l /opt/thingweb-directory/Lucene /opt/thingweb-directory
[Install]
WantedBy=multi-user.target
Note I run this with an account with normal user privileges created for the purpose. To install, copy the above to /etc/systemd/system/thing-directory.service and invoke
sudo systemctl enable thing-directory.service
sudo systemctl start thing-directory.service
Also, the following commands are useful for monitoring the service:
sudo systemctl status thing-directory
sudo journalctl -u thing-directory.service
And for shutting it down/turning off automatic startup on boot:
sudo systemctl stop thing-directory.service
sudo systemctl disable thing-directory.service
~
After deleting a TD using a HTTP DELETE request, the TD does no longer show up in the query interface. However when I try to upload a new TD with the same ID as the deleted one I get a 204 response, which typically occurs when the id already exists.
So uploading a new version of a thing using this approach seems not to be possible.
I created Postman client based on Swagger documentation (api.json file) and tried to register new thing. I got 500 ERROR (Problem accessing /td).
(I set up version 10 according to this guideline #33)
This is the thing that I want to register:
{
"name":"My Lamp",
"type": "alien-thing",
"description": "A web connected lamp",
"properties": {
"on": {
"type": "boolean",
"description": "Whether the lamp is turned on",
"href": "/things/lamp/properties/on"
},
"brightness" : {
"type": "number",
"description": "The level of light from 0-100",
"minimum" : 0,
"maximum" : 100,
"href": "/things/lamp/properties/brightness"
}
},
"actions": {
"toggle": {
"description": "Toggle the lamp on and off"
}
},
"events": {
"overheating": {
"description": "The lamp has exceeded its safe operating temperature"
}
},
"links": {
"properties": "/thing/lamp/properties",
"actions": "/things/lamp/actions",
"events": "/things/lamp/events"
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.