Newer
Older
import { knownUSPVersions } from "./util";
export type SessionInitMsg = {
version: USPVersion;
toId: string;
fromId: string;
sessionContext: {
sessionId: string;
sequenceId: string;
expectedId: string;
};
};
export type CommandType =
| "GET"
| "SET"
| "ADD"
| "DELETE"
| "OPERATE"
| "NOTIFY"
| "GET_SUPPORTED_DM"
| "GET_INSTANCES"
| "GET_SUPPORTED_PROTO";
export type SetCommandOptions = {
/**
* Prints raw set response message
*/
raw?: boolean;
};
Marin Karamihalev
committed
export type GetCommandGeneralOptions = {
/**
* Defaults to 2 (Only applies to usp version 1.2 )
*/
Marin Karamihalev
committed
};
export type GetCommandOptions = {
raw?: boolean;
Marin Karamihalev
committed
* All results will be nestled into { result: <result>, __query__: <full path> } (defaults to false)
* @deprecated Use getNested instead
Marin Karamihalev
committed
} & GetCommandGeneralOptions;
export type GetNestedCommandOptions = {} & GetCommandGeneralOptions;
type ReturnValue =
| string
| { __query__: string; [key: string]: ReturnValue | ReturnValue[] }
| { __query__: string; [key: string]: ReturnValue | ReturnValue[] }[];
export type GetReturn = string | Record<string, any> | Record<string, any>[];
Marin Karamihalev
committed
export type UspProperty = {
__query__: string;
result: string;
};
export type UspPropertyList = {
__query__: string;
result: { __query__: string; result: string }[];
};
export type UspObject = {
__query__: string;
result: { __query__: string; [key: string]: ReturnValue };
};
export type UspObjectList = {
__query__: string;
result: { __query__: string; [key: string]: ReturnValue }[];
};
export type SetResponse = {
affectedPath: string;
updatedParams: Record<string, string>;
}[];
export type AddResponse = string[];
export type AddRawResponse = {
header: {
msgId: string;
msgType: "ADD_RESP";
};
body: {
response: {
addResp: {
createdObjResults: {
requestedPath: string;
operStatus: {
operSuccess: {
instantiatedPath: string;
uniqueKeys: Record<string, string>;
};
};
}[];
};
};
};
};
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
export type SetRawResponse = {
header: {
msgId: string;
msgType: "SET_RESP";
};
body: {
response: {
setResp: {
updatedObjResults: {
requestedPath: string;
operStatus: {
operSuccess: {
updatedInstResults: [
{
affectedPath: string;
updatedParams: Record<string, string>;
}
];
};
};
}[];
};
};
};
};
export type VerifierFunc = (args: Record<string, any>) => VerifyResult;
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
NoError = "VerifyResult.NoError",
// GET
PathsMissing = "VerifyResult.PathsMissing",
PathsNotStringOrStringArray = "VerifyResult.PathsNotStringOrStringArray",
RawOptionNotBool = "VerifyResult.RawOptionNotBool",
RetainPathOptionNotBool = "VerifyResult.RetainPathOptionNotBool",
MaxDepthOptionNotNumber = "VerifyResult.MaxDepthOptionNotNumber",
MaxDepthOptionIsNegative = "VerifyResult.MaxDepthOptionIsNegative",
// SET / ADD
ValueIsMissing = "VerifyResult.ValueIsMissing",
ValueMustBeArray = "VerifyResult.ValueMustBeArray",
ValueAndPathArraysMustBeSameLength = "VerifyResult.ValueAndPathArraysMustBeSameLength",
ValueIsNotTupleArray = "VerifyResult.ValueIsNotTupleArray",
// DELETE
AllowPartialOptionNotBool = "VerifyResult.AllowPartialOptionNotBool",
// SUPPORTED_DM
OptionsMustBeBool = "VerifyResult.OptionsMustBeBool",
// INSTANCES
FirstLevelOnlyNotBool = "VerifyResult.FirstLevelOnlyNotBool",
// PROTO
ProtoNotString = "VerifyResult.ProtoNotString",
}
Marin Karamihalev
committed
export type GetNestedReturn =
| UspProperty
| UspPropertyList
| UspObject
| UspObjectList;
export type GetCommand = (
paths: string | string[],
options?: GetCommandOptions
) => Promise<GetReturn>;
Marin Karamihalev
committed
export type GetNestedCommand = (<T = GetNestedReturn>(
path: string,
options?: GetNestedCommandOptions
) => Promise<T>) &
(<T = GetNestedReturn>(
paths: string[],
options?: GetNestedCommandOptions
) => Promise<T[]>);
value:
| (JSValue | JSValue[] | InputRecord)
| (JSValue | JSValue[] | InputRecord)[],
options?: { raw?: false } & SetCommandOptions
) => Promise<SetResponse>) &
((
path: string | string[],
value:
| (JSValue | JSValue[] | InputRecord)
| (JSValue | JSValue[] | InputRecord)[],
options: { raw: true } & SetCommandOptions
) => Promise<SetRawResponse>) &
((
values: [string, JSValue | JSValue[] | InputRecord][],
options?: SetCommandOptions
) => Promise<SetResponse>);
export type AddCommand = ((
Marin Karamihalev
committed
path: string | string[],
| (JSValue | JSValue[] | InputRecord)
| (JSValue | JSValue[] | InputRecord)[]
| null
| undefined,
options?: { raw?: false }
) => Promise<AddResponse>) &
((
path: string | string[],
value:
| (JSValue | JSValue[] | InputRecord)
| (JSValue | JSValue[] | InputRecord)[]
| null
| undefined,
options: { raw: true }
) => Promise<AddRawResponse>) &
((
values: [string, JSValue | JSValue[] | InputRecord][],
options?: { raw?: boolean }
) => Promise<AddResponse>);
export type DelCommand = (
path: string | string[],
allowPartial?: boolean
Marin Karamihalev
committed
) => Promise<string[]>;
export type OperateSubscribeOptions = {
/**
* Skip response from calling operate, defaults to true
*/
Marin Karamihalev
committed
skipOperateResponse?: boolean;
};
export type OperateFn = {
Marin Karamihalev
committed
subscribe: (
cb: (msg: any) => void,
opts?: OperateSubscribeOptions
) => {
trigger: (input?: Record<string, any>) => Promise<any>;
};
(input?: Record<string, string>): Promise<any>;
};
export type OperateClearFn = () => Promise<void>;
export type OperateRecipe = (
path: string,
opts?: OperateOptions
) => Promise<[OperateFn, OperateClearFn]>;
export type OperateCommand = (
path: string,
id: string,
Marin Karamihalev
committed
input?: Record<string, any>
export type SupportedDMCommand = (
paths: string | string[],
opts?: SuportedCommandOpts
) => Promise<Record<string, any>>;
export type InstancesCommand = (
paths: string | string[],
opts?: { firstLevelOnly?: boolean }
) => Promise<Record<string, any>>;
export type SupportedProtoCommand = (version?: USPVersion) => Promise<string[]>;
export type SubscribeRecipe = (
opts: SubscriptionOptions,
callback: SubscriptionCallback
) => Promise<PromiseClearFn>;
export type PromiseClearFn = () => Promise<void>;
export type Command =
| GetCommand
Marin Karamihalev
committed
| GetNestedCommand
| SetCommand
| AddCommand
| DelCommand
| OperateRecipe
| SubscribeRecipe
| SupportedDMCommand
| InstancesCommand
| SupportedProtoCommand;
export type PbRequestCommand =
| PbRequestCommandGet
| PbRequestCommandSet
| PbRequestCommandAdd
| PbRequestCommandDel
| PbRequestCommandOperate
| PbRequestCommandSupport
| PbRequestCommandInstance
export interface SuportedCommandOpts {
firstLevelOnly?: boolean;
returnCommands?: boolean;
returnEvents?: boolean;
returnParams?: boolean;
export type InputRecord = {
[k: string]:
| {
required: boolean;
value: any;
}
| string
| number
| boolean;
} & { allowPartial?: boolean };
export type PbRequestCommandNotifyResp = {
notifyResp: {
subscriptionId: string;
};
};
export type PbRequestCommandNotify = {
notify: {
subscriptionId: string;
sendResp: boolean;
[key: string]: unknown;
};
};
export type PbRequestCommandSupportProto = {
getSupportedProtocol: {
controllerSupportedProtocolVersions: string;
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
};
};
export type PbRequestCommandInstance = {
getInstances: {
objPaths: string[];
firstLevelOnly: boolean;
};
};
export type PbRequestCommandSupport = {
getSupportedDm: {
objPaths: string[];
firstLevelOnly: boolean;
returnCommands: boolean;
returnEvents: boolean;
returnParams: boolean;
};
};
export type PbRequestCommandOperate = {
operate: {
command: string;
commandKey: string;
sendResp: boolean;
inputArgs: Record<string, any>;
};
};
export type PbRequestCommandDel = {
delete: {
allowPartial: boolean;
objPaths: string[];
};
};
export type PbRequestCommandGet = {
get: {
paramPaths: string[];
};
};
export type SetLookupUpdateObject = "Set.UpdateObject";
export type SetLookupUpdateParamSetting = "Set.UpdateParamSetting";
export type PbRequestCommandSet = {
set: {
allowPartial: boolean;
updateObjs: {
objPath: string;
lookup: SetLookupUpdateObject;
paramSettings: {
lookup: SetLookupUpdateParamSetting;
param: string;
value: any;
required: boolean;
}[];
}[];
};
};
Marin Karamihalev
committed
export type AddLookupCreateObject = "Add.CreateObject";
export type AddLookupCreateParamSetting = "Add.CreateParamSetting";
export type PbRequestCommandAdd = {
add: {
allowPartial: boolean;
createObjs: {
Marin Karamihalev
committed
lookup: AddLookupCreateObject;
objPath: string;
paramSettings: {
param: string;
value: any;
required: boolean;
Marin Karamihalev
committed
lookup: AddLookupCreateParamSetting;
}[];
}[];
};
};
export type Recipe = ResolveRecipe;
export type ResolveRecipe = (
msg: GetReturn,
level?: number
) => Promise<GetReturn>;
export type PreCallCallback = (name: string, args: any[]) => void;
export type PostCallCallback = (name: string, args: any[], result: any) => void;
Marin Karamihalev
committed
/** Options that allow extending command funcitonality */
export type Options = {
/** Timeout command after given number of milliseconds (throws an error for handling with catch) */
/** Call function before command */
preCall?: PreCallCallback;
/** Call after before command */
postCall?: PostCallCallback;
get?: {
/**
* Set the retainPath option to all get calls
*/
retainPath?: boolean;
/**
* Set the max depth parameter to all get calls
*/
max_depth?: number;
Marin Karamihalev
committed
};
export interface USP {
Marin Karamihalev
committed
* @param path Location of value (e.g. "Device.DeviceInfo." or an array of multiple paths)
* @param options Get options (not required)
* await usp.get(["Device.WiFi.Radio.1.", "Device.WiFi.Radio.2."])
*
* await usp.get("Device.WiFi.Radio.1.", { raw: true }) // skips parsing, produces raw results
get: GetCommand;
Marin Karamihalev
committed
/**
* Get value at path, returns values with their full path stored in "__query__" key
* @param path Location of value (e.g. "Device.DeviceInfo." or an array of multiple paths)
* @param options Get options (not required)
* ```
* await usp.getNested("Device.WiFi.Radio.1.")
*
* await usp.getNested(["Device.WiFi.Radio.1.", "Device.WiFi.Radio.2."])
*
* await usp.getNested("Device.WiFi.Radio.1.", { max_depth: 4 })
* // providing return type
* await usp.getNested<UspProperty>("Device.WiFi.Radio.1.Alias")
*
* await usp.getNested<UspPropertyList>("Device.WiFi.Radio.*.Alias")
*
* await usp.getNested<UspObject>("Device.WiFi.Radio.1.")
*
* await usp.getNested<UspObjectList>("Device.WiFi.Radio.*.")
*
* await usp.getNested<UspProperty>(["Device.WiFi.Radio.1.Alias", "Device.WiFi.Radio.2.Alias"])
* ```
*/
getNested: GetNestedCommand;
* Set value at path
* @param path Location of value (e.g. "Device.DeviceInfo.")
* @param value Value to assign
* @returns Object that respresents executed change
* ```
* await usp.set("Device.WiFi.Radio.1.", { Name: "radio-1" })
* await usp.set("Device.WiFi.Radio.1.Name", "radio-1")
* // or
* await usp.set(
["Device.NAT.PortMapping.1.", "Device.NAT.PortMapping.2."],
[{ Description: "cat-1" }, { Description: "cat-2" }]
)
* // or
* await device.set([
["Device.NAT.PortMapping.1.Description", "desc 1"],
["Device.NAT.PortMapping.2.Description", "desc 2"],
]);
set: SetCommand;
/**
* Create a command
* @param path Full path of command (e.g. "Device.IP.Diagnostics.IPPing()")
* @param opts Subscription options (not required)
* @returns Function that executes command
* const [ping, cleanPing] = await usp.operate("Device.IP.Diagnostics.IPPing()")
* const results = await ping({ Host: "iopsys.eu" })
* await cleanPing()
Marin Karamihalev
committed
* // sync command example, no need to get cleanup function as there is nothing to clean up with sync commands
* const [op] = await device.operate("Device.WiFi.Reset()", { isAsync: false })
* await op().then(log).catch(log)
operate: OperateRecipe;
* Directly call operate without creating a subscription (avoid using unless certain subscription exists),
* useful for calling sync operate commands for which either output is expected in response or
* no output is expected
* @param path Full path of command (e.g. "Device.IP.Diagnostics.IPPing()")
* @param id Full id of subscription (can be found in Device.LocalAgent.Subscription.)
* @param resp to get the response of operate command, useful when response has output
* @param input Optional arguments for command
* @returns Command results
* ```
* await usp._operate("Device.Reboot()", 'msg-1', false)
* await usp._operate("Device.LocalAgent.ControllerTrust.RequestChallenge()", 'msg-2', true, {ChallengeRef: "Device.LocalAgent.ControllerTrust.Challenge.1"})
* ```
*/
_operate: OperateCommand;
Marin Karamihalev
committed
* @param path Path to add to (e.g. "Device.NAT.PortMapping." or ["Device.NAT.PortMapping."] for multiple)
* @param values Optional object to add (if skipped will use default values), allows using arrays for multiple objects
* @returns Full path(s) of new object(s)
Marin Karamihalev
committed
* await usp.add("Device.NAT.PortMapping.", { Description: "cpe-1" })
* await usp.add("Device.NAT.PortMapping.", { Description: "cpe-1", allowPartial: true })
Marin Karamihalev
committed
* await usp.add("Device.NAT.PortMapping.", { Description: { value: "cpe-1", required: false }, allowPartial: true })
* await usp.add(
["Device.NAT.PortMapping.", "Device.NAT.PortMapping."],
[{ Description: "cpe-1" }, { Description: "cpe-2" }]
);
* await device.add([
["Device.NAT.PortMapping.", { Description: "bbbb" }],
["Device.NAT.PortMapping.", { Description: "bbbb" }],
]);
add: AddCommand;
* Delete object at path
* @param path Full path to delete (e.g. "Device.NAT.PortMapping.1.")
* @param allowPartial [Optional] Allow partial (defaults to false)
Marin Karamihalev
committed
* @returns String array of affected paths
* ```
* await usp.del("Device.NAT.PortMapping.1.")
* await usp.del("Device.NAT.PortMapping.1.", true)
del: DelCommand;
* Resolve references in message
* @param msg Message with reference in it
* @param level Optional level of nesting to resolve to (avoid using high numbers)
* ```
* await usp.get("Device.WiFi.Radio.1.").then(device.resolve)
* ```
*/
resolve: ResolveRecipe;
/**
* Get Supported DM
* @param paths Path(s)
* @param opts [Optional] Response options
* ```
* await usp.supportedDM("Device.WiFi.")
* ```
*/
supportedDM: SupportedDMCommand;
/**
* @param versions Controller supported protocol versions
supportedProto: SupportedProtoCommand;
* Get instances
* @param paths Path(s)
* @param opts [Optional] Response options
* await usp.instances("Device.WiFi.", { firstLevelOnly: true })
instances: InstancesCommand;
/**
* Subscribe to event
* @param options Subscription options
* @param callback Callback on relevant message
* @returns Returns function to clear subscription
* ```
* const clearSub = await usp.subscribe({ id: '1234', notif: 'ObjectCreation', reference: 'Device.NAT.PortMapping.' }, console.log)
* ```
*/
subscribe: SubscribeRecipe;
/**
* Add handler for messages
* @param ident Message identifier (identifies by id, can be a string or regexp)
* @param callback Callback on relevant message
* @returns Returns function to clear handler
* ```
* const clear = usp.on("error", () => console.log('An error!'))
* ```
*/
on: OnFn;
/**
* Disconnect from device
Marin Karamihalev
committed
/**
* Add general options to commands, extending their functionality
* @param opts Options
* @returns Entire USP API
* ```
* await usp.options({ timeout: 1000 }).get("Device.DeviceInfo.SerialNumber")
* ```
*/
options: (opts: Options) => USP;
Marin Karamihalev
committed
/**
* Gets current usp version (used by usp-js library for parsing incoming messages)
* @returns USP Version
* ```
* usp.getUspVersion()
* ```
*/
getUSPVersion: () => USPVersion;
}
export type BaseRecord = {
version: USPVersion;
toId: string;
fromId: string;
disconnect?: string;
noSessionContext?: {
payload: string;
sessionContext?: {
payload: string[];
/**
* Connect to device
* @param opts - Connection options
* @param events - Optional event handlers
* @returns A set of functions for interacting with the device
*/
export type Connect = (
options: ConnectionOptions,
events?: ConnectionEvents
) => Promise<USP>;
type NotifType =
| "Event"
| "ValueChange"
| "ObjectCreation"
| "ObjectDeletion"
| "OperationComplete"
| "OnBoardRequest";
export interface SubscriptionOptions {
Marin Karamihalev
committed
id?: string;
notif: NotifType;
reference: string | string[];
export type SubscriptionCallback = (
msg: Response,
fullMsg?: Record<string, any>
) => void;
export interface OperateOptions {
Marin Karamihalev
committed
sendResponse?: boolean;
export interface PbRequestHeader {
msgId: string;
msgType: CommandType;
lookup: "Header";
export interface PbRequestBody {
lookup: "Body";
request: {
lookup: "Request";
} & PbRequestCommand;
export interface PbRequestMessage {
header: PbRequestHeader;
body: PbRequestBody;
lookup: "Msg";
export type URLConnectionOptions = {
url: string;
} & MainConnectionOptions;
export type HostConnectionOptions = {
host: string;
port: number;
protocol: "wss" | "ws" | "mqtt" | "mqtts" | "tcp" | "ssl" | "wx" | "wxs";
} & MainConnectionOptions;
export type CertType = string | string[] | Buffer | Buffer[];
export type USPVersion = (typeof knownUSPVersions)[number];
export interface MainConnectionOptions {
username: string;
password: string;
Marin Karamihalev
committed
fromId?: string;
toId?: string;
idEndpoint?: string;
publishEndpoint?: string;
subscribeEndpoint?: string;
ca?: CertType | Object[];
key?: CertType;
cert?: CertType;
Marin Karamihalev
committed
useSession?: boolean;
/**
* Close connection if disconnected
*/
closeOnDisconnect?: boolean;
/**
* Timeout in milliseconds for connection
*/
connectTimeout?: number;
/**
* Defaults to false
*/
cleanSession?: boolean;
/**
* Allows passing additional options to the underlying connection library
*/
[key: string]: any;
export type MqttOptions = {
reconnectPeriod?: number;
};
export type ConnectionOptions = URLConnectionOptions | HostConnectionOptions;
export type Response = string | Record<string, any>;
export type CommandOptions = GetCommandOptions;
export type DecodeOptions = {
raw?: boolean;
};
export type DecodeFn = (
msg: Record<string, any>,
decodeOptions?: DecodeOptions
) => DecodeResponse | [any];
export type DecodeResponse =
| [any]
| [any, ResponseID | null, null | Response]
| [any, ResponseID | null, null | Response, CommandType];
export type EncodeArgs = {
header: any;
options: Record<string, string>;
args: Record<string, any>;
};
export type OnIdent = string | RegExp;
sendResp: boolean;
};
export type OnCallback = (
msg: Response,
fullMsg?: Record<string, any>,
opts?: CallbackOptions
) => void;
export type EncodeFn = (args: Record<string, any>) => PbRequestMessage;
export type CallArgs = Record<string, any>;
export type ClearFn = () => void;
export type OnFn = (ident: OnIdent, callback: OnCallback) => ClearFn;
export type MakeFn = (call: CallFn, on: OnFn) => Command;
export type MakeRecipeFn = (call: CallFn) => Recipe;
export type CommandTrigger = {
decode: string | ((msg: Record<string, string>) => boolean);
encode: string;
};
export type CommandObject = {
encode: EncodeFn;
decode: DecodeFn;
};
export interface ConnectionEvents {
onError?: (err: string) => void;
onOffline?: () => void;
onReconnect?: () => void;
onClose?: () => void;
export interface RecipeObject {
name: string;
make: MakeFn;
export type CallOptions = {
responseMsgType?: CommandType;
};
export type ResponseID = "ignore" | "error" | string;
export type JSValue = string | number | boolean;
export type CallFn = (
cmd: CommandType,
args: Record<string, any>,
callOpts?: CallOptions
) => Promise<any>;
export type ConnectionClient = {
on: (key: string, responseFn: (topic: string, data: any) => void) => void;
subscribe: (to: string) => void;
unsubscribe: (from: string) => void;
publish: (endpoint: string, msg: any) => void;
end: () => void;
};
export type ConnectClientFn = (
options: ConnectionOptions
) => Promise<ConnectionClient>;
export type DecodeIDFn = (data: any) => string;
export type Proto = {
rootRecord: any;
rootMsg: any;
export type LoadProtobufFn = (version: USPVersion) => Promise<Proto>;
export type BuildConnectionFn = (connectConfig: {
connectClient: ConnectClientFn;
decodeID: DecodeIDFn;
loadProtobuf: LoadProtobufFn;