Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
console.debug(`generateTD() found ${Object.keys(boundThing.events).length} Events`);
for (let eventName in boundThing.events) {
let event = boundThing.events[eventName];
// a form is generated for each address, supported protocol, and mediatype
for (let address of Helpers.getAddresses()) {
for (let type of ContentManager.getOfferedMediaTypes()) {
for (let server of servient.getServers()) {
// TODO get form directly from server, do not define URI paths here
// if server is online !==-1 assign the href information
if (server.getPort() !== -1 && server.scheme!=="mqtt") {
let href: string = server.scheme + "://" + address + ":" + server.getPort() + "/" + thing.name;
// depending on the resource pattern, uri is constructed
let newForm = new TD.Form(href + "/events/" + eventName, type);
if (server.scheme==="http") {
newForm.subProtocol = "LongPoll";
}
event.forms.push(newForm);
console.debug(`generateTD() assigns href '${href}' to Event '${eventName}'`);
}
}
}
}
// in the case of mqtt the broker URI is used within the hrefs
for (let server of servient.getServers()) {
if(server.getPort() !== -1 && server.scheme=="mqtt") {
for (let type of ContentManager.getOfferedMediaTypes()) {
try {
content = ContentSerdes.get().valueToContent(data, event.data);
} catch(err) {
console.warn(`HttpServer on port ${this.getPort()} cannot process data for Event '${eventName}: ${err.message}'`);
// subscription.unsubscribe();
thing.unsubscribeEvent(eventName);
return;
}
// send event data
console.log(`MqttBrokerServer at ${this.brokerURI} publishing to Event topic '${eventName}' `);
this.broker.publish(topic, content.body);
}
);
let href = this.brokerURI + topic;
let form = new TD.Form(href, ContentSerdes.DEFAULT);
form.op = ["subscribeevent", "unsubscribeevent"];
event.forms.push(form);
console.log(`MqttBrokerServer at ${this.brokerURI} assigns '${href}' to Event '${eventName}'`);
}
resolve();
});
}
}
}
}
// in the case of mqtt the broker URI is used within the hrefs
for (let server of servient.getServers()) {
if(server.getPort() !== -1 && server.scheme=="mqtt") {
for (let type of ContentManager.getOfferedMediaTypes()) {
// cast since MqttBrokerServer offers a getAddress
let href: string = server.scheme + "://" + server.getAddress() + ":" + server.getPort() + "/" + thing.name;
// TODO: add mqtt based vocabularies (qos, retain) to the forms
// depending on the resource pattern, uri is constructed
event.forms.push(new TD.Form(href + "/events/" + eventName, type));
console.debug(`generateTD() assigns href '${href}' to Event '${eventName}'`);
}
}
}
}
return boundThing;
}
if (!client) {
reject(new Error(`ConsumedThing '${this.getThing().name}' did not get suitable client for ${form.href}`));
} else {
console.log(`ConsumedThing '${this.getThing().name}' writing ${form.href} with '${value}'`);
let content = ContentSerdes.valueToContent(value, form.mediaType);
client.writeResource(form, content).then(() => {
resolve();
})
.catch(err => { reject(err); });
}
});
}
}
class ConsumedThingAction extends TD.ActionFragment implements WoT.ThingAction {
// functions for wrapping internal state
private getName: () => string;
private getThing: () => ConsumedThing;
constructor(name: string, thing: ConsumedThing) {
super();
// wrap internal state into functions to not be stringified in TD
this.getName = () => { return name; }
this.getThing = () => { return thing; }
}
run(parameter?: any): Promise {
return new Promise((resolve, reject) => {
let { client, form } = this.getThing().getClientFor(this.forms);
/** WoT.ThingAction interface: invoke this Action locally (async) */
public invoke(parameter?: any): Promise {
return new Promise((resolve, reject) => {
console.debug(`ExposedThing '${this.getThing().name}' has Action state of '${this.getName()}':`, this.getState());
if (this.getState().handler != null) {
console.log(`ExposedThing '${this.getThing().name}' calls registered handler for Action '${this.getName()}'`);
resolve(this.getState().handler(parameter));
} else {
reject(new Error(`ExposedThing '${this.getThing().name}' has no handler for Action '${this.getName()}'`));
}
});
}
}
class ExposedThingEvent extends TD.EventFragment implements WoT.ThingEvent, WoT.BaseSchema {
// functions for wrapping internal state
getName: () => string;
getThing: () => ExposedThing;
getState: () => EventState;
constructor(name: string, thing: ExposedThing) {
super();
// wrap internal state into functions to not be stringified
this.getName = () => { return name; }
this.getThing = () => { return thing; }
this.getState = (new class {
state: EventState = new EventState();
getInternalState = () => { return this.state };
}).getInternalState;
}
/** @inheritDoc */
setActionHandler(actionName: string, action: WoT.ActionHandler): WoT.ExposedThing {
console.log(`ExposedThing '${this.name}' setting action Handler for '${actionName}'`);
if (this.actions[actionName]) {
// in case of function instead of lambda, the handler is bound to a clean scope of the ActionState
this.actions[actionName].getState().handler = action.bind(this.actions[actionName].getState().scope);
} else {
throw Error(`ExposedThing '${this.name}' cannot set action handler for unknown '${actionName}'`);
}
return this;
}
}
class ExposedThingProperty extends TD.PropertyFragment implements WoT.ThingProperty, WoT.BaseSchema {
// functions for wrapping internal state
getName: () => string;
getThing: () => ExposedThing;
getState: () => PropertyState;
constructor(name: string, thing: ExposedThing) {
super();
// wrap internal state into functions to not be stringified in TD
this.getName = () => { return name; }
this.getThing = () => { return thing; }
this.getState = (new class {
state: PropertyState = new PropertyState();
getInternalState = () => { return this.state };
}).getInternalState;
/** notify state change */
if (this.getState().value!==value) {
this.getState().subject.next(value);
}
this.getState().value = value;
resolve();
}
});
}
public subscribe(next?: (value: any) => void, error?: (error: any) => void, complete?: () => void): Subscription {
return this.getState().subject.asObservable().subscribe(next, error, complete);
}
}
class ExposedThingAction extends TD.ActionFragment implements WoT.ThingAction {
// functions for wrapping internal state
getName: () => string;
getThing: () => ExposedThing;
getState: () => ActionState;
constructor(name: string, thing: ExposedThing) {
super();
// wrap internal state into functions to not be stringified
this.getName = () => { return name; }
this.getThing = () => { return thing; }
this.getState = (new class {
state: ActionState = new ActionState();
getInternalState = () => { return this.state };
}).getInternalState;
}
input = ContentSerdes.valueToContent(parameter, form.mediaType);
}
client.invokeResource(form, input).then((output: any) => {
// infer media type from form if not in response metadata
if (!output.mediaType) output.mediaType = form.mediaType;
let value = ContentSerdes.contentToValue(output);
resolve(value);
})
.catch(err => { reject(err); });
}
});
}
}
class ConsumedThingEvent extends TD.EventFragment implements Subscribable {
// functions for wrapping internal state
private getName: () => string;
private getThing: () => ConsumedThing;
constructor(name: string, thing: ConsumedThing) {
super();
// wrap internal state into functions to not be stringified in TD
this.getName = () => { return name; }
this.getThing = () => { return thing; }
}
public subscribe(next: ((value: any) => void), error?: (error: any) => void, complete?: () => void): Subscription {
let { client, form } = this.getThing().getClientFor(this.forms);
// return this.observablesEvent.get(name).asObservable();
// }
// onTDChange(): Observable {
// return this.observablesTDChange.asObservable();
// }
}
export interface ClientAndForm {
client: ProtocolClient
form: WoT.Form
}
class ConsumedThingProperty extends TD.PropertyFragment implements WoT.ThingProperty, WoT.BaseSchema {
// functions for wrapping internal state
private getName: () => string;
private getThing: () => ConsumedThing;
constructor(name: string, thing: ConsumedThing) {
super();
// wrap internal state into functions to not be stringified in TD
this.getName = () => { return name; }
this.getThing = () => { return thing; }
}
// get and set interface for the Property
get(): Promise {
return new Promise((resolve, reject) => {
addDefaultLanguage(thing: any) {
// add @language : "en" if no @language set
if(Array.isArray(thing["@context"])) {
let arrayContext: Array = thing["@context"];
let languageSet = false;
for (let arrayEntry of arrayContext) {
if(typeof arrayEntry == "object") {
if(arrayEntry["@language"] !== undefined) {
languageSet = true;
}
}
}
if(!languageSet) {
arrayContext.push({
"@language": TD.DEFAULT_CONTEXT_LANGUAGE
});
}
}
}