Skip to content

Commit 55e197c

Browse files
committed
fix(coap-server): add missing cov:observe subprotocol
1 parent 9d04652 commit 55e197c

2 files changed

Lines changed: 103 additions & 15 deletions

File tree

packages/binding-coap/src/coap-server.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import { MdnsIntroducer } from "./mdns-introducer";
3535
import { PropertyElement, DataSchema, ActionElement, EventElement } from "wot-thing-description-types";
3636
import { CoapServerConfig } from "./coap";
3737
import { DataSchemaValue } from "wot-typescript-definitions";
38+
import { filterPropertyObserveOperations, getPropertyOpValues } from "./util";
3839

3940
const { debug, warn, info, error } = createLoggers("binding-coap", "coap-server");
4041

@@ -233,27 +234,42 @@ export default class CoapServer implements ProtocolServer {
233234
private addFormToAffordance(form: TD.Form, affordance: AffordanceElement): void {
234235
const affordanceForms = affordance.forms;
235236
if (affordanceForms == null) {
236-
affordance.forms ??= [form];
237+
affordance.forms = [form];
237238
} else {
238239
affordanceForms.push(form);
239240
}
240241
}
241242

242243
private fillInPropertyBindingData(thing: ExposedThing, base: string, offeredMediaType: string) {
243244
for (const [propertyName, property] of Object.entries(thing.properties)) {
244-
const opValues = ProtocolHelpers.getPropertyOpValues(property);
245-
const form = this.createAffordanceForm(
246-
base,
247-
this.PROPERTY_DIR,
248-
offeredMediaType,
249-
opValues,
250-
thing.uriVariables,
251-
propertyName,
252-
property.uriVariables
253-
);
245+
const [readWriteOpValues, observeOpValues] = getPropertyOpValues(property);
246+
for (const formOpValues of [observeOpValues, readWriteOpValues]) {
247+
if (formOpValues.length === 0) {
248+
continue;
249+
}
254250

255-
this.addFormToAffordance(form, property);
256-
this.logHrefAssignment(form, "Property", propertyName);
251+
let subprotocol: string | undefined;
252+
253+
const observeOpValues = filterPropertyObserveOperations(formOpValues);
254+
255+
if (observeOpValues.length > 0) {
256+
subprotocol = "cov:observe";
257+
}
258+
259+
const form = this.createAffordanceForm(
260+
base,
261+
this.PROPERTY_DIR,
262+
offeredMediaType,
263+
formOpValues,
264+
thing.uriVariables,
265+
propertyName,
266+
property.uriVariables,
267+
subprotocol
268+
);
269+
270+
this.addFormToAffordance(form, property);
271+
this.logHrefAssignment(form, "Property", propertyName);
272+
}
257273
}
258274
}
259275

@@ -283,7 +299,8 @@ export default class CoapServer implements ProtocolServer {
283299
["subscribeevent", "unsubscribeevent"],
284300
thing.uriVariables,
285301
eventName,
286-
event.uriVariables
302+
event.uriVariables,
303+
"cov:observe"
287304
);
288305

289306
this.addFormToAffordance(form, event);
@@ -298,7 +315,8 @@ export default class CoapServer implements ProtocolServer {
298315
opValues: string | string[],
299316
thingUriVariables: PropertyElement["uriVariables"],
300317
affordanceName?: string,
301-
affordanceUriVariables?: PropertyElement["uriVariables"]
318+
affordanceUriVariables?: PropertyElement["uriVariables"],
319+
subprotocol?: string
302320
): TD.Form {
303321
const affordanceNamePattern = Helpers.updateInteractionNameWithUriVariablePattern(
304322
affordanceName ?? "",
@@ -314,6 +332,7 @@ export default class CoapServer implements ProtocolServer {
314332

315333
const form = new TD.Form(href, offeredMediaType);
316334
form.op = opValues;
335+
form.subprotocol = subprotocol;
317336

318337
return form;
319338
}

packages/binding-coap/src/util.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/********************************************************************************
2+
* Copyright (c) 2018 Contributors to the Eclipse Foundation
3+
*
4+
* See the NOTICE file(s) distributed with this work for additional
5+
* information regarding copyright ownership.
6+
*
7+
* This program and the accompanying materials are made available under the
8+
* terms of the Eclipse Public License v. 2.0 which is available at
9+
* http://www.eclipse.org/legal/epl-2.0, or the W3C Software Notice and
10+
* Document License (2015-05-13) which is available at
11+
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document.
12+
*
13+
* SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
14+
********************************************************************************/
15+
16+
import { ProtocolHelpers } from "@node-wot/core";
17+
import { PropertyElement } from "wot-thing-description-types";
18+
19+
const observeOpFilter = ["observeproperty", "unobserveproperty"];
20+
const readWriteOpFilter = ["readproperty", "writeproperty"];
21+
22+
function filterOpValues(opValues: string[], filterValues: string[]) {
23+
return opValues.filter((opValue) => filterValues.includes(opValue));
24+
}
25+
26+
/**
27+
* Convenience function to filter out the `op` values "observeproperty" and
28+
* "unobserveproperty" from a string array.
29+
*
30+
* @param opValues The `op` values to be filtered.
31+
* @returns A filtered array that might be empty.
32+
*/
33+
export function filterPropertyObserveOperations(opValues: string[]) {
34+
return filterOpValues(opValues, observeOpFilter);
35+
}
36+
37+
/**
38+
* Convenience function to filter out the `op` values "readproperty" and
39+
* "writeproperty" from a string array.
40+
*
41+
* @param opValues The `op` values to be filtered.
42+
* @returns A filtered array that might be empty.
43+
*/
44+
function filterPropertyReadWriteOperations(opValues: string[]) {
45+
return filterOpValues(opValues, readWriteOpFilter);
46+
}
47+
48+
/**
49+
* Function to (potentially) generate two arrays of `op` values: One with the
50+
* values "readproperty" and "writeproperty", and one with
51+
* "observerproperty" and "unobserveproperty".
52+
*
53+
* This CoAP-specific distinction is made to be able to generate
54+
* separate forms for the observe-related operations, where the addition
55+
* of a `subprotocol` field with a value of `cov:observe` has to be added.
56+
*
57+
* @param property The property for which the forms are going to be
58+
* generated.
59+
* @returns A tuple consisting of two op value arrays (one for read and
60+
* write operations, one for observe-related operations).
61+
*/
62+
export function getPropertyOpValues(property: PropertyElement) {
63+
const opValues = ProtocolHelpers.getPropertyOpValues(property);
64+
65+
const readWriteOpValues = filterPropertyReadWriteOperations(opValues);
66+
const observeOpValues = filterPropertyObserveOperations(opValues);
67+
68+
return [readWriteOpValues, observeOpValues];
69+
}

0 commit comments

Comments
 (0)