From f93d18c14ce332ee11edb2cfb4fe69c3b06cfe2d Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Sun, 12 Feb 2017 15:25:29 +0100 Subject: [PATCH 1/5] Typings:Initial commit --- .gitignore | 7 + index.d.ts | 180 ++++++++++++++++++++++ js/high-level-client-example.ts | 51 ++++++ js/high-level-resource-creation-client.ts | 63 ++++++++ js/high-level-resource-creation-server.ts | 74 +++++++++ js/high-level-server-example.ts | 98 ++++++++++++ js/node_modules/iotivity-node/index.d.ts | 1 + package.json | 7 +- 8 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 index.d.ts create mode 100644 js/high-level-client-example.ts create mode 100644 js/high-level-resource-creation-client.ts create mode 100644 js/high-level-resource-creation-server.ts create mode 100644 js/high-level-server-example.ts create mode 120000 js/node_modules/iotivity-node/index.d.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a5ba8302 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.vscode/ +build/ +node_modules +generated/ +iotivity-installed/ +iotivity-native/ + diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..f29d2661 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,180 @@ +// Type definitions for iotivity-node 1.2.0-2 +// Project: iotivity-node +// Definitions by: Hans Bakker https://www.github.com/wind-rider + +/// + +import { EventEmitter } from "events"; + +/*~ If this module has methods, declare them as functions like so. + */ +//export function myMethod(a: string): string; +//export function myOtherMethod(a: number): number; + +/*~ You can declare types that are available via importing the module */ +export interface IPlatformInfo { + id: string; + osVersion: string; + model: string; + manufacturerName: string; + manufacturerURL: string; + manufacturerDate: Date; + platformVersion: string; + firmwareVersion: string; + supportURL: string; +} + +export interface IDeviceInfo { + url: string; + name: string; + dataModels: string[]; + coreSpecVersion: string; + uuid: string; +} + +/*~ You can declare properties of the module using const, let, or var */ +//export const myField: number; + +export var device: IDeviceInfo; +export var platform: IPlatformInfo; + +/*~ If there are types, properties, or methods inside dotted names + *~ of the module, declare them inside a 'namespace'. + */ +//export namespace server { +/*~ For example, given this definition, someone could write: + *~ import { subProp } from 'yourModule'; + *~ subProp.foo(); + *~ or + *~ import * as yourMod from 'yourModule'; + *~ yourMod.subProp.foo(); + */ +// export function foo(): void; +//} + +export const server: Server; +export const client: Client; + +export class Server { + constructor(); + + oncreate(handler: RequestHandler): Server; + register(init: IResourceInfo): Promise |any;//todo +} + +export class Request { + constructor(init?: Request); + + id?: any;// TODO + observe: boolean; + target?: ServerResource; // TODO + type: string; + data?: ServerResource|any; //TODO + + respond(data?: ServerResource | any): Promise<{}>; //TODO + respondWithError(error: string): Promise<{}>; +} + +export type RequestHandler = (request: Request) => void; + +export class ServerResource implements IResourceInfo { + constructor(); + + deviceId: string; + slow: boolean; + active: boolean; + secure: boolean; + + ontranslate(handler: RequestHandler); + onretrieve(handler: RequestHandler); + onupdate(handler: RequestHandler); + ondelete(handler: RequestHandler); + oncreate(handler: RequestHandler); + + unregister(): Promise; //TODO + notify(): Promise; + + resourcePath: string; + resourceTypes: string[]; + interfaces: string[]; + discoverable: boolean; + observable: boolean; + properties: any; +} + +export interface IResourceInfo { + deviceId?: string; + resourcePath: string; + resourceTypes: string[]; + interfaces: string[]; + discoverable?: boolean; + observable?: boolean; + properties: any; + slow?: boolean; + active?: boolean; + secure?: boolean; +} + +export class Client extends EventEmitter implements IClientEvent { + // deviceId could also be an object but this is undocumented + getDeviceInfo(deviceId: string): Promise<{}>; + getPlatformInfo(deviceId: string): Promise<{}>; + + //TODO + create(resourceInit?: IResourceInfo, target?: any): Promise; + retrieve(resourceId: IResourceInfo, listener?: ClientResourceListener): Promise; + retrieve(resourceId: IResourceInfo, query: any, listener?: ClientResourceListener): Promise; + update(resource: ClientResource): Promise; + delete(resourceId: IResourceInfo): Promise; + + findDevices(listener?: DeviceHandler): Promise; + findPlatforms(listener?: PlatformHandler): Promise; + findResources(listener?: ClientResourceListener): Promise; + findResources(options? : any, listener?: ClientResourceListener): Promise; + + on(event: 'devicefound', listener: DeviceHandler): this; + on(event: 'platformfound', listener: PlatformHandler): this; + on(event: 'resourcefound', listener: ClientResourceListener): this; + on(event: 'error', listener: (error: Error) => void): this; + on(event: string | symbol, listener: Function): this; +} + +export type DeviceHandler = (device: IDeviceInfo) => void; +export type PlatformHandler = (platform: IPlatformInfo) => void; +export type ClientResourceListener = (resource: ClientResource) => void; + +export interface IClientEvent { + on(event: 'devicefound', listener: DeviceHandler): this; + on(event: 'platformfound', listener: PlatformHandler): this; + on(event: 'resourcefound', listener: ClientResourceListener): this; + on(event: 'error', listener: (error: Error) => void): this; + on(event: string | symbol, listener: Function): this; +} + +export class ClientResource extends EventEmitter implements IClientResourceEvent, IResourceInfo { + constructor(init, forceNew); + + resourcePath: string; + resourceTypes: string[]; + interfaces: string[]; + discoverable: boolean; + observable: boolean; + properties: any; + + deviceId: string; + slow: boolean; + active: boolean; + secure: boolean; + + on(event: 'delete', listener: ClientResourceListener): this; + on(event: 'update', listener: ClientResourceListener): this; + on(event: 'error', listener: (error: Error) => void): this; + on(event: string, listener: Function): this; +} + +export interface IClientResourceEvent { + on(event: 'delete', listener: ClientResourceListener): this; + on(event: 'update', listener: ClientResourceListener): this; + on(event: 'error', listener: (error: Error) => void): this; + on(event: string, listener: Function): this; +} \ No newline at end of file diff --git a/js/high-level-client-example.ts b/js/high-level-client-example.ts new file mode 100644 index 00000000..87816d4f --- /dev/null +++ b/js/high-level-client-example.ts @@ -0,0 +1,51 @@ +// Copyright 2016 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var observationCount = 0; + +console.log( "Acquiring OCF device" ); + +import * as iotivity from "iotivity-node"; + +var client = iotivity.client; + +// Add a listener that will receive the results of the discovery +client.on( "resourcefound", function( resource ) { + console.log( "Discovered resource:\n" + + JSON.stringify( resource, null, 4 ) ); + + // We've discovered the resource we were seeking. + if ( resource.resourcePath === "/a/high-level-example" ) { + var resourceUpdate: iotivity.ClientResourceListener = function( resource ) { + console.log( "Received resource update:\n" + + JSON.stringify( resource, null, 4 ) ); + + // Stop observing after having made 10 observations + if ( ++observationCount >= 10 ) { + resource.removeListener( "update", resourceUpdate ); + } + }; + + console.log( "This is the resource we want to observe" ); + + // Let's start observing the resource. + resource.on( "update", resourceUpdate ); + } +} ); + +console.log( "Issuing discovery request" ); +client.findResources().catch( function( error ) { + console.error( error.stack ? error.stack : ( error.message ? error.message : error ) ); + process.exit( 1 ); +} ); diff --git a/js/high-level-resource-creation-client.ts b/js/high-level-resource-creation-client.ts new file mode 100644 index 00000000..53d60f3a --- /dev/null +++ b/js/high-level-resource-creation-client.ts @@ -0,0 +1,63 @@ +// Copyright 2016 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +console.log( "Acquiring OCF device" ); + +import * as device from "iotivity-node"; + +function throwError( error ) { + console.error( error.stack ? error.stack : ( error.message ? error.message : error ) + + JSON.stringify( error, null, 4 ) ); + process.exit( 1 ); +} + +new Promise( function( fulfill, reject ) { + var resourceFoundHandler: device.ClientResourceListener = function( resource ) { + console.log( "Discovered the following resource:\n" + + JSON.stringify( resource, null, 4 ) ); + + // We've discovered the resource we were seeking. + if ( resource.resourcePath === "/a/high-level-resource-creation-example" ) { + console.log( "Found the test server" ); + device.client.removeListener( "resourcefound", resourceFoundHandler ); + fulfill( resource.deviceId ); + } + }; + + // Add a listener that will receive the results of the discovery + device.client.on( "resourcefound", resourceFoundHandler ); + + console.log( "Issuing discovery request" ); + device.client.findResources().catch( function( error ) { + device.client.removeListener( "resourcefound", resourceFoundHandler ); + reject( "findResource() failed: " + error ); + } ); +} ).then( function( deviceId: string ) { + console.log( "deviceId discovered" ); + return device.client.create( { + deviceId: deviceId, + resourcePath: "/a/new-resource", + resourceTypes: [ "core.light" ], + interfaces: [ "oic.if.baseline" ], + properties: { + exampleProperty: 23 + } + } ); +} ).then( function( resource: device.ClientResource ) { + console.log( "remote resource successfully created: " + + JSON.stringify( resource, null, 4 ) ); + return device.client.delete( resource ); +} ).then( function() { + console.log( "remote resource successfully deleted" ); +} ).catch( throwError ); diff --git a/js/high-level-resource-creation-server.ts b/js/high-level-resource-creation-server.ts new file mode 100644 index 00000000..5bf49946 --- /dev/null +++ b/js/high-level-resource-creation-server.ts @@ -0,0 +1,74 @@ +// Copyright 2016 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as device from "iotivity-node"; +import * as _ from "lodash"; + +var resourceCreatedByRemote: device.ServerResource; + +_.extend( device.device, { + coreSpecVersion: "res.1.0.0", + dataModels: [ "something.1.0.0" ], + name: "api-server-example" +} ); +_.extend( device.platform, { + manufacturerName: "Intel", + manufactureDate: new Date( "Wed Sep 23 10:04:17 EEST 2015" ), + platformVersion: "1.1.1", + firmwareVersion: "0.0.1", + supportUrl: "http://example.com/" +} ); + +function throwError( error ) { + console.error( error.stack ? error.stack : ( error.message ? error.message : error ) ); + process.exit( 1 ); +} + +device.server + .oncreate( function( request ) { + console.log( "create request" ); + device.server.register( _.extend( request.data, { + discoverable: true + } ) ).then( function( resource ) { + console.log( "resource successfully registered" ); + resourceCreatedByRemote = resource; + request.respond( resource ); + resource.ondelete( function( request ) { + console.log( "delete request" ); + resourceCreatedByRemote.unregister().then( + function() { + console.log( "resource successfully deleted" ); + request.respond() + .then( function() { + console.log( "delete request successfully delivered" ); + }, + function( anError ) { + console.log( ( "" + anError.stack ) + + JSON.stringify( anError, null, 4 ) ); + } ); + }, + _.bind( request.respondWithError, request ) ); + } ); + }, _.bind( request.respondWithError, request ) ); + } ) + .register( { + resourcePath: "/a/high-level-resource-creation-example", + resourceTypes: [ "core.light" ], + interfaces: [ "oic.if.baseline" ], + discoverable: true, + observable: true, + properties: { someValue: 0, someOtherValue: "Helsinki" } + } ).then( function() { + console.log( "initial resource successfully registered" ); + }, throwError ); diff --git a/js/high-level-server-example.ts b/js/high-level-server-example.ts new file mode 100644 index 00000000..c5d59585 --- /dev/null +++ b/js/high-level-server-example.ts @@ -0,0 +1,98 @@ +// Copyright 2016 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +console.log( "Acquiring OCF device" ); + +import * as _ from "lodash" +import * as device from "iotivity-node"; + +var lightResource: device.ServerResource, + observerCount = 0, + sensor = require( "./mock-sensor" )(); + + +_.extend( device.device, { + coreSpecVersion: "res.1.0.0", + dataModels: [ "something.1.0.0" ], + name: "api-server-example" +} ); +_.extend( device.platform, { + manufacturerName: "Intel", + manufactureDate: new Date( "Wed Sep 23 10:04:17 EEST 2015" ), + platformVersion: "1.1.1", + firmwareVersion: "0.0.1", + supportUrl: "http://example.com/" +} ); + +sensor.on( "change", function( newData ) { + var index; + + if ( !lightResource ) { + return; + } + + // Grab the updated data from the sensor and store it in the properties of the resource + for ( index in newData ) { + lightResource.properties[ index ] = newData[ index ]; + } + + if ( observerCount > 0 ) { + console.log( "Issuing notification" ); + lightResource.notify().catch( function( error ) { + console.log( "Error while notifying: " + error.message + "\n" + + JSON.stringify( error, null, 4 ) ); + } ); + } +} ); + +function handleError( theError ) { + console.error( theError ); + process.exit( 1 ); +} + +var lightResourceRequestHandlers = { + retrieve: function( request ) { + request.respond( request.target ).catch( handleError ); + observerCount += ( "observe" in request ) ? ( request.observe ? 1 : -1 ) : 0; + } as device.RequestHandler +}; + +if ( device.device.uuid ) { + + console.log( "Registering OCF resource" ); + + device.server.register( { + resourcePath: "/a/high-level-example", + resourceTypes: [ "core.light" ], + interfaces: [ "oic.if.baseline" ], + discoverable: true, + observable: true, + properties: { someValue: 0, someOtherValue: "Helsinki" } + } ).then( + function( resource ) { + console.log( "OCF resource successfully registered" ); + lightResource = resource; + + // Add event handlers for each supported request type + _.each( lightResourceRequestHandlers, function( callback, requestType ) { + resource[ "on" + requestType ]( function( request ) { + console.log( "Received request " + JSON.stringify( request, null, 4 ) ); + callback( request ); + } ); + } ); + }, + function( error ) { + throw error; + } ); +} diff --git a/js/node_modules/iotivity-node/index.d.ts b/js/node_modules/iotivity-node/index.d.ts new file mode 120000 index 00000000..18b6f1b0 --- /dev/null +++ b/js/node_modules/iotivity-node/index.d.ts @@ -0,0 +1 @@ +../../../index.d.ts \ No newline at end of file diff --git a/package.json b/package.json index c2d29666..d5842b73 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,10 @@ "repository": "https://github.com/otcshare/iotivity-node/", "license": "Apache-2.0", "main": "index.js", - "engines": { "node": ">0.10" }, + "types": "./index.d.ts", + "engines": { + "node": ">0.10" + }, "keywords": [ "oic", "iotivity", @@ -17,6 +20,8 @@ }, "gypfile": true, "dependencies": { + "@types/lodash": "^4.14.52", + "@types/node": "^7.0.5", "bindings": "~1.2.1", "lodash": "^4.16.4", "nan": "^2.1.0", From 9be8d0734c1c7fdf24b03038d87e84afed1c3328 Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Mon, 13 Feb 2017 00:52:05 +0100 Subject: [PATCH 2/5] Typings:Used spec and updated examples Updated with documentation from https://github.com/01org/iot-js-api/blob/master/api/ocf/ --- index.d.ts | 873 +++++++++++++++++++--- js/high-level-resource-creation-client.ts | 2 + js/high-level-resource-creation-server.ts | 4 + js/high-level-server-example.ts | 4 + 4 files changed, 785 insertions(+), 98 deletions(-) diff --git a/index.d.ts b/index.d.ts index f29d2661..ba5ebffc 100644 --- a/index.d.ts +++ b/index.d.ts @@ -3,178 +3,855 @@ // Definitions by: Hans Bakker https://www.github.com/wind-rider /// +/// import { EventEmitter } from "events"; -/*~ If this module has methods, declare them as functions like so. +/** + * Exposes information about the OCF platform that hosts the current device. + * + * @export + * @interface OcfPlatform */ -//export function myMethod(a: string): string; -//export function myOtherMethod(a: number): number; - -/*~ You can declare types that are available via importing the module */ -export interface IPlatformInfo { +export interface OcfPlatform { + + /** + * Platform identifier + * + * @type {string} + * @memberOf OcfPlatform + */ id: string; - osVersion: string; - model: string; + + /** + * OS version + * + * @type {string} + * @memberOf OcfPlatform + */ + osVersion?: string; + + /** + * Model of the hardware + * + * @type {string} + * @memberOf OcfPlatform + */ + model?: string; + + /** + * Manufacturer name + * + * @type {string} + * @memberOf OcfPlatform + */ manufacturerName: string; + + /** + * Manufacturer web page + * + * @type {string} + * @memberOf OcfPlatform + */ manufacturerURL: string; + + /** + * Manufacturing date + * + * @type {Date} + * @memberOf OcfPlatform + */ manufacturerDate: Date; + + /** + * Platform version + * + * @type {string} + * @memberOf OcfPlatform + */ platformVersion: string; + + /** + * Firmware version + * + * @type {string} + * @memberOf OcfPlatform + */ firmwareVersion: string; + + /** + * Product support web page + * + * @type {string} + * @memberOf OcfPlatform + */ supportURL: string; } -export interface IDeviceInfo { - url: string; - name: string; +/** + * Exposes information about the OCF device that runs the current OCF stack instance. + * + * @interface ocf.OcfDevice + */ +export interface OcfDevice { + + /** + * UUID of the device + * + * @type {string} + * @memberOf OcfDevice + */ + uuid: string; + + /** + * host:port + * + * @type {string} + * @memberOf OcfDevice + */ + url?: string; + + /** + * Name of the device + * + * @type {string} + * @memberOf OcfDevice + */ + name?: string; + + /** + * List of supported OCF data models. + * The dataModels property is in the following format: vertical.major.minor where major and minor are numbers and vertical is a string such as "Smart Home". + * + * @type {string[]} + * @memberOf OcfDevice + */ dataModels: string[]; + + /** + * OCF Core Specification version + * + * @type {string} + * @memberOf OcfDevice + */ coreSpecVersion: string; - uuid: string; } -/*~ You can declare properties of the module using const, let, or var */ -//export const myField: number; +/** + * Identifies an OCF resource by the UUID of the device that hosts the resource, + * and the URI path of the resource that uniquely identifies the resource inside a device. + * + * @export + * @interface ResourceId + */ +export interface ResourceId { + + /** + * UUID of the device + * + * @type {string} + * @memberOf ResourceId + */ + deviceId: string; -export var device: IDeviceInfo; -export var platform: IPlatformInfo; + /** + * URI path of the resource + * + * @type {string} + * @memberOf ResourceId + */ + resourcePath: string; +} -/*~ If there are types, properties, or methods inside dotted names - *~ of the module, declare them inside a 'namespace'. +/** + * Represents an OCF resource Link used in Collections. + * The {@link discoverable} and {@link observable} properties come from the {@link p} (policy) property of a Web Link. + * @export + * @interface ResourceLink + * @extends {ResourceId} */ -//export namespace server { -/*~ For example, given this definition, someone could write: - *~ import { subProp } from 'yourModule'; - *~ subProp.foo(); - *~ or - *~ import * as yourMod from 'yourModule'; - *~ yourMod.subProp.foo(); +export interface ResourceLink extends ResourceId { + /** + * List of OCF resource types + * + * @type {string[]} + * @memberOf ResourceLink + */ + resourceTypes: string[]; + + /** + * List of supported interfaces + * + * @type {string[]} + * @memberOf ResourceLink + */ + interfaces: string[]; + + /** + * Whether the resource is discoverable + * + * @type {boolean} + * @memberOf ResourceLink + */ + discoverable?: boolean; + + /** + * Whether the resource is observable + * + * @type {boolean} + * @memberOf ResourceLink + */ + observable?: boolean; + + /** + * Immutable instance identifier of a link + * + * @type {string} + * @memberOf ResourceLink + */ + ins: string; +} + +/** + * Used for creating and registering resources, + * exposes the properties of an OCF resource. All properties are read-write. + * Either the {@link properties} or the {@link links} property MUST be defined. + * The {@link interfaces} property MUST at least contain "oic.if.baseline". + * @export + * @interface Resource + * @extends {ResourceId} */ -// export function foo(): void; -//} +export interface Resource extends ResourceId { + + /** + * List of OCF resource types + * + * @type {string[]} + * @memberOf Resource + */ + resourceTypes: string[]; + + /** + * List of supported interfaces + * + * @type {string[]} + * @memberOf Resource + */ + interfaces: string[]; + + /** + * List of supported Internet media types + * + * @type {string[]} + * @memberOf Resource + */ + mediaTypes: string[]; + /** + * Whether the resource is discoverable + * + * @type {boolean} + * @memberOf Resource + */ + discoverable?: boolean; + + /** + * Whether the resource is observable + * + * @type {boolean} + * @memberOf Resource + */ + observable?: boolean; + + /** + * Collection of links + * When present, it means the resource is an OCF Collection resource that contains + * zero or more [RFC5988 Web Links]{@link https://tools.ietf.org/html/rfc5988} + * represented by the {@link ResourceLink} dictionary. + * @type {ResourceLink[]} + * @memberOf Resource + */ + links: ResourceLink[] + + /** + * Whether the resource is secure + * + * @type {boolean} + * @memberOf Resource + */ + secure?: boolean; + + /** + * Whether the resource is constrained + * + * @type {boolean} + * @memberOf Resource + */ + slow?: boolean; + + /** + * Resource representation properties as described in the data model. + * Contains resource-specific properties and values + * usually described in the RAML data model definition of the resource. + * @type {*} + * @memberOf Resource + */ + properties?: any; + + /** + * TODO Not in the spec??? + * + * @type {boolean} + * @memberOf Resource + */ + active?: boolean; +} + +export interface FindResourcesOptions { + /** + * OCF device UUID + * + * @type {string} + * @memberOf FindResourcesOptions + */ + deviceId?: string; + + /** + * OCF resource type + * + * @type {string} + * @memberOf FindResourcesOptions + */ + resourceType?: string; + + /** + * OCF resource path + * + * @type {string} + * @memberOf FindResourcesOptions + */ + resourcePath?: string; + + /** + * Polling period for discovery + * + * @type {number} + * @memberOf FindResourcesOptions + */ + polling?: number; + + /** + * Timeout period for discovery + * + * @type {number} + * @memberOf FindResourcesOptions + */ + timeout?: number; +} + +export var device: OcfDevice; +export var platform: OcfPlatform; export const server: Server; export const client: Client; +/** + * TODO follow implementation or spec? + * + * @export + * @abstract + * @class OcfError + * @extends {Error} + */ +export abstract class OcfError extends Error { + /** + * UUID of the device. + * Represents the device UUID causing the error. The value null means the local device, + * and the value undefined means the error source device is not available. + * @type {string} + * @memberOf OcfError + */ + deviceId?: string; + + /** + * URI path of the resource. + * Represents the resource path of the resource causing the error. + * If deviceId is undefined, then the value of resourcePath should also be set to undefined. + * @type {string} + * @memberOf OcfError + */ + resourcePath?: string; +} + +export interface RegisterResourceDictionary { + resourcePath: string; + resourceTypes: string[]; + interfaces: string[]; + mediaTypes: string[]; + discoverable: boolean; + observable: boolean; + secure: boolean; + slow: boolean; + properties?: {}; + links?: ResourceLink[]; +} + export class Server { constructor(); + /** + * + * + * @param {RequestHandler} handler + * @returns {Server} TODO spec says void? + * + * @memberOf Server + */ oncreate(handler: RequestHandler): Server; - register(init: IResourceInfo): Promise |any;//todo + register(init: RegisterResourceDictionary): Promise;//todo + + // TODO not implemented? + // Enable/disable presence for this device. + //enablePresence(optional unsigned long timeToLive): Promise; // in ms + //disablePresence(): Promise; } -export class Request { - constructor(init?: Request); +export class OcfRequest { + constructor(init?: OcfRequest); id?: any;// TODO - observe: boolean; - target?: ServerResource; // TODO + + + /** + * OCF request type. + * Can be "create", "retrieve", "update", "delete" + * @type {string} + * @memberOf OcfRequest + */ type: string; - data?: ServerResource|any; //TODO + + /** + * Requesting resource + * + * @type {ResourceId} + * @memberOf OcfRequest + */ + source: ResourceId; + + /** + * Request handling resource + * + * @type {ResourceId} + * @memberOf OcfRequest + */ + target: ResourceId; // TODO + data: ResourceId | ServerResource | any; //TODO + options?: any //TODO + observe: boolean; respond(data?: ServerResource | any): Promise<{}>; //TODO respondWithError(error: string): Promise<{}>; } -export type RequestHandler = (request: Request) => void; +export type TranslateHandler = (requestOptions: any) => any; //TODO +export type RequestHandler = (request: OcfRequest) => void; -export class ServerResource implements IResourceInfo { +export class ServerResource implements Resource { constructor(); - deviceId: string; - slow: boolean; - active: boolean; - secure: boolean; - - ontranslate(handler: RequestHandler); - onretrieve(handler: RequestHandler); - onupdate(handler: RequestHandler); - ondelete(handler: RequestHandler); - oncreate(handler: RequestHandler); + ontranslate(handler: TranslateHandler): ServerResource; + onretrieve(handler: RequestHandler): ServerResource; + onupdate(handler: RequestHandler): ServerResource; + ondelete(handler: RequestHandler): ServerResource; + oncreate(handler: RequestHandler): ServerResource; unregister(): Promise; //TODO notify(): Promise; - resourcePath: string; - resourceTypes: string[]; - interfaces: string[]; - discoverable: boolean; - observable: boolean; - properties: any; -} + /** + * UUID of the device + * + * @type {string} + * @memberOf ResourceId + */ + deviceId: string; -export interface IResourceInfo { - deviceId?: string; + /** + * URI path of the resource + * + * @type {string} + * @memberOf ResourceId + */ resourcePath: string; + + /** + * List of OCF resource types + * + * @type {string[]} + * @memberOf Resource + */ resourceTypes: string[]; + + /** + * List of supported interfaces + * + * @type {string[]} + * @memberOf Resource + */ interfaces: string[]; + + /** + * List of supported Internet media types + * + * @type {string[]} + * @memberOf Resource + */ + mediaTypes: string[]; + /** + * Whether the resource is discoverable + * + * @type {boolean} + * @memberOf Resource + */ discoverable?: boolean; + + /** + * Whether the resource is observable + * + * @type {boolean} + * @memberOf Resource + */ observable?: boolean; - properties: any; - slow?: boolean; - active?: boolean; + + /** + * Collection of links + * When present, it means the resource is an OCF Collection resource that contains + * zero or more [RFC5988 Web Links]{@link https://tools.ietf.org/html/rfc5988} + * represented by the {@link ResourceLink} dictionary. + * @type {ResourceLink[]} + * @memberOf Resource + */ + links: ResourceLink[] + + /** + * Whether the resource is secure + * + * @type {boolean} + * @memberOf Resource + */ secure?: boolean; -} -export class Client extends EventEmitter implements IClientEvent { - // deviceId could also be an object but this is undocumented - getDeviceInfo(deviceId: string): Promise<{}>; - getPlatformInfo(deviceId: string): Promise<{}>; + /** + * Whether the resource is constrained + * + * @type {boolean} + * @memberOf Resource + */ + slow?: boolean; - //TODO - create(resourceInit?: IResourceInfo, target?: any): Promise; - retrieve(resourceId: IResourceInfo, listener?: ClientResourceListener): Promise; - retrieve(resourceId: IResourceInfo, query: any, listener?: ClientResourceListener): Promise; - update(resource: ClientResource): Promise; - delete(resourceId: IResourceInfo): Promise; + /** + * Resource representation properties as described in the data model. + * Contains resource-specific properties and values + * usually described in the RAML data model definition of the resource. + * @type {*} + * @memberOf Resource + */ + properties?: any; + + /** + * TODO Not in the spec??? + * + * @type {boolean} + * @memberOf Resource + */ + active?: boolean; +} +/** + * The OCF Client API implements CRUDN (Create, Retrieve, Update, Delete, Notify) functionality + * that enables remote access to resources on the network, as well as OCF discovery. + * + * @export + * @class Client + * @extends {EventEmitter} + * @implements {IClientEvent} + */ +export class Client extends EventEmitter { + + /** + * Fetches a remote device information object. The deviceId argument is a string that contains an OCF device UUID. + * deviceId could also be an object but this is undocumented + * @param {string} deviceId + * @returns {Promise} + * + * @memberOf Client + */ + getDeviceInfo(deviceId: string): Promise; + + /** + * Fetches a remote platform information object. The {@link deviceId} argument is + * a string that contains an OCF device UUID. + * + * @param {string} deviceId + * @returns {Promise<{}>} + * + * @memberOf Client + */ + getPlatformInfo(deviceId: string): Promise; + + /** + * Initiates a device discovery network operation. + * When a device is discovered, a {@link devicefound} event is fired that contains + * a property named {@link device}, whose value is a {@link OcfDevice} object. + * @param {DeviceHandler} [listener] + * @returns {Promise} + * + * @memberOf Client + */ findDevices(listener?: DeviceHandler): Promise; + + /** + * Initiates a platform discovery network operation. + * When a platform is discovered, a {@link platformfound} event is fired that contains + * a property named {@link platform}, whose value is a {@link OcfPlatform} object. + * @param {PlatformHandler} [listener] + * @returns {Promise} + * + * @memberOf Client + */ findPlatforms(listener?: PlatformHandler): Promise; + + /** + * Whenever a resource resource is discovered, the {@link resourcefound} event is fired + * with {@link resource} as an argument to the listener function. + * + * @param {ClientResourceListener} [listener] + * @returns {Promise} + * + * @memberOf Client + */ findResources(listener?: ClientResourceListener): Promise; - findResources(options? : any, listener?: ClientResourceListener): Promise; - on(event: 'devicefound', listener: DeviceHandler): this; + /** + * Whenever a resource resource is discovered, the {@link resourcefound} event is fired + * with {@link resource} as an argument to the listener function. + * + * @param {FindResourcesOptions} [options] + * @param {ClientResourceListener} [listener] + * @returns {Promise} + * + * @memberOf Client + */ + findResources(options?: FindResourcesOptions, listener?: ClientResourceListener): Promise; + + /** + * Creates a remote resource on a given device, and optionally specifies a {@link target} resource + * that is supposed to create the new resource. The device's {@link oncreate} event handler + * takes care of dispatching the request to the {@link target} resource that will handle + * creating the resource, and responds with the created resource, or with an error. + * @param {Resource} [resource] It should contain at least the resourcePath and resourceType properties + * @param {ResourceId} [target] The optional target argument is a ResourceId object that contains at least a device UUID and a resource path that identifies the target resource responsible for creating the requested resource. + * @returns {Promise} + * + * @memberOf Client + */ + create(resource?: Resource, target?: ResourceId): Promise; + retrieve(resourceId: Resource, listener?: ClientResourceListener): Promise; + retrieve(resourceId: Resource, query: any, listener?: ClientResourceListener): Promise; + + /** + * Updates a resource on the network by sending a request to the device specified by resource.deviceId. + * The device's update event handler takes care of updating the resource and replying + * with the updated resource, or with an error. The resource identified by resource is updated. + * + * @param {Resource} resource + * @returns {Promise} + * + * @memberOf Client + */ + update(resource: Resource): Promise; + + /** + * Deletes a resource from the network by sending a request to the device specified + * in resourceId.deviceId. The device's delete event handler takes care of + * deleting (unregistering) the resource and reporting success or error. + * + * @param {ResourceId} resourceId + * @returns {Promise} + * + * @memberOf Client + */ + delete(resourceId: ResourceId): Promise; + on(event: 'platformfound', listener: PlatformHandler): this; + on(event: 'devicefound', listener: DeviceHandler): this; + on(event: 'devicelost', listener: DeviceHandler): this; on(event: 'resourcefound', listener: ClientResourceListener): this; - on(event: 'error', listener: (error: Error) => void): this; - on(event: string | symbol, listener: Function): this; } -export type DeviceHandler = (device: IDeviceInfo) => void; -export type PlatformHandler = (platform: IPlatformInfo) => void; +export type DeviceHandler = (device: OcfDevice) => void; +export type PlatformHandler = (platform: OcfPlatform) => void; export type ClientResourceListener = (resource: ClientResource) => void; -export interface IClientEvent { - on(event: 'devicefound', listener: DeviceHandler): this; - on(event: 'platformfound', listener: PlatformHandler): this; - on(event: 'resourcefound', listener: ClientResourceListener): this; - on(event: 'error', listener: (error: Error) => void): this; - on(event: string | symbol, listener: Function): this; -} - -export class ClientResource extends EventEmitter implements IClientResourceEvent, IResourceInfo { +/** + * Note that applications should not create {@link ClientResource} objects, + * as they are created and tracked by implementations. Applications can create and use + * {@link ResourceId} and {@link Resource} objects as method arguments, + * but client-created {@link ClientResource} objects are not tracked by implementations + * and will not receive events. + * @export + * @class ClientResource + * @extends {EventEmitter} + * @implements {IClientResourceEvent} + * @implements {Resource} + */ +export class ClientResource extends EventEmitter implements Resource { constructor(init, forceNew); + /** + * UUID of the device + * + * @type {string} + * @memberOf ResourceId + */ + deviceId: string; + + /** + * URI path of the resource + * + * @type {string} + * @memberOf ResourceId + */ resourcePath: string; + /** + * List of OCF resource types + * + * @type {string[]} + * @memberOf Resource + */ resourceTypes: string[]; + + /** + * List of supported interfaces + * + * @type {string[]} + * @memberOf Resource + */ interfaces: string[]; - discoverable: boolean; - observable: boolean; - properties: any; - deviceId: string; - slow: boolean; - active: boolean; - secure: boolean; + /** + * List of supported Internet media types + * + * @type {string[]} + * @memberOf Resource + */ + mediaTypes: string[]; + /** + * Whether the resource is discoverable + * + * @type {boolean} + * @memberOf Resource + */ + discoverable?: boolean; - on(event: 'delete', listener: ClientResourceListener): this; - on(event: 'update', listener: ClientResourceListener): this; - on(event: 'error', listener: (error: Error) => void): this; - on(event: string, listener: Function): this; -} + /** + * Whether the resource is observable + * + * @type {boolean} + * @memberOf Resource + */ + observable?: boolean; -export interface IClientResourceEvent { + /** + * Collection of links + * When present, it means the resource is an OCF Collection resource that contains + * zero or more [RFC5988 Web Links]{@link https://tools.ietf.org/html/rfc5988} + * represented by the {@link ResourceLink} dictionary. + * @type {ResourceLink[]} + * @memberOf Resource + */ + links: ResourceLink[] + + /** + * Whether the resource is secure + * + * @type {boolean} + * @memberOf Resource + */ + secure?: boolean; + + /** + * Whether the resource is constrained + * + * @type {boolean} + * @memberOf Resource + */ + slow?: boolean; + + /** + * Resource representation properties as described in the data model. + * Contains resource-specific properties and values + * usually described in the RAML data model definition of the resource. + * @type {*} + * @memberOf Resource + */ + properties?: any; + + /** + * TODO Not in the spec??? + * + * @type {boolean} + * @memberOf Resource + */ + active?: boolean; + + /** + * Polling hint for this resource. + * The {@link polling} property is a number that represents the period of polling + * in milliseconds, used in the + * [resource polling algorithm]{@link https://github.com/01org/iot-js-api/blob/master/api/ocf/client.md#resourcepolling}. + * By writing {@link polling}, applications provide a hint to the implementation about + * how often it should attempt retrieving the resource in order to determine it is alive. + * Implementations MAY override the value of {@link polling}. + * @type {number} + * @memberOf ClientResource + */ + polling?: number; + + /** + * The {@link delete} event is fired on a {@link ClientResource} object when the implementation gets notified + * about the resource being deleted or unregistered from the OCF network. The event listener receives + * a {@link ResourceId} dictionary object that contains the {@link deviceId} and {@link resourcePath} + * of the deleted resource. + * + * @param {'delete'} event + * @param {ClientResourceListener} listener + * @returns {this} + * + * @memberOf ClientResource + */ on(event: 'delete', listener: ClientResourceListener): this; + + /** + * The update event is fired on a {@link ClientResource} object when the implementation + * receives an OCF resource update notification because the resource representation has changed. + * The event listener receives a dictionary object that contains the resource properties + * that have changed. + * In addition, the resource property values are already updated to the new values + * when the event is fired. + * + * The recommended way to observe and unobserve resources from applications is by using + * the {@link retrieve()} method, in order to be able to specify OCF retrieve options. + * However, for convenience, when the first listener function {@link listener} is added to + * the {@link update} event of {@link resource}, implementations SHOULD call + * `retrieve(resource, null, listener). When the last listener is removed, + * the implementations SHOULD call retrieve(resource), i.e. make an OCF retrieve request + * with the {@link observe} flag off. + * + * @param {'update'} event + * @param {ClientResourceListener} listener + * @returns {this} + * + * @memberOf ClientResource + */ on(event: 'update', listener: ClientResourceListener): this; - on(event: 'error', listener: (error: Error) => void): this; - on(event: string, listener: Function): this; } \ No newline at end of file diff --git a/js/high-level-resource-creation-client.ts b/js/high-level-resource-creation-client.ts index 53d60f3a..cc8e9ba1 100644 --- a/js/high-level-resource-creation-client.ts +++ b/js/high-level-resource-creation-client.ts @@ -50,6 +50,8 @@ new Promise( function( fulfill, reject ) { resourcePath: "/a/new-resource", resourceTypes: [ "core.light" ], interfaces: [ "oic.if.baseline" ], + mediaTypes: [], + links: [], properties: { exampleProperty: 23 } diff --git a/js/high-level-resource-creation-server.ts b/js/high-level-resource-creation-server.ts index 5bf49946..448d0008 100644 --- a/js/high-level-resource-creation-server.ts +++ b/js/high-level-resource-creation-server.ts @@ -66,6 +66,10 @@ device.server resourcePath: "/a/high-level-resource-creation-example", resourceTypes: [ "core.light" ], interfaces: [ "oic.if.baseline" ], + mediaTypes: [], + links: [], + secure: true, + slow: false, discoverable: true, observable: true, properties: { someValue: 0, someOtherValue: "Helsinki" } diff --git a/js/high-level-server-example.ts b/js/high-level-server-example.ts index c5d59585..a9a2ae19 100644 --- a/js/high-level-server-example.ts +++ b/js/high-level-server-example.ts @@ -76,6 +76,10 @@ if ( device.device.uuid ) { resourcePath: "/a/high-level-example", resourceTypes: [ "core.light" ], interfaces: [ "oic.if.baseline" ], + mediaTypes: [], + links: [], + secure: true, + slow: false, discoverable: true, observable: true, properties: { someValue: 0, someOtherValue: "Helsinki" } From 2dbaee5758ba1d7d8df12e23b4c328a2932f27fd Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Mon, 13 Feb 2017 23:27:13 +0100 Subject: [PATCH 3/5] Typings: fixes for typings and examples --- index.d.ts | 407 ++++++++++++------ {js => ts}/high-level-client-example.ts | 0 .../high-level-resource-creation-client.ts | 2 +- .../high-level-resource-creation-server.ts | 2 +- {js => ts}/high-level-server-example.ts | 0 5 files changed, 280 insertions(+), 131 deletions(-) rename {js => ts}/high-level-client-example.ts (100%) rename {js => ts}/high-level-resource-creation-client.ts (98%) rename {js => ts}/high-level-resource-creation-server.ts (97%) rename {js => ts}/high-level-server-example.ts (100%) diff --git a/index.d.ts b/index.d.ts index ba5ebffc..e89499c6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -3,10 +3,58 @@ // Definitions by: Hans Bakker https://www.github.com/wind-rider /// -/// import { EventEmitter } from "events"; +/** + * Exposes information about the OCF device that runs the current OCF stack instance. + * + * @interface ocf.OcfDevice + */ +export interface OcfDevice { + + /** + * UUID of the device + * + * @type {string} + * @memberOf OcfDevice + */ + uuid: string; + + /** + * host:port + * + * @type {string} + * @memberOf OcfDevice + */ + url?: string; + + /** + * Name of the device + * + * @type {string} + * @memberOf OcfDevice + */ + name?: string; + + /** + * List of supported OCF data models. + * The dataModels property is in the following format: vertical.major.minor where major and minor are numbers and vertical is a string such as "Smart Home". + * + * @type {string[]} + * @memberOf OcfDevice + */ + dataModels: string[]; + + /** + * OCF Core Specification version + * + * @type {string} + * @memberOf OcfDevice + */ + coreSpecVersion: string; +} + /** * Exposes information about the OCF platform that hosts the current device. * @@ -89,52 +137,31 @@ export interface OcfPlatform { } /** - * Exposes information about the OCF device that runs the current OCF stack instance. + * TODO follow implementation or spec? * - * @interface ocf.OcfDevice + * @export + * @abstract + * @class OcfError + * @extends {Error} */ -export interface OcfDevice { - - /** - * UUID of the device - * - * @type {string} - * @memberOf OcfDevice - */ - uuid: string; - - /** - * host:port - * - * @type {string} - * @memberOf OcfDevice - */ - url?: string; - +export abstract class OcfError extends Error { /** - * Name of the device - * + * UUID of the device. + * Represents the device UUID causing the error. The value null means the local device, + * and the value undefined means the error source device is not available. * @type {string} - * @memberOf OcfDevice - */ - name?: string; - - /** - * List of supported OCF data models. - * The dataModels property is in the following format: vertical.major.minor where major and minor are numbers and vertical is a string such as "Smart Home". - * - * @type {string[]} - * @memberOf OcfDevice + * @memberOf OcfError */ - dataModels: string[]; + deviceId?: string; /** - * OCF Core Specification version - * + * URI path of the resource. + * Represents the resource path of the resource causing the error. + * If deviceId is undefined, then the value of resourcePath should also be set to undefined. * @type {string} - * @memberOf OcfDevice + * @memberOf OcfError */ - coreSpecVersion: string; + resourcePath?: string; } /** @@ -193,7 +220,7 @@ export interface ResourceLink extends ResourceId { * @type {boolean} * @memberOf ResourceLink */ - discoverable?: boolean; + discoverable: boolean; /** * Whether the resource is observable @@ -201,7 +228,7 @@ export interface ResourceLink extends ResourceId { * @type {boolean} * @memberOf ResourceLink */ - observable?: boolean; + observable: boolean; /** * Immutable instance identifier of a link @@ -209,7 +236,32 @@ export interface ResourceLink extends ResourceId { * @type {string} * @memberOf ResourceLink */ - ins: string; + ins?: string; +} + +/** + * Object to create resources via Client + * + * @export + * @interface ResoureCreateObject + */ +export interface ResoureCreateObject { + + /** + * OCF resource URI path + * + * @type {string} + * @memberOf ResoureCreateObject + */ + resourcePath: string; + + /** + * OCF resource types + * TODO the spec says resourceType_ is string_ + * @type {string[]} + * @memberOf ResoureCreateObject + */ + resourceTypes: string[]; } /** @@ -221,7 +273,7 @@ export interface ResourceLink extends ResourceId { * @interface Resource * @extends {ResourceId} */ -export interface Resource extends ResourceId { +export interface Resource extends ResourceId, ResoureCreateObject { /** * List of OCF resource types @@ -252,7 +304,7 @@ export interface Resource extends ResourceId { * @type {boolean} * @memberOf Resource */ - discoverable?: boolean; + discoverable: boolean; /** * Whether the resource is observable @@ -260,7 +312,7 @@ export interface Resource extends ResourceId { * @type {boolean} * @memberOf Resource */ - observable?: boolean; + observable: boolean; /** * Collection of links @@ -278,7 +330,7 @@ export interface Resource extends ResourceId { * @type {boolean} * @memberOf Resource */ - secure?: boolean; + secure: boolean; /** * Whether the resource is constrained @@ -299,13 +351,18 @@ export interface Resource extends ResourceId { /** * TODO Not in the spec??? - * + * True means that the resource is initialized, otherwise the resource is 'inactive'. + * 'inactive' signifies that the resource has been marked for deletion or is already deleted. * @type {boolean} * @memberOf Resource */ active?: boolean; } +export interface ResourceRepresentation { + //TODO is timestamp always in ResourceRepresentation? +} + export interface FindResourcesOptions { /** * OCF device UUID @@ -354,33 +411,6 @@ export var platform: OcfPlatform; export const server: Server; export const client: Client; -/** - * TODO follow implementation or spec? - * - * @export - * @abstract - * @class OcfError - * @extends {Error} - */ -export abstract class OcfError extends Error { - /** - * UUID of the device. - * Represents the device UUID causing the error. The value null means the local device, - * and the value undefined means the error source device is not available. - * @type {string} - * @memberOf OcfError - */ - deviceId?: string; - - /** - * URI path of the resource. - * Represents the resource path of the resource causing the error. - * If deviceId is undefined, then the value of resourcePath should also be set to undefined. - * @type {string} - * @memberOf OcfError - */ - resourcePath?: string; -} export interface RegisterResourceDictionary { resourcePath: string; @@ -395,29 +425,52 @@ export interface RegisterResourceDictionary { links?: ResourceLink[]; } +/** + * The Server API provides the means to register and unregister resources, + * register handlers that serve CRUDN requests on a device, + * notify of resource changes. + * A device that implements the Server API may provide special resources to handle CRUDN requests. + * The Server API object does not expose its own properties, only methods for registering handlers. + * @export + * @class Server + */ export class Server { - constructor(); /** - * + * Registers a function to handle OCF create resource requests * * @param {RequestHandler} handler - * @returns {Server} TODO spec says void? + * @returns {Server} this for chaining * * @memberOf Server */ oncreate(handler: RequestHandler): Server; - register(init: RegisterResourceDictionary): Promise;//todo - // TODO not implemented? - // Enable/disable presence for this device. - //enablePresence(optional unsigned long timeToLive): Promise; // in ms - //disablePresence(): Promise; + /** + * Registers a resource in the OCF network. + * + * @param {RegisterResourceDictionary} init + * @returns {Promise} + * + * @memberOf Server + */ + register(init: RegisterResourceDictionary): Promise;//todo } +/** + * Describes an object that is passed to server event listeners. + * + * @export + * @class OcfRequest + */ export class OcfRequest { - constructor(init?: OcfRequest); + /** + * TODO not part of the spec? + * + * @type {*} + * @memberOf OcfRequest + */ id?: any;// TODO @@ -444,29 +497,140 @@ export class OcfRequest { * @memberOf OcfRequest */ target: ResourceId; // TODO - data: ResourceId | ServerResource | any; //TODO + data: ResourceId | Resource | ResourceRepresentation; //TODO + + /** + * Object whose properties represent the REST query parameters + * passed along with the request as a JSON-serializable dictionary. + * The semantics of the parameters are application-specific + * (e.g. requesting a resource representation in metric or imperial units). + * For instance request options may be used with the retrieve request. + * + * @type {*} + * @memberOf OcfRequest + */ options?: any //TODO + + /** + * Flag for OCF retrieve requests that tells whether observation + * for the requested resource should be on or off. For + * requests other than "retrieve" the value SHOULD be undefined. + * + * @type {boolean} + * @memberOf OcfRequest + */ observe: boolean; - respond(data?: ServerResource | any): Promise<{}>; //TODO - respondWithError(error: string): Promise<{}>; + /** + * Sends a response to this request. + * The data argument is optional and used with requests such as create and update. + * The method is typically used from request handlers, and internally + * reuses the request information in order to construct a response message. + * + * @param {(ResourceId | Resource | ResourceRepresentation)} [data] + * @returns {Promise} + * + * @memberOf OcfRequest + */ + respond(data?: ResourceId | Resource | ResourceRepresentation): Promise; + + /** + * Sends an error response to this request. + * The error argument is an Error object. + * The method is typically used from request handlers, and internally + * reuses the request information in order to construct a response message. + * + * @param {string} error + * @returns {Promise} + * + * @memberOf OcfRequest + */ + respondWithError(error: string): Promise; } -export type TranslateHandler = (requestOptions: any) => any; //TODO +export type TranslateHandler = (requestOptions: any) => ResourceRepresentation; //TODO export type RequestHandler = (request: OcfRequest) => void; export class ServerResource implements Resource { - constructor(); + /** + * Registers a callback function handler for translation and returns this. + * + * The handler function will be invoked by the implementation when the client + * requests a certain representation of the resource by the means of request options. + * The handler function will receive as argument a dictionary object options that contains + * the REST request options parsed into property-value pairs. + * The handler can use options and this.properties in order to compute + * the modified resource representation object. + * + * @param {TranslateHandler} handler + * @returns {ServerResource} + * + * @memberOf ServerResource + */ ontranslate(handler: TranslateHandler): ServerResource; + + /** + * Registers the function handler to handle OCF retrieve resource requests + * and returns this for chaining. + * + * @param {RequestHandler} handler + * @returns {ServerResource} + * + * @memberOf ServerResource + */ onretrieve(handler: RequestHandler): ServerResource; + + /** + * Registers the function handler to handle OCF update resource requests + * and returns this for chaining. + * + * @param {RequestHandler} handler + * @returns {ServerResource} + * + * @memberOf ServerResource + */ onupdate(handler: RequestHandler): ServerResource; + + /** + * Registers the handler function to handle OCF delete resource requests + * and returns this for chaining. + * + * @param {RequestHandler} handler + * @returns {ServerResource} + * + * @memberOf ServerResource + */ ondelete(handler: RequestHandler): ServerResource; + + /** + * TODO not part of the spec? + * + * @param {RequestHandler} handler + * @returns {ServerResource} + * + * @memberOf ServerResource + */ oncreate(handler: RequestHandler): ServerResource; - unregister(): Promise; //TODO + /** + * Notifies subscribed clients about a resource representation change. + * Notifications are sent with the update event + * @returns {Promise} + * + * @memberOf ServerResource + */ notify(): Promise; + /** + * Unregisters the given resource from the OCF network. + * + * @returns {Promise} + * + * @memberOf ServerResource + */ + unregister(): Promise; //TODO + /** * UUID of the device * @@ -512,7 +676,7 @@ export class ServerResource implements Resource { * @type {boolean} * @memberOf Resource */ - discoverable?: boolean; + discoverable: boolean; /** * Whether the resource is observable @@ -520,7 +684,7 @@ export class ServerResource implements Resource { * @type {boolean} * @memberOf Resource */ - observable?: boolean; + observable: boolean; /** * Collection of links @@ -538,7 +702,7 @@ export class ServerResource implements Resource { * @type {boolean} * @memberOf Resource */ - secure?: boolean; + secure: boolean; /** * Whether the resource is constrained @@ -577,16 +741,6 @@ export class ServerResource implements Resource { */ export class Client extends EventEmitter { - /** - * Fetches a remote device information object. The deviceId argument is a string that contains an OCF device UUID. - * deviceId could also be an object but this is undocumented - * @param {string} deviceId - * @returns {Promise} - * - * @memberOf Client - */ - getDeviceInfo(deviceId: string): Promise; - /** * Fetches a remote platform information object. The {@link deviceId} argument is * a string that contains an OCF device UUID. @@ -599,15 +753,14 @@ export class Client extends EventEmitter { getPlatformInfo(deviceId: string): Promise; /** - * Initiates a device discovery network operation. - * When a device is discovered, a {@link devicefound} event is fired that contains - * a property named {@link device}, whose value is a {@link OcfDevice} object. - * @param {DeviceHandler} [listener] - * @returns {Promise} + * Fetches a remote device information object. The deviceId argument is a string that contains an OCF device UUID. + * deviceId could also be an object but this is undocumented + * @param {string} deviceId + * @returns {Promise} * * @memberOf Client */ - findDevices(listener?: DeviceHandler): Promise; + getDeviceInfo(deviceId: string): Promise; /** * Initiates a platform discovery network operation. @@ -620,6 +773,17 @@ export class Client extends EventEmitter { */ findPlatforms(listener?: PlatformHandler): Promise; + /** + * Initiates a device discovery network operation. + * When a device is discovered, a {@link devicefound} event is fired that contains + * a property named {@link device}, whose value is a {@link OcfDevice} object. + * @param {DeviceHandler} [listener] + * @returns {Promise} + * + * @memberOf Client + */ + findDevices(listener?: DeviceHandler): Promise; + /** * Whenever a resource resource is discovered, the {@link resourcefound} event is fired * with {@link resource} as an argument to the listener function. @@ -651,12 +815,11 @@ export class Client extends EventEmitter { * @param {Resource} [resource] It should contain at least the resourcePath and resourceType properties * @param {ResourceId} [target] The optional target argument is a ResourceId object that contains at least a device UUID and a resource path that identifies the target resource responsible for creating the requested resource. * @returns {Promise} - * * @memberOf Client */ - create(resource?: Resource, target?: ResourceId): Promise; - retrieve(resourceId: Resource, listener?: ClientResourceListener): Promise; - retrieve(resourceId: Resource, query: any, listener?: ClientResourceListener): Promise; + create(resource: ResoureCreateObject, target?: ResourceId): Promise; + retrieve(resourceId: Resource, listener?: ClientResourceListener): Promise; + retrieve(resourceId: Resource, query: any, listener?: ClientResourceListener): Promise; /** * Updates a resource on the network by sending a request to the device specified by resource.deviceId. @@ -705,7 +868,6 @@ export type ClientResourceListener = (resource: ClientResource) => void; * @implements {Resource} */ export class ClientResource extends EventEmitter implements Resource { - constructor(init, forceNew); /** * UUID of the device @@ -751,7 +913,7 @@ export class ClientResource extends EventEmitter implements Resource { * @type {boolean} * @memberOf Resource */ - discoverable?: boolean; + discoverable: boolean; /** * Whether the resource is observable @@ -759,7 +921,7 @@ export class ClientResource extends EventEmitter implements Resource { * @type {boolean} * @memberOf Resource */ - observable?: boolean; + observable: boolean; /** * Collection of links @@ -777,7 +939,7 @@ export class ClientResource extends EventEmitter implements Resource { * @type {boolean} * @memberOf Resource */ - secure?: boolean; + secure: boolean; /** * Whether the resource is constrained @@ -804,19 +966,6 @@ export class ClientResource extends EventEmitter implements Resource { */ active?: boolean; - /** - * Polling hint for this resource. - * The {@link polling} property is a number that represents the period of polling - * in milliseconds, used in the - * [resource polling algorithm]{@link https://github.com/01org/iot-js-api/blob/master/api/ocf/client.md#resourcepolling}. - * By writing {@link polling}, applications provide a hint to the implementation about - * how often it should attempt retrieving the resource in order to determine it is alive. - * Implementations MAY override the value of {@link polling}. - * @type {number} - * @memberOf ClientResource - */ - polling?: number; - /** * The {@link delete} event is fired on a {@link ClientResource} object when the implementation gets notified * about the resource being deleted or unregistered from the OCF network. The event listener receives @@ -846,7 +995,7 @@ export class ClientResource extends EventEmitter implements Resource { * `retrieve(resource, null, listener). When the last listener is removed, * the implementations SHOULD call retrieve(resource), i.e. make an OCF retrieve request * with the {@link observe} flag off. - * + * TODO not sure how to model this because it may be partial and not sure whether it is Resource or ClientResource * * @param {'update'} event * @param {ClientResourceListener} listener * @returns {this} diff --git a/js/high-level-client-example.ts b/ts/high-level-client-example.ts similarity index 100% rename from js/high-level-client-example.ts rename to ts/high-level-client-example.ts diff --git a/js/high-level-resource-creation-client.ts b/ts/high-level-resource-creation-client.ts similarity index 98% rename from js/high-level-resource-creation-client.ts rename to ts/high-level-resource-creation-client.ts index cc8e9ba1..4bc072dd 100644 --- a/js/high-level-resource-creation-client.ts +++ b/ts/high-level-resource-creation-client.ts @@ -55,7 +55,7 @@ new Promise( function( fulfill, reject ) { properties: { exampleProperty: 23 } - } ); + } as device.Resource); } ).then( function( resource: device.ClientResource ) { console.log( "remote resource successfully created: " + JSON.stringify( resource, null, 4 ) ); diff --git a/js/high-level-resource-creation-server.ts b/ts/high-level-resource-creation-server.ts similarity index 97% rename from js/high-level-resource-creation-server.ts rename to ts/high-level-resource-creation-server.ts index 448d0008..9817014e 100644 --- a/js/high-level-resource-creation-server.ts +++ b/ts/high-level-resource-creation-server.ts @@ -40,7 +40,7 @@ device.server console.log( "create request" ); device.server.register( _.extend( request.data, { discoverable: true - } ) ).then( function( resource ) { + } ) as device.RegisterResourceDictionary ).then( function( resource ) { console.log( "resource successfully registered" ); resourceCreatedByRemote = resource; request.respond( resource ); diff --git a/js/high-level-server-example.ts b/ts/high-level-server-example.ts similarity index 100% rename from js/high-level-server-example.ts rename to ts/high-level-server-example.ts From 255138fa77bd77b232a5727363f619fe2aeff627 Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Mon, 13 Feb 2017 23:33:37 +0100 Subject: [PATCH 4/5] Typings: removed OcfRequest.id --- index.d.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index e89499c6..9e9ace1d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -465,15 +465,6 @@ export class Server { */ export class OcfRequest { - /** - * TODO not part of the spec? - * - * @type {*} - * @memberOf OcfRequest - */ - id?: any;// TODO - - /** * OCF request type. * Can be "create", "retrieve", "update", "delete" From 2231e0c256ccc79b1abc3d7f5e18084763e2ac07 Mon Sep 17 00:00:00 2001 From: Hans Bakker Date: Tue, 14 Feb 2017 18:29:56 +0100 Subject: [PATCH 5/5] All: Update spec version in ts examples Update spec version to res.1.1.0 implented in IoTivity 1.2.0 --- ts/high-level-resource-creation-server.ts | 2 +- ts/high-level-server-example.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/high-level-resource-creation-server.ts b/ts/high-level-resource-creation-server.ts index 9817014e..c492ab5a 100644 --- a/ts/high-level-resource-creation-server.ts +++ b/ts/high-level-resource-creation-server.ts @@ -18,7 +18,7 @@ import * as _ from "lodash"; var resourceCreatedByRemote: device.ServerResource; _.extend( device.device, { - coreSpecVersion: "res.1.0.0", + coreSpecVersion: "res.1.1.0", dataModels: [ "something.1.0.0" ], name: "api-server-example" } ); diff --git a/ts/high-level-server-example.ts b/ts/high-level-server-example.ts index a9a2ae19..f5d1e877 100644 --- a/ts/high-level-server-example.ts +++ b/ts/high-level-server-example.ts @@ -23,7 +23,7 @@ var lightResource: device.ServerResource, _.extend( device.device, { - coreSpecVersion: "res.1.0.0", + coreSpecVersion: "res.1.1.0", dataModels: [ "something.1.0.0" ], name: "api-server-example" } );