diff --git a/example/exposed_thing/http_server.dart b/example/exposed_thing/http_server.dart index 12249cc9..31cec6c6 100644 --- a/example/exposed_thing/http_server.dart +++ b/example/exposed_thing/http_server.dart @@ -3,6 +3,8 @@ import "package:dart_wot/binding_http.dart"; import "package:dart_wot/core.dart"; +var property = "hi :)"; + void main() async { final servient = Servient.create(servers: [HttpServer(HttpConfig(port: 3000))]); @@ -25,11 +27,27 @@ void main() async { }, }); - exposedThing.setPropertyReadHandler("status", ({ - data, - formIndex, - uriVariables, - }) async { - return InteractionInput.fromString("Hi :)"); - }); + exposedThing + ..setPropertyReadHandler("status", ({ + data, + formIndex, + uriVariables, + }) async { + return InteractionInput.fromString(property); + }) + ..setPropertyWriteHandler("status", ( + interactionOutput, { + data, + formIndex, + uriVariables, + }) async { + final value = await interactionOutput.value(); + + if (value is String) { + property = value; + return; + } + + // TODO: Should an incorrect data type be handled in some way? + }); } diff --git a/lib/src/binding_http/http_server.dart b/lib/src/binding_http/http_server.dart index 911452c9..846c8322 100644 --- a/lib/src/binding_http/http_server.dart +++ b/lib/src/binding_http/http_server.dart @@ -71,17 +71,31 @@ final class HttpServer implements ProtocolServer { for (final affordance in thingDescription.properties?.entries ?? >[]) { - router.get("/$key/${affordance.key}", (request) async { - final content = await thing.handleReadProperty(affordance.key); - - return Response( - 200, - body: content.body, - headers: { - "Content-Type": content.type, - }, - ); - }); + router + ..get("/$key/${affordance.key}", (request) async { + final content = await thing.handleReadProperty(affordance.key); + + return Response( + 200, + body: content.body, + headers: { + "Content-Type": content.type, + }, + ); + }) + ..post("/$key/${affordance.key}", (request) async { + if (request is! Request) { + throw Exception(); + } + + final content = + Content(request.mimeType ?? "application/json", request.read()); + await thing.handleWriteProperty(affordance.key, content); + + return Response( + 204, + ); + }); } _routes[key] = router; diff --git a/lib/src/core/implementation/exposed_thing.dart b/lib/src/core/implementation/exposed_thing.dart index ed7b2beb..ce7623f8 100644 --- a/lib/src/core/implementation/exposed_thing.dart +++ b/lib/src/core/implementation/exposed_thing.dart @@ -10,6 +10,7 @@ import "../definitions.dart"; import "../scripting_api.dart" as scripting_api; import "content.dart"; +import "interaction_output.dart"; import "servient.dart"; /// Implementation of the [scripting_api.ExposedThing] interface. @@ -27,6 +28,9 @@ class ExposedThing implements scripting_api.ExposedThing { final Map _propertyReadHandlers = {}; + final Map _propertyWriteHandlers = + {}; + @override Future emitPropertyChange(String name) { // TODO(JKRhb): implement emitPropertyChange @@ -38,7 +42,7 @@ class ExposedThing implements scripting_api.ExposedThing { String name, scripting_api.PropertyWriteHandler handler, ) { - // TODO(JKRhb): implement setPropertyWriteHandler + _propertyWriteHandlers[name] = handler; } @override @@ -142,4 +146,45 @@ class ExposedThing implements scripting_api.ExposedThing { thingDescription.properties?[propertyName], ); } + + /// Handles a `writeproperty` operation triggered by a TD consumer. + @internal + Future handleWriteProperty( + String propertyName, + Content input, { + int? formIndex, + Map? uriVariables, + Object? data, + }) async { + final writeHandler = _propertyWriteHandlers[propertyName]; + + if (writeHandler == null) { + throw Exception( + "Write handler for property $propertyName is not defined.", + ); + } + + final Form form; + + if (formIndex == null) { + // FIXME: Returning a form does not really make sense here. + form = Form(Uri.parse("hi")); + } else { + form = thingDescription.properties?[propertyName]?.forms + .elementAtOrNull(formIndex) ?? + Form(Uri.parse("hi")); + } + + await writeHandler( + InteractionOutput( + input, + _servient.contentSerdes, + form, + thingDescription.properties?[propertyName], + ), + formIndex: formIndex, + uriVariables: uriVariables, + data: data, + ); + } }