Skip to content

Commit

Permalink
merge: 'discovery-redesign' into 'main'
Browse files Browse the repository at this point in the history
Rework Discovery API

See merge request namib-master/libraries/dart_wot!26
  • Loading branch information
JKRhb committed Feb 10, 2022
2 parents 00f525b + bfd81e7 commit 0e843de
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 30 deletions.
25 changes: 12 additions & 13 deletions example/dart_wot_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,19 +112,18 @@ Future<void> main() async {

await consumedThing.readProperty("test");

Future<void> handleThingInteraction(ThingDescription thingDescription) async {
final consumedThing = await wot.consume(thingDescription);
print("The title of the fetched TD is ${consumedThing.title}.");
print("Done!");
final thingDiscovery = wot.discover(ThingFilter(
"https://raw.githubusercontent.com/w3c/wot-testing"
"/b07fa6124bca7796e6ca752a3640fac264d3bcbc/events/2021.03.Online/TDs"
"/Oracle/oracle-Festo_Shared.td.jsonld",
DiscoveryMethod.direct));

exit(0);
}
final discoveredThingDescription = await thingDiscovery.next();
thingDiscovery.stop();
final consumedDiscoveredThing = await wot.consume(discoveredThingDescription);

print("The title of the fetched TD is ${consumedDiscoveredThing.title}.");
print("Done!");

wot.discover(
handleThingInteraction,
ThingFilter(
"https://raw.githubusercontent.com/w3c/wot-testing"
"/b07fa6124bca7796e6ca752a3640fac264d3bcbc/events/2021.03.Online/TDs"
"/Oracle/oracle-Festo_Shared.td.jsonld",
DiscoveryMethod.direct));
exit(0);
}
43 changes: 38 additions & 5 deletions lib/src/core/thing_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import 'dart:async';

import '../../scripting_api.dart' as scripting_api;
import '../definitions/form.dart';
import '../definitions/thing_description.dart';
Expand Down Expand Up @@ -40,17 +42,25 @@ class ThingDiscovery implements scripting_api.ThingDiscovery {

final Servient _servient;

final scripting_api.DiscoveryListener _callback;
// This linting issue should be a false positive.
// ignore: close_sinks
StreamController<ThingDescription>? _controller;

StreamIterator<ThingDescription>? _streamIterator;

/// Creates a new [ThingDiscovery] object with a given [thingFilter].
ThingDiscovery(this._callback, this.thingFilter, this._servient);
ThingDiscovery(this.thingFilter, this._servient);

@override
Future<void> start() async {
final thingFilter = this.thingFilter;
_controller = StreamController();
_streamIterator = StreamIterator(_controller!.stream);

if (thingFilter == null) {
throw ArgumentError();
// TODO(JKRhb): This has to be revisited once the specification has been
// updated and the thingFilter can actually be unset.
throw ArgumentError("thingFilter can't be null!");
}
_active = true;

Expand All @@ -67,10 +77,15 @@ class ThingDiscovery implements scripting_api.ThingDiscovery {

@override
void stop() {
_controller?.sink.close();
_active = false;
}

Future<void> _discoverDirectly(String? uri) async {
final controller = _controller;
if (controller == null) {
throw StateError("ThingDiscovery is not active!");
}
if (uri == null) {
throw ArgumentError();
}
Expand All @@ -84,9 +99,11 @@ class ThingDiscovery implements scripting_api.ThingDiscovery {
final value = await _servient.contentSerdes.contentToValue(content, null);

if (value is Map<String, dynamic>) {
_callback(ThingDescription.fromJson(value));
final thingDescription = ThingDescription.fromJson(value);
_done = true; // TODO(JKRhb): Check if done should be set here
_active = false;
_done = true;
controller.sink.add(thingDescription);
await controller.sink.close();
return;
}

Expand All @@ -98,4 +115,20 @@ class ThingDiscovery implements scripting_api.ThingDiscovery {
throw error;
}
}

@override
Future<ThingDescription> next() async {
final streamIterator = _streamIterator;
if (streamIterator == null) {
throw StateError("ThingDiscovery has not been started yet!");
}
final hasNext = await streamIterator.moveNext();
if (!active && !hasNext) {
_done = true;
} else if (hasNext) {
return streamIterator.current;
}
// TODO(JKRhb): Revisit error message
throw StateError("ThingDiscovery has already been stopped!");
}
}
6 changes: 3 additions & 3 deletions lib/src/core/wot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class WoT implements scripting_api.WoT {

/// Discovers [ThingDescription]s matching a given [filter].
@override
ThingDiscovery discover(scripting_api.DiscoveryListener callback,
[scripting_api.ThingFilter? filter]) {
return ThingDiscovery(callback, filter, _servient)..start();
ThingDiscovery discover([scripting_api.ThingFilter? filter]) {
// TODO(JKRhb): Decide if the user should call the start method.
return ThingDiscovery(filter, _servient)..start();
}
}
6 changes: 5 additions & 1 deletion lib/src/scripting_api/discovery/thing_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
//
// SPDX-License-Identifier: BSD-3-Clause

import '../../definitions/thing_description.dart';
import 'thing_filter.dart';

/// Interface
/// Provides the properties and methods controlling the discovery process.
abstract class ThingDiscovery {
/// The [thingFilter] that is applied during the discovery process.
ThingFilter? get thingFilter;
Expand All @@ -25,4 +26,7 @@ abstract class ThingDiscovery {

/// Stops the discovery process.
void stop();

/// Provides the next discovered [ThingDescription] object.
Future<ThingDescription> next();
}
4 changes: 0 additions & 4 deletions lib/src/scripting_api/types.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,3 @@ typedef PropertyWriteMap = Map<String, InteractionInput>;
/// Represents a Partial TD as described in the
/// [WoT Architecture](https://w3c.github.io/wot-architecture/#dfn-partial-td).
typedef ExposedThingInit = Map<String, dynamic>;

/// User provided callback that is given an argument of type [ThingDescription]
/// and is used for handling discovered Thing Descriptions.
typedef DiscoveryListener = void Function(ThingDescription thingDescription);
8 changes: 4 additions & 4 deletions lib/src/scripting_api/wot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ abstract class WoT {
/// based on the underlying impementation.
Future<ExposedThing> produce(ExposedThingInit exposedThingInit);

/// Discovers [ThingDescription]s, which are passed to a [callback] function
/// upon retrieval.
/// Discovers [ThingDescription]s which can be obtained by calling `next()`
/// on the returned [ThingDiscovery] object.
///
/// As this part of the Scripting API specification is still in development,
/// this method's implementation is in an experimental state and does not
/// conform to the specification's latest version.
Expand All @@ -49,6 +50,5 @@ abstract class WoT {
/// The [ThingDiscovery] object that is returned by this function can be used
/// for stopping the Discovery process and retrieving information about its
/// current state (i. e. whether it is still `active` or already `done`).
ThingDiscovery discover(DiscoveryListener callback,
[ThingFilter? thingFilter]);
ThingDiscovery discover([ThingFilter? thingFilter]);
}

0 comments on commit 0e843de

Please sign in to comment.