Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: move discovery configurations to scripting_api package #180

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions example/coap_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,19 @@ Future<void> handleThingDescription(
Future<void> main(List<String> args) async {
final servient = Servient.create(
clientFactories: [CoapClientFactory()],
discoveryConfigurations: [
DirectConfiguration(
Uri.parse("coap://plugfest.thingweb.io:5683/testthing"),
),
],
);

final wot = await servient.start();
final discoveryConfigurations = [
DirectConfiguration(
Uri.parse("coap://plugfest.thingweb.io:5683/testthing"),
),
];

// Example using for-await-loop
try {
await for (final thingDescription in wot.discover()) {
await for (final thingDescription
in wot.discover(discoveryConfigurations)) {
await handleThingDescription(wot, thingDescription);
}
print('Discovery with "await for" has finished.');
Expand All @@ -62,7 +63,7 @@ Future<void> main(List<String> args) async {
//
// Notice how the "onDone" callback is called before the result is passed
// to the handleThingDescription function.
wot.discover().listen(
wot.discover(discoveryConfigurations).listen(
(thingDescription) async {
await handleThingDescription(wot, thingDescription);
},
Expand Down
12 changes: 7 additions & 5 deletions example/coap_dns_sd_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ Future<void> main(List<String> args) async {
CoapClientFactory(),
HttpClientFactory(),
],
discoveryConfigurations: [
const DnsSdDConfiguration(protocolType: ProtocolType.udp),
],
);

final wot = await servient.start();

final discoveryConfigurations = [
const DnsSdDConfiguration(protocolType: ProtocolType.udp),
];

// Example using for-await-loop
try {
await for (final thingDescription in wot.discover()) {
await for (final thingDescription
in wot.discover(discoveryConfigurations)) {
handleThingDescription(thingDescription);
}
print('Discovery with "await for" has finished.');
Expand All @@ -40,7 +42,7 @@ Future<void> main(List<String> args) async {
//
// Notice how the "onDone" callback is called before the result is passed
// to the handleThingDescription function.
wot.discover().listen(
wot.discover(discoveryConfigurations).listen(
handleThingDescription,
onError: (error) => print("Encountered an error: $error"),
onDone: () => print('Discovery with "listen" has finished.'),
Expand Down
12 changes: 6 additions & 6 deletions example/core_link_format_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import "package:dart_wot/core.dart";
Future<void> main(List<String> args) async {
final servient = Servient.create(
clientFactories: [CoapClientFactory()],
discoveryConfigurations: [
CoreLinkFormatConfiguration(
Uri.parse("coap://plugfest.thingweb.io"),
),
],
);

final wot = await servient.start();
final discoveryConfigurations = [
CoreLinkFormatConfiguration(
Uri.parse("coap://plugfest.thingweb.io"),
),
];

await for (final thingDescription in wot.discover()) {
await for (final thingDescription in wot.discover(discoveryConfigurations)) {
print(thingDescription.title);

if (thingDescription.title != "Smart-Coffee-Machine") {
Expand Down
1 change: 0 additions & 1 deletion lib/src/core/implementation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,4 @@ export "implementation/augmented_form.dart";
export "implementation/codecs/content_codec.dart";
export "implementation/content.dart";
export "implementation/content_serdes.dart";
export "implementation/discovery/discovery_configuration.dart";
export "implementation/servient.dart" show Servient;
27 changes: 5 additions & 22 deletions lib/src/core/implementation/servient.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import "../scripting_api.dart" as scripting_api;

import "consumed_thing.dart";
import "content_serdes.dart";
import "discovery/discovery_configuration.dart";
import "exposed_thing.dart";
import "thing_discovery.dart";
import "wot.dart";
Expand All @@ -28,8 +27,7 @@ import "wot.dart";
abstract class Servient {
/// Creates a new [Servient].
///
/// The [Servient] can be pre-configured with [List]s of
/// [clientFactories] and [discoveryConfigurations].
/// The [Servient] can be pre-configured with a [List] of [clientFactories].
/// However, it is also possible to dynamically [addClientFactory]s and
/// [removeClientFactory]s at runtime.
///
Expand All @@ -40,24 +38,14 @@ abstract class Servient {
List<ProtocolClientFactory>? clientFactories,
ServerSecurityCallback? serverSecurityCallback,
ContentSerdes? contentSerdes,
List<DiscoveryConfiguration>? discoveryConfigurations,
}) {
return InternalServient(
clientFactories: clientFactories,
serverSecurityCallback: serverSecurityCallback,
contentSerdes: contentSerdes,
discoveryConfigurations: discoveryConfigurations,
);
}

/// [List] of [DiscoveryConfiguration]s that are used when calling the
/// [scripting_api.WoT.discover] method.
List<DiscoveryConfiguration> get discoveryConfigurations;

set discoveryConfigurations(
List<DiscoveryConfiguration> discoveryConfigurations,
);

/// Starts this [Servient] and returns a [scripting_api.WoT] runtime object.
///
/// The [scripting_api.WoT] runtime can be used for consuming, producing, and
Expand Down Expand Up @@ -85,9 +73,7 @@ class InternalServient implements Servient {
List<ProtocolClientFactory>? clientFactories,
ServerSecurityCallback? serverSecurityCallback,
ContentSerdes? contentSerdes,
List<DiscoveryConfiguration>? discoveryConfigurations,
}) : contentSerdes = contentSerdes ?? ContentSerdes(),
discoveryConfigurations = discoveryConfigurations ?? [],
_serverSecurityCallback = serverSecurityCallback {
for (final clientFactory in clientFactories ?? <ProtocolClientFactory>[]) {
addClientFactory(clientFactory);
Expand All @@ -100,9 +86,6 @@ class InternalServient implements Servient {

final ServerSecurityCallback? _serverSecurityCallback;

@override
List<DiscoveryConfiguration> discoveryConfigurations;

/// The [ContentSerdes] object that is used for serializing/deserializing.
final ContentSerdes contentSerdes;

Expand Down Expand Up @@ -343,15 +326,15 @@ class InternalServient implements Servient {
return thingDescription;
}

/// Perform automatic discovery using this [InternalServient]'s
/// [discoveryConfigurations].
/// Perform discovery using the passed-in [discoveryConfigurations].
///
/// A [thingFilter] can be provided to filter the discovered Thing
/// Descriptions; however, doing so currently does not have any effect yet.
ThingDiscovery discover({
ThingDiscovery discover(
List<scripting_api.DiscoveryConfiguration> discoveryConfigurations, {
scripting_api.ThingFilter? thingFilter,
}) {
return ThingDiscovery(thingFilter, this);
return ThingDiscovery(thingFilter, this, discoveryConfigurations);
}

/// Requests a [ThingDescription] from a [url].
Expand Down
38 changes: 23 additions & 15 deletions lib/src/core/implementation/thing_discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,17 @@ import "../protocol_interfaces.dart";
import "../scripting_api.dart" as scripting_api;

import "content.dart";
import "discovery/discovery_configuration.dart";
import "servient.dart";

/// Implementation of the [scripting_api.ThingDiscovery] interface.
class ThingDiscovery extends Stream<ThingDescription>
implements scripting_api.ThingDiscovery {
/// Creates a new [ThingDiscovery] object with a given [thingFilter].
ThingDiscovery(this.thingFilter, this._servient) {
ThingDiscovery(
this.thingFilter,
this._servient,
this._discoveryConfigurations,
) {
_stream = _start();
}

Expand All @@ -42,40 +45,45 @@ class ThingDiscovery extends Stream<ThingDescription>
@override
final scripting_api.ThingFilter? thingFilter;

final List<scripting_api.DiscoveryConfiguration> _discoveryConfigurations;

late final Stream<ThingDescription> _stream;

Stream<ThingDescription> _start() async* {
for (final discoveryParameter in _servient.discoveryConfigurations) {
for (final discoveryParameter in _discoveryConfigurations) {
switch (discoveryParameter) {
case DnsSdDConfiguration(
case scripting_api.DnsSdDConfiguration(
:final discoveryType,
domainName: final domain,
:final protocolType,
):
yield* _discoverUsingDnsSd(discoveryType, domain, protocolType);
case CoreLinkFormatConfiguration(
case scripting_api.CoreLinkFormatConfiguration(
:final uri,
:final discoveryType,
):
yield* _discoverWithCoreLinkFormat(uri, discoveryType);
case CoreResourceDirectoryConfiguration(
case scripting_api.CoreResourceDirectoryConfiguration(
:final uri,
:final discoveryType,
):
yield* _discoverFromCoreResourceDirectory(uri, discoveryType);
case DirectConfiguration(:final uri):
case scripting_api.DirectConfiguration(:final uri):
if (!uri.hasMulticastAddress) {
yield* Stream.fromFuture(_servient.requestThingDescription(uri));
} else {
yield* _performMulticastDiscovery(uri);
}
case ExploreDirectoryConfiguration(:final uri, :final thingFilter):
case scripting_api.ExploreDirectoryConfiguration(
:final uri,
:final thingFilter
):
final thingDiscoveryProcess = await _servient.exploreDirectory(
uri,
thingFilter: thingFilter,
);
yield* thingDiscoveryProcess;
case MqttDiscoveryConfiguration(
case scripting_api.MqttDiscoveryConfiguration(
:final brokerUri,
:final discoveryTopic,
:final expectedContentType,
Expand Down Expand Up @@ -122,9 +130,9 @@ class ThingDiscovery extends Stream<ThingDescription>
}

Stream<ThingDescription> _discoverUsingDnsSd(
DiscoveryType discoveryType,
scripting_api.DiscoveryType discoveryType,
String domainName,
ProtocolType protocolType,
scripting_api.ProtocolType protocolType,
) async* {
if (domainName != ".local") {
throw UnimplementedError(
Expand All @@ -134,7 +142,7 @@ class ThingDiscovery extends Stream<ThingDescription>

final serviceNameSegments = <String>[];

if (discoveryType == DiscoveryType.directory) {
if (discoveryType == scripting_api.DiscoveryType.directory) {
serviceNameSegments.addAll(const ["_directory", "_sub"]);
}

Expand All @@ -155,7 +163,7 @@ class ThingDiscovery extends Stream<ThingDescription>
Stream<ThingDescription> _performMdnsDiscovery(
String domainName,
String defaultUriScheme,
DiscoveryType expectedType,
scripting_api.DiscoveryType expectedType,
) async* {
final MDnsClient client = MDnsClient();
await client.start();
Expand Down Expand Up @@ -233,7 +241,7 @@ class ThingDiscovery extends Stream<ThingDescription>

Stream<ThingDescription> _discoverWithCoreLinkFormat(
Uri uri,
DiscoveryType discoveryType,
scripting_api.DiscoveryType discoveryType,
) async* {
await for (final coreWebLinks in _performCoreLinkFormatDiscovery(
uri,
Expand All @@ -246,7 +254,7 @@ class ThingDiscovery extends Stream<ThingDescription>

Stream<ThingDescription> _discoverFromCoreResourceDirectory(
Uri uri,
DiscoveryType discoveryType,
scripting_api.DiscoveryType discoveryType,
) async* {
yield* _performCoreLinkFormatDiscovery(
uri,
Expand Down
11 changes: 9 additions & 2 deletions lib/src/core/implementation/wot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import "dart:async";

import "package:meta/meta.dart";

import "../definitions.dart";
import "../scripting_api.dart" as scripting_api;
import "consumed_thing.dart";
Expand Down Expand Up @@ -39,10 +41,15 @@ class WoT implements scripting_api.WoT {
_servient.produce(init);

@override
ThingDiscovery discover({
ThingDiscovery discover(
@experimental
List<scripting_api.DiscoveryConfiguration> discoveryConfigurations, {
scripting_api.ThingFilter? thingFilter,
}) =>
_servient.discover(thingFilter: thingFilter);
_servient.discover(
discoveryConfigurations,
thingFilter: thingFilter,
);

@override
Future<ThingDescription> requestThingDescription(Uri url) =>
Expand Down
2 changes: 2 additions & 0 deletions lib/src/core/scripting_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ library scripting_api;

export "scripting_api/consumed_thing.dart";
export "scripting_api/data_schema_value.dart";
export "scripting_api/discovery/directory_payload_format.dart";
export "scripting_api/discovery/discovery_configuration.dart";
export "scripting_api/discovery/thing_discovery.dart";
export "scripting_api/discovery/thing_filter.dart";
export "scripting_api/exposed_thing.dart";
Expand Down
34 changes: 34 additions & 0 deletions lib/src/core/scripting_api/discovery/directory_payload_format.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 Contributors to the Eclipse Foundation. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
// SPDX-License-Identifier: BSD-3-Clause

/// Enumeration for specifying the value of the `format` query parameter when
/// using the `exploreDirectory` discovery method.
///
/// See [section 7.3.2.1.5] of the [WoT Discovery] specification for more
/// information.
///
/// [WoT Discovery]: https://www.w3.org/TR/2023/REC-wot-discovery-20231205
/// [section 7.3.2.1.5]: https://www.w3.org/TR/2023/REC-wot-discovery-20231205/#exploration-directory-api-things-listing
enum DirectoryPayloadFormat {
/// Indicates that an array of Thing Descriptions should be returned.
///
/// This is the default value.
array,

/// Indicates that an collection of Thing Descriptions should be returned.
collection,
;

@override
String toString() {
switch (this) {
case array:
return "array";
case collection:
return "collection";
}
}
}
Loading
Loading