Skip to content

Commit 3b5d350

Browse files
committed
fixup! Implement ExposedThing functionality
1 parent ac13ae0 commit 3b5d350

File tree

4 files changed

+106
-16
lines changed

4 files changed

+106
-16
lines changed

lib/src/binding_http/http_server.dart

+16-4
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ final class HttpServer implements ProtocolServer {
103103
switch (affordanceValue) {
104104
// TODO: Refactor
105105
// TODO: Handle values from protocol bindings
106-
case Property(:final readOnly, :final writeOnly):
106+
case Property(:final readOnly, :final writeOnly, :final observable):
107107
if (!writeOnly) {
108108
const operationType = OperationType.readproperty;
109109
final methodName = operationType.defaultHttpMethod;
@@ -161,7 +161,15 @@ final class HttpServer implements ProtocolServer {
161161
),
162162
);
163163
}
164-
// TODO: Handle observe
164+
165+
if (observable) {
166+
const _ = [
167+
OperationType.observeproperty,
168+
OperationType.unobserveproperty,
169+
];
170+
171+
// TODO: Implement some kind of event mechanism (e.g., longpolling)
172+
}
165173
case Action():
166174
const operationType = OperationType.invokeaction;
167175
final methodName = operationType.defaultHttpMethod;
@@ -193,8 +201,12 @@ final class HttpServer implements ProtocolServer {
193201
);
194202

195203
case Event():
196-
// TODO: Implement
197-
continue;
204+
const _ = [
205+
OperationType.subscribeevent,
206+
OperationType.unsubscribeevent,
207+
];
208+
209+
// TODO: Implement some kind of event mechanism (e.g., longpolling)
198210
}
199211
}
200212

lib/src/core/implementation/exposed_thing.dart

+70-8
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
4444
final Map<String, scripting_api.EventSubscriptionHandler>
4545
_eventUnsubscribeHandlers = {};
4646

47+
final Map<String, ContentListener> _propertyChangeListeners = {};
48+
49+
final Map<String, ContentListener> _eventListeners = {};
50+
4751
Property _obtainProperty(String name) {
4852
final property = thingDescription.properties?[name];
4953

@@ -57,6 +61,19 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
5761
return property;
5862
}
5963

64+
Event _obtainEvent(String name) {
65+
final event = thingDescription.events?[name];
66+
67+
if (event == null) {
68+
throw ArgumentError(
69+
"Event $name does not exist in ExposedThing "
70+
"with title ${thingDescription.title}.",
71+
);
72+
}
73+
74+
return event;
75+
}
76+
6077
void _checkReadableProperty(String name) {
6178
final property = _obtainProperty(name);
6279

@@ -85,9 +102,32 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
85102
}
86103

87104
@override
88-
Future<void> emitPropertyChange(String name) {
89-
// TODO(JKRhb): implement emitPropertyChange
90-
throw UnimplementedError();
105+
Future<void> emitPropertyChange(
106+
String name, [
107+
String contentType = "application/json",
108+
]) async {
109+
final property = _obtainProperty(name);
110+
111+
final readHandler = _propertyReadHandlers[name];
112+
113+
// TODO: Does this need to be a ProtocolListenerRegistry?
114+
final propertyChangeHandler = _propertyChangeListeners[name];
115+
116+
// TODO: Do we need to throw an error here?
117+
if (readHandler == null || propertyChangeHandler == null) {
118+
return;
119+
}
120+
121+
final interactionInput = await readHandler();
122+
123+
final content = Content.fromInteractionInput(
124+
interactionInput,
125+
contentType,
126+
_servient.contentSerdes,
127+
property,
128+
);
129+
130+
propertyChangeHandler(content);
91131
}
92132

93133
@override
@@ -96,9 +136,27 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
96136
}
97137

98138
@override
99-
Future<void> emitEvent(String name, Object? data) {
100-
// TODO(JKRhb): implement emitEvent
101-
throw UnimplementedError();
139+
Future<void> emitEvent(
140+
String name,
141+
scripting_api.InteractionInput data, [
142+
String contentType = "application/json",
143+
]) async {
144+
final event = _obtainEvent(name);
145+
146+
final eventListener = _eventListeners[name];
147+
148+
if (eventListener == null) {
149+
return;
150+
}
151+
152+
final content = Content.fromInteractionInput(
153+
data,
154+
contentType,
155+
_servient.contentSerdes,
156+
event.data,
157+
);
158+
159+
eventListener(content);
102160
}
103161

104162
@override
@@ -343,7 +401,8 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
343401

344402
@override
345403
Future<void> handleObserveProperty(
346-
String propertyName, {
404+
String propertyName,
405+
ContentListener contentListener, {
347406
int? formIndex,
348407
Map<String, Object>? uriVariables,
349408
Object? data,
@@ -356,6 +415,8 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
356415
);
357416
}
358417

418+
_propertyChangeListeners[propertyName] = contentListener;
419+
359420
await observeHandler(
360421
data: data,
361422
uriVariables: uriVariables,
@@ -387,7 +448,8 @@ class ExposedThing implements scripting_api.ExposedThing, ExposableThing {
387448

388449
@override
389450
Future<void> handleSubscribeEvent(
390-
String eventName, {
451+
String eventName,
452+
ContentListener contentListener, {
391453
int? formIndex,
392454
Map<String, Object>? uriVariables,
393455
Object? data,

lib/src/core/protocol_interfaces/exposable_thing.dart

+7-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import "../implementation.dart";
1010
///
1111
typedef PropertyContentMap = Map<String, Content>;
1212

13+
///
14+
typedef ContentListener = void Function(Content content);
15+
1316
/// Interface that allows ProtocolServers to interact with ExposedThings.
1417
// TODO: This needs a better name
1518
abstract interface class ExposableThing {
@@ -58,7 +61,8 @@ abstract interface class ExposableThing {
5861

5962
/// Handles an `observeproperty` operation triggered by a TD consumer.
6063
Future<void> handleObserveProperty(
61-
String eventName, {
64+
String eventName,
65+
ContentListener contentListener, {
6266
int? formIndex,
6367
Map<String, Object>? uriVariables,
6468
Object? data,
@@ -83,7 +87,8 @@ abstract interface class ExposableThing {
8387

8488
/// Handles a `subscribeevent` operation triggered by a TD consumer.
8589
Future<void> handleSubscribeEvent(
86-
String eventName, {
90+
String eventName,
91+
ContentListener contentListener, {
8792
int? formIndex,
8893
Map<String, Object>? uriVariables,
8994
Object? data,

lib/src/core/scripting_api/exposed_thing.dart

+13-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
//
55
// SPDX-License-Identifier: BSD-3-Clause
66

7+
import "package:meta/meta.dart";
8+
79
import "../definitions.dart";
810
import "interaction_input.dart";
911
import "interaction_output.dart";
@@ -88,7 +90,11 @@ abstract interface class ExposedThing {
8890

8991
/// Informs all subscribers about the change of the property with the given
9092
/// [name].
91-
Future<void> emitPropertyChange(String name);
93+
@experimental
94+
Future<void> emitPropertyChange(
95+
String name, [
96+
String contentType = "application/json",
97+
]);
9298

9399
/// Assigns a [handler] function to an action with a given [name].
94100
///
@@ -115,5 +121,10 @@ abstract interface class ExposedThing {
115121
/// occurred.
116122
///
117123
/// You can provide (optional) input [data] that is emitted with the event.
118-
Future<void> emitEvent(String name, InteractionInput data);
124+
@experimental
125+
Future<void> emitEvent(
126+
String name,
127+
InteractionInput data, [
128+
String contentType = "application/json",
129+
]);
119130
}

0 commit comments

Comments
 (0)