From 5a2c540a1c56b9dc811621e8a7c6d01b583a740a Mon Sep 17 00:00:00 2001 From: fatadel Date: Sun, 21 Mar 2021 00:08:00 +0100 Subject: [PATCH 1/5] feat: rename links => forms --- webthing/property.py | 6 +++--- webthing/server.py | 4 ++-- webthing/thing.py | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/webthing/property.py b/webthing/property.py index ef7c049..3cbd017 100644 --- a/webthing/property.py +++ b/webthing/property.py @@ -53,10 +53,10 @@ def as_property_description(self): """ description = deepcopy(self.metadata) - if 'links' not in description: - description['links'] = [] + if 'forms' not in description: + description['forms'] = [] - description['links'].append( + description['forms'].append( { 'rel': 'property', 'href': self.href_prefix + self.href, diff --git a/webthing/server.py b/webthing/server.py index 9e7edae..95bb711 100644 --- a/webthing/server.py +++ b/webthing/server.py @@ -151,7 +151,7 @@ def get(self): for thing in self.things.get_things(): description = thing.as_thing_description() description['href'] = thing.get_href() - description['links'].append({ + description['forms'].append({ 'rel': 'alternate', 'href': '{}{}'.format(ws_href, thing.get_href()), }) @@ -243,7 +243,7 @@ def get(self, thing_id='0'): ) description = self.thing.as_thing_description() - description['links'].append({ + description['forms'].append({ 'rel': 'alternate', 'href': '{}{}'.format(ws_href, self.thing.get_href()), }) diff --git a/webthing/thing.py b/webthing/thing.py index d87f922..d3b427d 100644 --- a/webthing/thing.py +++ b/webthing/thing.py @@ -46,7 +46,7 @@ def as_thing_description(self): 'properties': self.get_property_descriptions(), 'actions': {}, 'events': {}, - 'links': [ + 'forms': [ { 'rel': 'properties', 'href': '{}/properties'.format(self.href_prefix), @@ -64,7 +64,7 @@ def as_thing_description(self): for name, action in self.available_actions.items(): thing['actions'][name] = action['metadata'] - thing['actions'][name]['links'] = [ + thing['actions'][name]['forms'] = [ { 'rel': 'action', 'href': '{}/actions/{}'.format(self.href_prefix, name), @@ -73,7 +73,7 @@ def as_thing_description(self): for name, event in self.available_events.items(): thing['events'][name] = event['metadata'] - thing['events'][name]['links'] = [ + thing['events'][name]['forms'] = [ { 'rel': 'event', 'href': '{}/events/{}'.format(self.href_prefix, name), @@ -81,7 +81,7 @@ def as_thing_description(self): ] if self.ui_href is not None: - thing['links'].append({ + thing['forms'].append({ 'rel': 'alternate', 'mediaType': 'text/html', 'href': self.ui_href, From 8bde403f72b61e9042d579ae7c5bab1814a6d52a Mon Sep 17 00:00:00 2001 From: fatadel Date: Sun, 21 Mar 2021 02:50:07 +0100 Subject: [PATCH 2/5] feat: rename mediaType => type --- webthing/thing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webthing/thing.py b/webthing/thing.py index d3b427d..9e9e0b5 100644 --- a/webthing/thing.py +++ b/webthing/thing.py @@ -83,7 +83,7 @@ def as_thing_description(self): if self.ui_href is not None: thing['forms'].append({ 'rel': 'alternate', - 'mediaType': 'text/html', + 'type': 'text/html', 'href': self.ui_href, }) From 055e5cce1e875f20c9482f95cb37b8d2dcf59232 Mon Sep 17 00:00:00 2001 From: fatadel Date: Sun, 21 Mar 2021 16:50:15 +0100 Subject: [PATCH 3/5] feat: remove object wrappers for Property and Action --- webthing/server.py | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/webthing/server.py b/webthing/server.py index 95bb711..d79662c 100644 --- a/webthing/server.py +++ b/webthing/server.py @@ -437,9 +437,7 @@ def get(self, thing_id='0', property_name=None): if thing.has_property(property_name): self.set_header('Content-Type', 'application/json') - self.write(json.dumps({ - property_name: thing.get_property(property_name), - })) + self.write(json.dumps(thing.get_property(property_name))) else: self.set_status(404) @@ -456,32 +454,26 @@ def put(self, thing_id='0', property_name=None): return try: - args = json.loads(self.request.body.decode()) + value = json.loads(self.request.body.decode()) except ValueError: self.set_status(400) return - if property_name not in args: - self.set_status(400) - return - if thing.has_property(property_name): try: - thing.set_property(property_name, args[property_name]) + thing.set_property(property_name, value) except PropertyError: self.set_status(400) return self.set_header('Content-Type', 'application/json') - self.write(json.dumps({ - property_name: thing.get_property(property_name), - })) + self.write(json.dumps(thing.get_property(property_name))) else: self.set_status(404) class ActionsHandler(BaseHandler): - """Handle a request to /actions.""" + """Handle a request to /actions.""" # TODO: Should this feature be removed? def get(self, thing_id='0'): """ @@ -572,24 +564,14 @@ def post(self, thing_id='0', action_name=None): return try: - message = json.loads(self.request.body.decode()) + input_ = json.loads(self.request.body.decode()) except ValueError: self.set_status(400) return - keys = list(message.keys()) - if len(keys) != 1: - self.set_status(400) - return - - if keys[0] != action_name: - self.set_status(400) - return - - action_params = message[action_name] - input_ = None - if 'input' in action_params: - input_ = action_params['input'] + # Allow payloads wrapped inside `value` field + if 'value' in input_: + input_ = input_['value'] action = thing.perform_action(action_name, input_) if action: @@ -608,7 +590,7 @@ def post(self, thing_id='0', action_name=None): class ActionIDHandler(BaseHandler): - """Handle a request to /actions//.""" + """Handle a request to /actions//.""" # TODO: Should this feature be removed? def get(self, thing_id='0', action_name=None, action_id=None): """ From b79f7c1a96a3cb9e2c14a3fdb79dfe6d4789f2ef Mon Sep 17 00:00:00 2001 From: fatadel Date: Sun, 21 Mar 2021 19:55:24 +0100 Subject: [PATCH 4/5] feat: remove rel and add op for Property --- webthing/property.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/webthing/property.py b/webthing/property.py index 3cbd017..b4f7a37 100644 --- a/webthing/property.py +++ b/webthing/property.py @@ -56,9 +56,17 @@ def as_property_description(self): if 'forms' not in description: description['forms'] = [] + # TODO: The assumption is that all properties are at least readable - but that's probably not true + op = ['readproperty'] + if not self.metadata.get('readOnly'): + op.append('writeproperty') + + if self.metadata.get('observable'): + op.extend(('observeproperty', 'unobserveproperty')) + description['forms'].append( { - 'rel': 'property', + 'op': op, 'href': self.href_prefix + self.href, } ) From e1a8ec0ecfd26ff3fceffe10d46a396f62a0f1d2 Mon Sep 17 00:00:00 2001 From: fatadel Date: Sun, 21 Mar 2021 20:04:57 +0100 Subject: [PATCH 5/5] feat: remove rel and add op for Action and Event --- webthing/thing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webthing/thing.py b/webthing/thing.py index 9e9e0b5..9c4a777 100644 --- a/webthing/thing.py +++ b/webthing/thing.py @@ -66,7 +66,7 @@ def as_thing_description(self): thing['actions'][name] = action['metadata'] thing['actions'][name]['forms'] = [ { - 'rel': 'action', + 'op': ['invokeaction'], 'href': '{}/actions/{}'.format(self.href_prefix, name), }, ] @@ -75,7 +75,7 @@ def as_thing_description(self): thing['events'][name] = event['metadata'] thing['events'][name]['forms'] = [ { - 'rel': 'event', + 'op': ['subscribeevent', 'unsubscribeevent'], 'href': '{}/events/{}'.format(self.href_prefix, name), }, ]