Skip to content

Commit

Permalink
Use forms instead of links in Properties, Actions, and Events
Browse files Browse the repository at this point in the history
fixes #2806
  • Loading branch information
relu91 committed Sep 29, 2021
1 parent 78423ff commit 2dfc982
Show file tree
Hide file tree
Showing 18 changed files with 22,651 additions and 223 deletions.
22,340 changes: 22,296 additions & 44 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"express-rate-limit": "^5.2.6",
"express-ws": "^4.0.0",
"find": "^0.3.0",
"gateway-addon": "^1.0.1-alpha.1",
"gateway-addon": "^2.0.0-alpha.1",
"glob-to-regexp": "^0.4.1",
"http-proxy": "^1.18.1",
"ip-regex": "^4.3.0",
Expand Down
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ export enum LogSeverity {
PROMPT = 4,
}

export enum WoTOperation {
READ_ALL_PROPERTIES_OP = 'readallproperties',
SUBSCRIBE_ALL_EVENTS_OP = 'subscribeallevents',
UNSUBSCRIBE_ALL_EVENTS_OP = 'unsubscribeallevents',
}
export interface LogMessage {
severity: LogSeverity;
message: string;
Expand Down
218 changes: 117 additions & 101 deletions src/models/thing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Event as EventSchema,
Property as PropertySchema,
Link,
Form,
} from 'gateway-addon/lib/schema';
import Action from './action';
import Event from './event';
Expand All @@ -42,6 +43,7 @@ export interface ThingDescription {
actions: Record<string, ActionSchema>;
events: Record<string, EventSchema>;
links: Link[];
forms: Form[];
floorplanVisibility: boolean;
floorplanX: number;
floorplanY: number;
Expand Down Expand Up @@ -106,6 +108,8 @@ export default class Thing extends EventEmitter {

private links: Link[];

private forms: Form[];

private iconHref: string | null;

private group_id: string | null;
Expand Down Expand Up @@ -137,6 +141,7 @@ export default class Thing extends EventEmitter {
this.events = description.events || {};
this.connected = false;
this.eventsDispatched = [];
this.forms = [];

if (description.properties) {
for (const propertyName in description.properties) {
Expand All @@ -146,50 +151,60 @@ export default class Thing extends EventEmitter {
delete property.href;
}

if (property.links) {
property.links = property.links
.filter((link) => {
return link.rel && link.rel !== 'property';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}

return link;
});
if (property.forms) {
property.forms = property.forms.map((form) => {
// TODO: WebThingsIO non-standard keyword
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return form;
});
} else {
property.links = [];
property.forms = [];
}

// Give the property a URL
property.links.push({
rel: 'property',
// Conservative approach do not remove provided forms
property.forms.push({
href: `${this.href}${Constants.PROPERTIES_PATH}/${encodeURIComponent(propertyName)}`,
});

this.properties[propertyName] = property;
}

// If there are properties, add a top level form for them
if (Object.keys(description.properties).length > 0) {
this.forms.push({
href: `${this.href}/properties`,
op: Constants.WoTOperation.READ_ALL_PROPERTIES_OP,
});
}
}

// If there are events, add a top level form for them
if (Object.keys(description.events ?? {}).length > 0) {
this.forms.push({
href: `${this.href}/events`,
op: [
Constants.WoTOperation.SUBSCRIBE_ALL_EVENTS_OP,
Constants.WoTOperation.UNSUBSCRIBE_ALL_EVENTS_OP,
],
subprotocol: 'sse',
});
}

this.floorplanVisibility = description.floorplanVisibility;
this.floorplanX = description.floorplanX;
this.floorplanY = description.floorplanY;
this.layoutIndex = description.layoutIndex;
this.selectedCapability = description.selectedCapability;
this.links = [
{
rel: 'properties',
href: `${this.href}/properties`,
},
{
rel: 'actions',
href: `${this.href}/actions`,
},
{
rel: 'events',
href: `${this.href}/events`,
},
];

const uiLink = {
Expand Down Expand Up @@ -235,26 +250,21 @@ export default class Thing extends EventEmitter {
delete action.href;
}

if (action.links) {
action.links = action.links
.filter((link) => {
return link.rel && link.rel !== 'action';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}
if (action.forms) {
action.forms = action.forms.map((form) => {
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return link;
});
return form;
});
} else {
action.links = [];
action.forms = [];
}

// Give the action a URL
action.links.push({
rel: 'action',
action.forms!.push({
href: `${this.href}${Constants.ACTIONS_PATH}/${encodeURIComponent(actionName)}`,
});
}
Expand All @@ -266,27 +276,23 @@ export default class Thing extends EventEmitter {
delete event.href;
}

if (event.links) {
event.links = event.links
.filter((link) => {
return link.rel && link.rel !== 'event';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}
if (event.forms) {
event.forms = event.forms.map((form) => {
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return link;
});
return form;
});
} else {
event.links = [];
event.forms = [];
}

// Give the event a URL
event.links.push({
rel: 'event',
event.forms.push({
href: `${this.href}${Constants.EVENTS_PATH}/${encodeURIComponent(eventName)}`,
subprotocol: 'sse',
});
}

Expand Down Expand Up @@ -584,6 +590,7 @@ export default class Thing extends EventEmitter {
actions: this.actions,
events: this.events,
links: JSON.parse(JSON.stringify(this.links)),
forms: this.forms,
floorplanVisibility: this.floorplanVisibility,
floorplanX: this.floorplanX,
floorplanY: this.floorplanY,
Expand Down Expand Up @@ -681,7 +688,7 @@ export default class Thing extends EventEmitter {

// Update description
this.description = description.description || '';

this.forms = [];
// Update properties
this.properties = {};
if (description.properties) {
Expand All @@ -692,30 +699,35 @@ export default class Thing extends EventEmitter {
delete property.href;
}

if (property.links) {
property.links = property.links
.filter((link) => {
return link.rel && link.rel !== 'property';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}

return link;
});
if (property.forms) {
property.forms = property.forms.map((form) => {
// TODO: WebThingsIO non-standard keyword
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return form;
});
} else {
property.links = [];
property.forms = [];
}

// Give the property a URL
property.links.push({
rel: 'property',
// Conservative approach do not remove provided forms
property.forms.push({
href: `${this.href}${Constants.PROPERTIES_PATH}/${encodeURIComponent(propertyName)}`,
});
this.properties[propertyName] = property;
}

// If there are properties, add a top level form for them
if (Object.keys(description.properties).length > 0) {
this.forms.push({
href: `${this.href}/properties`,
op: Constants.WoTOperation.READ_ALL_PROPERTIES_OP,
});
}
}

// Update actions
Expand All @@ -727,26 +739,21 @@ export default class Thing extends EventEmitter {
delete action.href;
}

if (action.links) {
action.links = action.links
.filter((link) => {
return link.rel && link.rel !== 'action';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}
if (action.forms) {
action.forms = action.forms.map((form) => {
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return link;
});
return form;
});
} else {
action.links = [];
action.forms = [];
}

// Give the action a URL
action.links.push({
rel: 'action',
action.forms!.push({
href: `${this.href}${Constants.ACTIONS_PATH}/${encodeURIComponent(actionName)}`,
});
}
Expand All @@ -760,27 +767,36 @@ export default class Thing extends EventEmitter {
delete event.href;
}

if (event.links) {
event.links = event.links
.filter((link) => {
return link.rel && link.rel !== 'event';
})
.map((link) => {
if (link.proxy) {
delete link.proxy;
link.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${link.href}`;
}
if (event.forms) {
event.forms = event.forms.map((form) => {
// TODO: WebThingsIO non-standard keyword
if (form.proxy) {
delete form.proxy;
form.href = `${Constants.PROXY_PATH}/${encodeURIComponent(this.id)}${form.href}`;
}

return link;
});
return form;
});
} else {
event.links = [];
event.forms = [];
}

// Give the event a URL
event.links.push({
rel: 'event',
event.forms.push({
href: `${this.href}${Constants.EVENTS_PATH}/${encodeURIComponent(eventName)}`,
subprotocol: 'sse',
});
}

// If there are events, add a top level form for them
if (Object.keys(description.events ?? {}).length > 0) {
this.forms.push({
href: `${this.href}/events`,
op: [
Constants.WoTOperation.SUBSCRIBE_ALL_EVENTS_OP,
Constants.WoTOperation.UNSUBSCRIBE_ALL_EVENTS_OP,
],
subprotocol: 'sse',
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/plugin/property-proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ export default class PropertyProxy extends Property<Any> {
if (Array.isArray(propertyDict.enum)) {
this.setEnum(propertyDict.enum);
}
if (Array.isArray(propertyDict.links)) {
this.setLinks(propertyDict.links);
if (Array.isArray(propertyDict.forms)) {
this.setForms(propertyDict.forms);
}

while (this.propertyChangedPromises.length > 0) {
Expand Down
Loading

0 comments on commit 2dfc982

Please sign in to comment.