From 3e4a17ee486df25e3dd1a255cb92525b296adfec Mon Sep 17 00:00:00 2001 From: Marin Karamihalev <marin.karamihalev@iopsys.eu> Date: Thu, 1 Sep 2022 09:49:36 +0200 Subject: [PATCH] partial progress to v12 --- src/commands/{ => 1.0,1.1}/add.ts | 6 +-- src/commands/{ => 1.0,1.1}/del.ts | 4 +- src/commands/{ => 1.0,1.1}/get.ts | 4 +- src/commands/1.0,1.1/index.ts | 21 ++++++++ src/commands/{ => 1.0,1.1}/instances.ts | 4 +- src/commands/{ => 1.0,1.1}/notify.ts | 4 +- src/commands/{ => 1.0,1.1}/operate.ts | 4 +- src/commands/{ => 1.0,1.1}/proto.ts | 10 ++-- src/commands/{ => 1.0,1.1}/set.ts | 4 +- src/commands/{ => 1.0,1.1}/supported.ts | 4 +- src/commands/1.2/add.ts | 64 +++++++++++++++++++++++ src/commands/1.2/del.ts | 31 +++++++++++ src/commands/1.2/get.ts | 62 ++++++++++++++++++++++ src/commands/1.2/index.ts | 21 ++++++++ src/commands/1.2/instances.ts | 31 +++++++++++ src/commands/1.2/notify.ts | 42 +++++++++++++++ src/commands/1.2/operate.ts | 40 ++++++++++++++ src/commands/1.2/proto.ts | 30 +++++++++++ src/commands/1.2/set.ts | 69 +++++++++++++++++++++++++ src/commands/1.2/supported.ts | 34 ++++++++++++ src/commands/index.ts | 58 +++++++++++---------- src/commands/util.ts | 10 ++-- src/configurations/build.ts | 25 +++++---- src/configurations/mqtt.ts | 7 +-- src/configurations/util.ts | 11 ++++ src/configurations/ws.ts | 4 +- src/specs/usp-msg-1-1.js | 2 +- src/specs/usp-msg-1-2.js | 1 + src/specs/usp-record-1-1.js | 2 +- src/specs/usp-record-1-2.js | 1 + src/types.ts | 17 ++++-- 31 files changed, 553 insertions(+), 74 deletions(-) rename src/commands/{ => 1.0,1.1}/add.ts (94%) rename src/commands/{ => 1.0,1.1}/del.ts (85%) rename src/commands/{ => 1.0,1.1}/get.ts (95%) create mode 100644 src/commands/1.0,1.1/index.ts rename src/commands/{ => 1.0,1.1}/instances.ts (87%) rename src/commands/{ => 1.0,1.1}/notify.ts (91%) rename src/commands/{ => 1.0,1.1}/operate.ts (93%) rename src/commands/{ => 1.0,1.1}/proto.ts (67%) rename src/commands/{ => 1.0,1.1}/set.ts (96%) rename src/commands/{ => 1.0,1.1}/supported.ts (89%) create mode 100644 src/commands/1.2/add.ts create mode 100644 src/commands/1.2/del.ts create mode 100644 src/commands/1.2/get.ts create mode 100644 src/commands/1.2/index.ts create mode 100644 src/commands/1.2/instances.ts create mode 100644 src/commands/1.2/notify.ts create mode 100644 src/commands/1.2/operate.ts create mode 100644 src/commands/1.2/proto.ts create mode 100644 src/commands/1.2/set.ts create mode 100644 src/commands/1.2/supported.ts create mode 100644 src/configurations/util.ts create mode 100644 src/specs/usp-msg-1-2.js create mode 100644 src/specs/usp-record-1-2.js diff --git a/src/commands/add.ts b/src/commands/1.0,1.1/add.ts similarity index 94% rename from src/commands/add.ts rename to src/commands/1.0,1.1/add.ts index 3298468..96a18df 100644 --- a/src/commands/add.ts +++ b/src/commands/1.0,1.1/add.ts @@ -1,6 +1,6 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; -import { AddLookupCreateObject, AddLookupCreateParamSetting } from "../types"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; +import { AddLookupCreateObject, AddLookupCreateParamSetting } from "../../types"; const decode: DecodeFn = (msg) => { const paths: string[] | undefined = util.searchAll(msg, "instantiatedPath"); diff --git a/src/commands/del.ts b/src/commands/1.0,1.1/del.ts similarity index 85% rename from src/commands/del.ts rename to src/commands/1.0,1.1/del.ts index 9fcf04d..77bab50 100644 --- a/src/commands/del.ts +++ b/src/commands/1.0,1.1/del.ts @@ -1,5 +1,5 @@ -import { DecodeFn, EncodeFn } from "../types"; -import { uniq, searchAll } from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import { uniq, searchAll } from "../util"; const decode: DecodeFn = (msg) => { const affectedPaths = searchAll(msg, "affectedPaths") || []; diff --git a/src/commands/get.ts b/src/commands/1.0,1.1/get.ts similarity index 95% rename from src/commands/get.ts rename to src/commands/1.0,1.1/get.ts index 591d5f5..d5d11f1 100644 --- a/src/commands/get.ts +++ b/src/commands/1.0,1.1/get.ts @@ -1,5 +1,5 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (msg, decodeOptions) => { const resolvedPathResultsArr = util.searchAll(msg, "resolvedPathResults"); diff --git a/src/commands/1.0,1.1/index.ts b/src/commands/1.0,1.1/index.ts new file mode 100644 index 0000000..bc09adf --- /dev/null +++ b/src/commands/1.0,1.1/index.ts @@ -0,0 +1,21 @@ +import get from "./get"; +import set from "./set"; +import add from "./add"; +import del from "./del"; +import operate from "./operate"; +import supported from "./supported"; +import proto from "./proto"; +import instances from "./instances"; +import notify from "./notify"; + +export default { + GET: get, + ADD: add, + DELETE: del, + GET_INSTANCES: instances, + GET_SUPPORTED_DM: supported, + GET_SUPPORTED_PROTO: proto, + NOTIFY: notify, + OPERATE: operate, + SET: set, +}; diff --git a/src/commands/instances.ts b/src/commands/1.0,1.1/instances.ts similarity index 87% rename from src/commands/instances.ts rename to src/commands/1.0,1.1/instances.ts index 6c780ed..11d274e 100644 --- a/src/commands/instances.ts +++ b/src/commands/1.0,1.1/instances.ts @@ -1,5 +1,5 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (msg) => { const results = util.search(msg, "reqPathResults"); diff --git a/src/commands/notify.ts b/src/commands/1.0,1.1/notify.ts similarity index 91% rename from src/commands/notify.ts rename to src/commands/1.0,1.1/notify.ts index 884aa2f..25ac2f9 100644 --- a/src/commands/notify.ts +++ b/src/commands/1.0,1.1/notify.ts @@ -1,5 +1,5 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; const parseInfo = (key: string, data: Record<string, any>) => util.unflatten( diff --git a/src/commands/operate.ts b/src/commands/1.0,1.1/operate.ts similarity index 93% rename from src/commands/operate.ts rename to src/commands/1.0,1.1/operate.ts index cd337dd..eaf344b 100644 --- a/src/commands/operate.ts +++ b/src/commands/1.0,1.1/operate.ts @@ -1,8 +1,8 @@ import { DecodeFn, EncodeFn, -} from "../types"; -import * as util from "./util"; +} from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (msg) => { const data = util.searchAll(msg, "operationResults"); diff --git a/src/commands/proto.ts b/src/commands/1.0,1.1/proto.ts similarity index 67% rename from src/commands/proto.ts rename to src/commands/1.0,1.1/proto.ts index 57f13ca..1b655bb 100644 --- a/src/commands/proto.ts +++ b/src/commands/1.0,1.1/proto.ts @@ -1,12 +1,12 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (msg) => { const results = util.search(msg, "agentSupportedProtocolVersions"); - return [results]; + return [results.split(",")]; }; -const encode: EncodeFn = ({ versions }) => ({ +const encode: EncodeFn = () => ({ lookup: "Msg", header: { msgId: util.uniq("GET_SUPPORTED_PROTO@"), @@ -18,7 +18,7 @@ const encode: EncodeFn = ({ versions }) => ({ request: { lookup: "Request", getSupportedProtocol: { - controllerSupportedProtocolVersions: versions, + controllerSupportedProtocolVersions: "", }, }, }, diff --git a/src/commands/set.ts b/src/commands/1.0,1.1/set.ts similarity index 96% rename from src/commands/set.ts rename to src/commands/1.0,1.1/set.ts index 3ed27b0..be08a6c 100644 --- a/src/commands/set.ts +++ b/src/commands/1.0,1.1/set.ts @@ -3,8 +3,8 @@ import { EncodeFn, SetLookupUpdateObject, SetLookupUpdateParamSetting, -} from "../types"; -import * as util from "./util"; +} from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (_msg) => { return [null]; diff --git a/src/commands/supported.ts b/src/commands/1.0,1.1/supported.ts similarity index 89% rename from src/commands/supported.ts rename to src/commands/1.0,1.1/supported.ts index b160f6f..cd3d9ce 100644 --- a/src/commands/supported.ts +++ b/src/commands/1.0,1.1/supported.ts @@ -1,5 +1,5 @@ -import { DecodeFn, EncodeFn } from "../types"; -import * as util from "./util"; +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; const decode: DecodeFn = (msg) => { const results = util.search(msg, "reqObjResults"); diff --git a/src/commands/1.2/add.ts b/src/commands/1.2/add.ts new file mode 100644 index 0000000..96a18df --- /dev/null +++ b/src/commands/1.2/add.ts @@ -0,0 +1,64 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; +import { AddLookupCreateObject, AddLookupCreateParamSetting } from "../../types"; + +const decode: DecodeFn = (msg) => { + const paths: string[] | undefined = util.searchAll(msg, "instantiatedPath"); + if (paths && paths.length === 1) return [paths[0]]; + return [paths]; +}; + +const isObj = (v) => + typeof v === "object" && v.required !== undefined && v.value !== undefined; + +const makePair = (value): [string, any, boolean][] => + value + ? Object.entries(value as any[]).map(([k, v]) => + isObj(v) + ? [k, v.value.toString(), "required" in v && Boolean(v.required)] + : [k, v.toString(), true] + ) + : []; + +const encode: EncodeFn = ({ value, path }) => { + const paths = Array.isArray(path) ? path : [path]; + const values = value ? (Array.isArray(value) ? value : [value]) : []; + const allowPartial = values && values.some((it) => it.allowPartial) || false; + + const createObjs = paths.map((path, i) => ({ + lookup: "Add.CreateObject" as AddLookupCreateObject, + objPath: path, + paramSettings: makePair(values[i]) + .filter(([k]) => k !== "allowPartial") + .map(([param, value, required]) => ({ + lookup: "Add.CreateParamSetting" as AddLookupCreateParamSetting, + param, + value, + required, + })), + })); + + return { + lookup: "Msg", + header: { + lookup: "Header", + msgId: util.uniq("ADD@"), + msgType: "ADD", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + add: { + allowPartial, + createObjs, + }, + }, + }, + }; +}; + +export default { + decode, + encode, +}; diff --git a/src/commands/1.2/del.ts b/src/commands/1.2/del.ts new file mode 100644 index 0000000..77bab50 --- /dev/null +++ b/src/commands/1.2/del.ts @@ -0,0 +1,31 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import { uniq, searchAll } from "../util"; + +const decode: DecodeFn = (msg) => { + const affectedPaths = searchAll(msg, "affectedPaths") || []; + return [affectedPaths]; +}; + +const encode: EncodeFn = ({ paths, allowPartial }) => ({ + lookup: "Msg", + header: { + msgId: uniq("DELETE@"), + msgType: "DELETE", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + delete: { + objPaths: Array.isArray(paths) ? paths : [paths], + allowPartial: allowPartial || false + }, + }, + }, +}); + +export default { + decode, + encode +}; diff --git a/src/commands/1.2/get.ts b/src/commands/1.2/get.ts new file mode 100644 index 0000000..c4a1226 --- /dev/null +++ b/src/commands/1.2/get.ts @@ -0,0 +1,62 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (msg, decodeOptions) => { + const resolvedPathResultsArr = util.searchAll(msg, "resolvedPathResults"); + if (decodeOptions?.raw) return [resolvedPathResultsArr]; + + const requestedPath = util.search(msg, "requestedPath"); + if (resolvedPathResultsArr) { + // path has search query (ex. Device.IP.Interface.[Name=="wan"].) + const pathIncludesSearch = + typeof requestedPath === "string" && + (requestedPath.includes("*") || requestedPath.includes("[")); + + const pathSplit = requestedPath.split("."); + + // found multiple items + const hasMultipleIndexes = util.hasMultipleIndexes( + resolvedPathResultsArr + .map((it) => + Object.keys(it.resultParams).map((p) => it.resolvedPath + p) + ) + .flat(1), + pathSplit + ); + + const shouldBeArray = + pathIncludesSearch || + hasMultipleIndexes + // not sure about removing this + // resolvedPathResultsArr.length > 1; + const unflattened = util.convertToNestedObject(resolvedPathResultsArr); + const unwrapped = util.fullyUnwrapObject(unflattened, shouldBeArray); + return [util.isEmpty(unwrapped) ? [] : unwrapped]; + } + return [null]; +}; + +const encode: EncodeFn = ({ paths, options }) => ({ + lookup: "Msg", + header: { + msgId: util.uniq("GET@"), + msgType: "GET", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + get: { + paramPaths: Array.isArray(paths) ? paths : [paths], + ...(Number.isInteger(options?.max_depth) ? { maxDepth: options.max_depth } : {}), + maxDepth: options.max_depth || 2 + }, + }, + }, +}); + +export default { + decode, + encode, +}; diff --git a/src/commands/1.2/index.ts b/src/commands/1.2/index.ts new file mode 100644 index 0000000..bc09adf --- /dev/null +++ b/src/commands/1.2/index.ts @@ -0,0 +1,21 @@ +import get from "./get"; +import set from "./set"; +import add from "./add"; +import del from "./del"; +import operate from "./operate"; +import supported from "./supported"; +import proto from "./proto"; +import instances from "./instances"; +import notify from "./notify"; + +export default { + GET: get, + ADD: add, + DELETE: del, + GET_INSTANCES: instances, + GET_SUPPORTED_DM: supported, + GET_SUPPORTED_PROTO: proto, + NOTIFY: notify, + OPERATE: operate, + SET: set, +}; diff --git a/src/commands/1.2/instances.ts b/src/commands/1.2/instances.ts new file mode 100644 index 0000000..11d274e --- /dev/null +++ b/src/commands/1.2/instances.ts @@ -0,0 +1,31 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (msg) => { + const results = util.search(msg, "reqPathResults"); + return [results]; +}; + +const encode: EncodeFn = ({ paths, opts = {} }) => ({ + lookup: "Msg", + header: { + msgId: util.uniq("GET_INSTANCES@"), + msgType: "GET_INSTANCES", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + getInstances: { + objPaths: Array.isArray(paths) ? paths : [paths], + firstLevelOnly: opts.firstLevelOnly || false + }, + }, + }, +}); + +export default { + decode, + encode +}; diff --git a/src/commands/1.2/notify.ts b/src/commands/1.2/notify.ts new file mode 100644 index 0000000..25ac2f9 --- /dev/null +++ b/src/commands/1.2/notify.ts @@ -0,0 +1,42 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; + +const parseInfo = (key: string, data: Record<string, any>) => + util.unflatten( + util.search(data, key === "operComplete" ? "outputArgs" : key) || {} + ); + +const decode: DecodeFn = (msg) => { + const parent = util.searchParent(msg, "subscriptionId"); + if (parent) { + const id = parent.subscriptionId; + const relField = Object.keys(parent).find((k) => k !== "subscriptionId"); + return id && relField + ? [parseInfo(relField, msg), id, null] + : [null, id, null]; + } + return [null]; +}; + +const encode: EncodeFn = ({ paths }) => ({ + lookup: "Msg", + header: { + msgId: util.uniq("NOTIFY@"), + msgType: "GET", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + get: { + paramPaths: Array.isArray(paths) ? paths : [paths], + }, + }, + }, +}); + +export default { + decode, + encode, +}; diff --git a/src/commands/1.2/operate.ts b/src/commands/1.2/operate.ts new file mode 100644 index 0000000..eaf344b --- /dev/null +++ b/src/commands/1.2/operate.ts @@ -0,0 +1,40 @@ +import { + DecodeFn, + EncodeFn, +} from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (msg) => { + const data = util.searchAll(msg, "operationResults"); + const output = util.search(data, 'reqOutputArgs'); + if (output) return [output]; + if (data && data.length === 1) return [util.unflatten(data[0])]; + const unflattened = data.map((v) => util.unflatten(v)); + return [unflattened]; +}; + +const encode: EncodeFn = ({ path, input, id, resp }) => ({ + lookup: "Msg", + header: { + msgId: id, + msgType: "OPERATE", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + operate: { + command: path, + commandKey: "", + sendResp: resp, + inputArgs: input || {}, + }, + }, + }, +}); + +export default { + decode, + encode +}; diff --git a/src/commands/1.2/proto.ts b/src/commands/1.2/proto.ts new file mode 100644 index 0000000..1b655bb --- /dev/null +++ b/src/commands/1.2/proto.ts @@ -0,0 +1,30 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (msg) => { + const results = util.search(msg, "agentSupportedProtocolVersions"); + return [results.split(",")]; +}; + +const encode: EncodeFn = () => ({ + lookup: "Msg", + header: { + msgId: util.uniq("GET_SUPPORTED_PROTO@"), + msgType: "GET_SUPPORTED_PROTO", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + getSupportedProtocol: { + controllerSupportedProtocolVersions: "", + }, + }, + }, +}); + +export default { + decode, + encode +}; diff --git a/src/commands/1.2/set.ts b/src/commands/1.2/set.ts new file mode 100644 index 0000000..be08a6c --- /dev/null +++ b/src/commands/1.2/set.ts @@ -0,0 +1,69 @@ +import { + DecodeFn, + EncodeFn, + SetLookupUpdateObject, + SetLookupUpdateParamSetting, +} from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (_msg) => { + return [null]; +}; + +const isObject = (v) => + typeof v === "object" && v.required !== undefined && v.value !== undefined; + +const makePairs = (path: string, value): [string, any, boolean][] => + path.endsWith(".") && typeof value === "object" && value !== null + ? Object.entries(value as any[]).map(([k, v]) => + isObject(v) + ? [k, v.value.toString(), "required" in v && Boolean(v.required)] + : [k, v.toString(), true] + ) + : [[path.split(".").pop() || "", (value || "").toString(), true]]; + +const encode: EncodeFn = ({ value, path: initialPath }) => { + const paths = Array.isArray(initialPath) ? initialPath : [initialPath]; + const values = value ? (Array.isArray(value) ? value : [value]) : []; + const allowPartial = + (values && values.some((it) => it.allowPartial)) || false; + + const updateObjs = paths.map((path, i) => ({ + lookup: "Set.UpdateObject" as SetLookupUpdateObject, + objPath: path.endsWith(".") + ? path + : path.slice(0, path.lastIndexOf(".") + 1), + paramSettings: makePairs(path, values[i]) + .filter(([k]) => k !== "allowPartial") + .map(([param, value, required]) => ({ + lookup: "Set.UpdateParamSetting" as SetLookupUpdateParamSetting, + param, + value, + required, + })), + })); + + return { + lookup: "Msg", + header: { + lookup: "Header", + msgId: util.uniq("SET@"), + msgType: "SET", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + set: { + allowPartial, + updateObjs, + }, + }, + }, + }; +}; + +export default { + decode, + encode, +}; diff --git a/src/commands/1.2/supported.ts b/src/commands/1.2/supported.ts new file mode 100644 index 0000000..cd3d9ce --- /dev/null +++ b/src/commands/1.2/supported.ts @@ -0,0 +1,34 @@ +import { DecodeFn, EncodeFn } from "../../types"; +import * as util from "../util"; + +const decode: DecodeFn = (msg) => { + const results = util.search(msg, "reqObjResults"); + return [results]; +}; + +const encode: EncodeFn = ({ paths, opts = {} }) => ({ + lookup: "Msg", + header: { + msgId: util.uniq("GET_SUPPORTED_DM@"), + msgType: "GET_SUPPORTED_DM", + lookup: "Header", + }, + body: { + lookup: "Body", + request: { + lookup: "Request", + getSupportedDm: { + objPaths: Array.isArray(paths) ? paths : [paths], + firstLevelOnly: opts.firstLevelOnly || false, + returnCommands: opts.returnCommands || false, + returnEvents: opts.returnEvents || false, + returnParams: opts.returnParams || false, + }, + }, + }, +}); + +export default { + decode, + encode +}; diff --git a/src/commands/index.ts b/src/commands/index.ts index c22f96e..18895d3 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -9,32 +9,20 @@ import { DecodeResponse, Proto, DecodeOptions, + USPVersion, } from "../types"; -import get from "./get"; -import set from "./set"; -import add from "./add"; -import del from "./del"; -import operate from "./operate"; -import supported from "./supported"; -import proto from "./proto"; -import instances from "./instances"; -import notify from "./notify"; - import resolve from "./recipes/resolve"; import operateRecipe from "./recipes/operate"; import subscribe from "./recipes/subscribe"; -const commands: Record<CommandType, CommandObject> = { - GET: get, - ADD: add, - DELETE: del, - GET_INSTANCES: instances, - GET_SUPPORTED_DM: supported, - GET_SUPPORTED_PROTO: proto, - NOTIFY: notify, - OPERATE: operate, - SET: set, +import v10 from "./1.0,1.1"; +import v12 from "./1.2"; + +const commands: Record<USPVersion, Record<CommandType, CommandObject>> = { + "1.0": v10, + "1.1": v10, + "1.2": v12, }; const recipes: RecipeObject[] = [resolve as any, operateRecipe, subscribe]; @@ -53,7 +41,9 @@ const unkownErr = ( export const readMsg = (proto: Proto, data: any): Record<string, any> => { const record = proto.rootRecord.lookupType("usp_record.Record"); - const decodedRecord: any = record.decode('binaryData' in data ? data.binaryData : data); + const decodedRecord: any = record.decode( + "binaryData" in data ? data.binaryData : data + ); const msg = proto.rootMsg.lookupType("usp.Msg"); const decodedMsg = msg.decode(decodedRecord.noSessionContext.payload); @@ -61,11 +51,13 @@ export const readMsg = (proto: Proto, data: any): Record<string, any> => { return JSON.parse(JSON.stringify(decodedMsg)); // forces conversions }; -export const decode = (parsedMsg: any): DecodeResponse => { +type DecodeFn = (parsedMsg: any, version: USPVersion) => DecodeResponse; + +export const decode: DecodeFn = (parsedMsg, version: USPVersion) => { const err = searchParent(parsedMsg, "errMsg") || null; const command = extractCommand(parsedMsg); const foundId = search(parsedMsg, "msgId"); - + // if id is formatted by me (command@) then use, otherwise check for sub id const id = foundId.includes("@") ? foundId @@ -75,19 +67,28 @@ export const decode = (parsedMsg: any): DecodeResponse => { if (!command) return unkownErr(parsedMsg); if (err) return [id, null, err, command]; - const cmd: CommandObject | null = commands[command] || null; + const cmd: CommandObject | null = commands[version][command] || null; if (!cmd) return unkownErr(parsedMsg); const [decodedData, decodedId, decodedErr] = cmd.decode(parsedMsg); return [decodedId || id, decodedData, decodedErr || err, command]; }; -export const decodeWithOptions = ( +type DecodeWithOptionsFn = ( parsedMsg: any, cmdType: CommandType | undefined, - options: DecodeOptions + options: DecodeOptions, + version: USPVersion +) => any; + +export const decodeWithOptions: DecodeWithOptionsFn = ( + parsedMsg, + cmdType, + options, + version: USPVersion ) => { - const cmd: CommandObject | null = commands[cmdType as CommandType] || null; + const cmd: CommandObject | null = + commands[version][cmdType as CommandType] || null; if (!cmd) return unkownErr(parsedMsg); const [decodedData] = cmd.decode(parsedMsg, options); @@ -98,9 +99,10 @@ export const makeEncode = (proto: Proto, options?: Record<string, string>) => ( command: CommandType, + version: USPVersion, args: Record<string, any> ): [string, any, string | null] => { - const cmd = commands[command] || null; + const cmd = commands[version][command] || null; if (!cmd) return ["error", null, `Uknown command: ${command}`]; return [...convert(proto, cmd.encode(args), options)]; }; diff --git a/src/commands/util.ts b/src/commands/util.ts index 69338e8..5330dee 100644 --- a/src/commands/util.ts +++ b/src/commands/util.ts @@ -143,16 +143,20 @@ export const isEmpty = (obj: any): boolean => typeof obj === "object" && Object.keys(obj).length === 0; +const clearObj = (obj) => + isObject(obj) && Object.keys(obj).length === 1 ? Object.values(obj)[0] : obj; + export const fullyUnwrapObject = (obj: any, shouldBeArray: boolean) => { if (isObject(obj) && Object.keys(obj).length === 1) return fullyUnwrapObject(Object.values(obj)[0], shouldBeArray); + const simplifiedObj = clearObj(obj); const isArray = Array.isArray(obj); if (shouldBeArray) - if (isArray) return obj.filter((v) => !isEmpty(v)); - else return isEmpty(obj) ? [] : [obj]; + if (isArray) return obj.filter((v) => !isEmpty(v)).map(clearObj); + else return isEmpty(obj) ? [] : [clearObj(obj)]; else if (isArray) return fullyUnwrapObject( - obj.find((v) => !isEmpty(v)), + obj.find((v) => !isEmpty(v)).map(clearObj), shouldBeArray ); else return obj; diff --git a/src/configurations/build.ts b/src/configurations/build.ts index ab2580f..0dc9d4b 100644 --- a/src/configurations/build.ts +++ b/src/configurations/build.ts @@ -1,9 +1,9 @@ import { - decode, - decodeWithOptions, makeEncode, makeRecipes, readMsg, + decode, + decodeWithOptions, } from "../commands"; import { CallFn, @@ -90,12 +90,19 @@ const buildConnect: BuildConnectionFn = options.subscribeEndpoint || defaultSubscribeEndpoint; const publishEndpoint = options.publishEndpoint || defaultPublishEndpoint; const idEndpoint = options.idEndpoint || defaultIdEndpoint; + let version = options.version || "1.1"; - const proto: Proto = await loadProtobuf(); + const proto: Proto = await loadProtobuf(version); const router = makeRouter(); const callbackRouter = makeCallbackRouter(); + const connectTimeout = options.connectTimeout || defaultConnectionTimeout; + const client = await timeoutWrapper( + () => connectClient(options), + connectTimeout + ); + const handleError = (err: any) => events && events.onError && events.onError(err); const handleOffline = () => { @@ -108,9 +115,6 @@ const buildConnect: BuildConnectionFn = callbackRouter.add("error", handleError); - const connectTimeout = options.connectTimeout || defaultConnectionTimeout; - const client = await timeoutWrapper(() => connectClient(options), connectTimeout); - const handleInit = () => new Promise<string>((resolve, reject) => { const id = setTimeout( @@ -133,7 +137,7 @@ const buildConnect: BuildConnectionFn = client.on("message", (_topic, data: any) => { const parsedMsg = readMsg(proto, data || _topic); - const [id, message, err, cmdType] = decode(parsedMsg); + const [id, message, err, cmdType] = decode(parsedMsg, version); if (typeof id !== "string") { handleError( `Could not locate id for message:\n${JSON.stringify( @@ -150,7 +154,8 @@ const buildConnect: BuildConnectionFn = const messageAfterOptions = decodeWithOptions( parsedMsg, cmdType, - call.options + call.options, + version ); call.resolve(messageAfterOptions); } else call.resolve(message); @@ -198,7 +203,7 @@ const buildConnect: BuildConnectionFn = const encode = makeEncode(proto, { fromId, toId }); const call: CallFn = (command, args, callOpts) => new Promise((resolve, reject) => { - const [id, msg, err] = encode(command, args); + const [id, msg, err] = encode(command, version, args); if (err) reject(err); else { router.add(id, callOpts?.responseMsgType || command, { @@ -219,7 +224,7 @@ const buildConnect: BuildConnectionFn = del: (paths, allowPartial) => call("DELETE", { paths, allowPartial }), instances: (paths, opts) => call("GET_INSTANCES", { paths, opts }), supportedDM: (paths, opts) => call("GET_SUPPORTED_DM", { paths, opts }), - supportedProto: (versions) => call("GET_SUPPORTED_PROTO", { versions }), + getSupportedProtocols: () => call("GET_SUPPORTED_PROTO", {}), _operate: (path, id, resp, input) => call("OPERATE", { path, input, id, resp }), on, diff --git a/src/configurations/mqtt.ts b/src/configurations/mqtt.ts index 4d7658c..07911b0 100644 --- a/src/configurations/mqtt.ts +++ b/src/configurations/mqtt.ts @@ -6,12 +6,12 @@ import { URLConnectionOptions, Proto, ConnectClientFn, + USPVersion, } from "../types"; import buildConnect from "./build"; import protobuf from "protobufjs"; -import rootRecordJson from "../specs/usp-record-1-1"; -import rootMsgJson from "../specs/usp-msg-1-1"; +import { jsonRoots } from "./util"; const isURL = (opts: ConnectionOptions): opts is URLConnectionOptions => "url" in opts; @@ -29,7 +29,8 @@ const connectClient: ConnectClientFn = async (opts) => } as any) as unknown as ConnectionClient) : (mqttAsync.connectAsync(opts) as unknown as ConnectionClient); -const loadProtobuf = async (): Promise<Proto> => { +const loadProtobuf = async (version: USPVersion): Promise<Proto> => { + const [rootRecordJson, rootMsgJson] = jsonRoots[version]; const rootRecord = protobuf.Root.fromJSON(rootRecordJson); const rootMsg = protobuf.Root.fromJSON(rootMsgJson); const header: any = rootMsg.lookupType("usp.Header"); diff --git a/src/configurations/util.ts b/src/configurations/util.ts new file mode 100644 index 0000000..4b6b203 --- /dev/null +++ b/src/configurations/util.ts @@ -0,0 +1,11 @@ +import rootRecordJson11 from "../specs/usp-record-1-1"; +import rootMsgJson11 from "../specs/usp-msg-1-1"; +import rootRecordJson12 from "../specs/usp-record-1-2"; +import rootMsgJson12 from "../specs/usp-msg-1-2"; +import { USPVersion } from "../types"; + +export const jsonRoots: Record<USPVersion, [any, any]> = { + "1.0": [rootRecordJson11, rootMsgJson11], + "1.1": [rootRecordJson11, rootMsgJson11], + "1.2": [rootRecordJson12, rootMsgJson12], +} diff --git a/src/configurations/ws.ts b/src/configurations/ws.ts index d8a0ab7..2862b1f 100644 --- a/src/configurations/ws.ts +++ b/src/configurations/ws.ts @@ -1,6 +1,6 @@ import { client as WebSocketClient } from "websocket"; import { decodeId } from "../commands"; -import { ConnectionOptions, Proto, ConnectClientFn } from "../types"; +import { Proto, ConnectClientFn, USPVersion } from "../types"; import buildConnect from "./build"; import protobuf from "protobufjs"; @@ -28,7 +28,7 @@ const connectClient: ConnectClientFn = (opts: any) => client.connect(`${opts.protocol}://${opts.host}:${opts.port}/usp/endpoint`, "v1.usp"); }); -const loadProtobuf = async (): Promise<Proto> => { +const loadProtobuf = async (version: USPVersion): Promise<Proto> => { const rootRecord = protobuf.Root.fromJSON(rootRecordJson); const rootMsg = protobuf.Root.fromJSON(rootMsgJson); const header: any = rootMsg.lookupType("usp.Header"); diff --git a/src/specs/usp-msg-1-1.js b/src/specs/usp-msg-1-1.js index 51c8de1..bd189ef 100644 --- a/src/specs/usp-msg-1-1.js +++ b/src/specs/usp-msg-1-1.js @@ -1 +1 @@ -export default {"nested":{"usp":{"nested":{"Msg":{"fields":{"header":{"type":"Header","id":1},"body":{"type":"Body","id":2}}},"Header":{"fields":{"msgId":{"type":"string","id":1},"msgType":{"type":"MsgType","id":2}},"nested":{"MsgType":{"values":{"ERROR":0,"GET":1,"GET_RESP":2,"NOTIFY":3,"SET":4,"SET_RESP":5,"OPERATE":6,"OPERATE_RESP":7,"ADD":8,"ADD_RESP":9,"DELETE":10,"DELETE_RESP":11,"GET_SUPPORTED_DM":12,"GET_SUPPORTED_DM_RESP":13,"GET_INSTANCES":14,"GET_INSTANCES_RESP":15,"NOTIFY_RESP":16,"GET_SUPPORTED_PROTO":17,"GET_SUPPORTED_PROTO_RESP":18}}}},"Body":{"oneofs":{"msgBody":{"oneof":["request","response","error"]}},"fields":{"request":{"type":"Request","id":1},"response":{"type":"Response","id":2},"error":{"type":"Error","id":3}}},"Request":{"oneofs":{"reqType":{"oneof":["get","getSupportedDm","getInstances","set","add","delete","operate","notify","getSupportedProtocol"]}},"fields":{"get":{"type":"Get","id":1},"getSupportedDm":{"type":"GetSupportedDM","id":2},"getInstances":{"type":"GetInstances","id":3},"set":{"type":"Set","id":4},"add":{"type":"Add","id":5},"delete":{"type":"Delete","id":6},"operate":{"type":"Operate","id":7},"notify":{"type":"Notify","id":8},"getSupportedProtocol":{"type":"GetSupportedProtocol","id":9}}},"Response":{"oneofs":{"respType":{"oneof":["getResp","getSupportedDmResp","getInstancesResp","setResp","addResp","deleteResp","operateResp","notifyResp","getSupportedProtocolResp"]}},"fields":{"getResp":{"type":"GetResp","id":1},"getSupportedDmResp":{"type":"GetSupportedDMResp","id":2},"getInstancesResp":{"type":"GetInstancesResp","id":3},"setResp":{"type":"SetResp","id":4},"addResp":{"type":"AddResp","id":5},"deleteResp":{"type":"DeleteResp","id":6},"operateResp":{"type":"OperateResp","id":7},"notifyResp":{"type":"NotifyResp","id":8},"getSupportedProtocolResp":{"type":"GetSupportedProtocolResp","id":9}}},"Error":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2},"paramErrs":{"rule":"repeated","type":"ParamError","id":3}},"nested":{"ParamError":{"fields":{"paramPath":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3}}}}},"Get":{"fields":{"paramPaths":{"rule":"repeated","type":"string","id":1}}},"GetResp":{"fields":{"reqPathResults":{"rule":"repeated","type":"RequestedPathResult","id":1}},"nested":{"RequestedPathResult":{"fields":{"requestedPath":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3},"resolvedPathResults":{"rule":"repeated","type":"ResolvedPathResult","id":4}}},"ResolvedPathResult":{"fields":{"resolvedPath":{"type":"string","id":1},"resultParams":{"keyType":"string","type":"string","id":2}}}}},"GetSupportedDM":{"fields":{"objPaths":{"rule":"repeated","type":"string","id":1},"firstLevelOnly":{"type":"bool","id":2},"returnCommands":{"type":"bool","id":3},"returnEvents":{"type":"bool","id":4},"returnParams":{"type":"bool","id":5}}},"GetSupportedDMResp":{"fields":{"reqObjResults":{"rule":"repeated","type":"RequestedObjectResult","id":1}},"nested":{"RequestedObjectResult":{"fields":{"reqObjPath":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3},"dataModelInstUri":{"type":"string","id":4},"supportedObjs":{"rule":"repeated","type":"SupportedObjectResult","id":5}}},"SupportedObjectResult":{"fields":{"supportedObjPath":{"type":"string","id":1},"access":{"type":"ObjAccessType","id":2},"isMultiInstance":{"type":"bool","id":3},"supportedCommands":{"rule":"repeated","type":"SupportedCommandResult","id":4},"supportedEvents":{"rule":"repeated","type":"SupportedEventResult","id":5},"supportedParams":{"rule":"repeated","type":"SupportedParamResult","id":6}}},"SupportedParamResult":{"fields":{"paramName":{"type":"string","id":1},"access":{"type":"ParamAccessType","id":2}}},"SupportedCommandResult":{"fields":{"commandName":{"type":"string","id":1},"inputArgNames":{"rule":"repeated","type":"string","id":2},"outputArgNames":{"rule":"repeated","type":"string","id":3}}},"SupportedEventResult":{"fields":{"eventName":{"type":"string","id":1},"argNames":{"rule":"repeated","type":"string","id":2}}},"ParamAccessType":{"values":{"PARAM_READ_ONLY":0,"PARAM_READ_WRITE":1,"PARAM_WRITE_ONLY":2}},"ObjAccessType":{"values":{"OBJ_READ_ONLY":0,"OBJ_ADD_DELETE":1,"OBJ_ADD_ONLY":2,"OBJ_DELETE_ONLY":3}}}},"GetInstances":{"fields":{"objPaths":{"rule":"repeated","type":"string","id":1},"firstLevelOnly":{"type":"bool","id":2}}},"GetInstancesResp":{"fields":{"reqPathResults":{"rule":"repeated","type":"RequestedPathResult","id":1}},"nested":{"RequestedPathResult":{"fields":{"requestedPath":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3},"currInsts":{"rule":"repeated","type":"CurrInstance","id":4}}},"CurrInstance":{"fields":{"instantiatedObjPath":{"type":"string","id":1},"uniqueKeys":{"keyType":"string","type":"string","id":2}}}}},"GetSupportedProtocol":{"fields":{"controllerSupportedProtocolVersions":{"type":"string","id":1}}},"GetSupportedProtocolResp":{"fields":{"agentSupportedProtocolVersions":{"type":"string","id":1}}},"Add":{"fields":{"allowPartial":{"type":"bool","id":1},"createObjs":{"rule":"repeated","type":"CreateObject","id":2}},"nested":{"CreateObject":{"fields":{"objPath":{"type":"string","id":1},"paramSettings":{"rule":"repeated","type":"CreateParamSetting","id":2}}},"CreateParamSetting":{"fields":{"param":{"type":"string","id":1},"value":{"type":"string","id":2},"required":{"type":"bool","id":3}}}}},"AddResp":{"fields":{"createdObjResults":{"rule":"repeated","type":"CreatedObjectResult","id":1}},"nested":{"CreatedObjectResult":{"fields":{"requestedPath":{"type":"string","id":1},"operStatus":{"type":"OperationStatus","id":2}},"nested":{"OperationStatus":{"oneofs":{"operStatus":{"oneof":["operFailure","operSuccess"]}},"fields":{"operFailure":{"type":"OperationFailure","id":1},"operSuccess":{"type":"OperationSuccess","id":2}},"nested":{"OperationFailure":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2}}},"OperationSuccess":{"fields":{"instantiatedPath":{"type":"string","id":1},"paramErrs":{"rule":"repeated","type":"ParameterError","id":2},"uniqueKeys":{"keyType":"string","type":"string","id":3}}}}}}},"ParameterError":{"fields":{"param":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3}}}}},"Delete":{"fields":{"allowPartial":{"type":"bool","id":1},"objPaths":{"rule":"repeated","type":"string","id":2}}},"DeleteResp":{"fields":{"deletedObjResults":{"rule":"repeated","type":"DeletedObjectResult","id":1}},"nested":{"DeletedObjectResult":{"fields":{"requestedPath":{"type":"string","id":1},"operStatus":{"type":"OperationStatus","id":2}},"nested":{"OperationStatus":{"oneofs":{"operStatus":{"oneof":["operFailure","operSuccess"]}},"fields":{"operFailure":{"type":"OperationFailure","id":1},"operSuccess":{"type":"OperationSuccess","id":2}},"nested":{"OperationFailure":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2}}},"OperationSuccess":{"fields":{"affectedPaths":{"rule":"repeated","type":"string","id":1},"unaffectedPathErrs":{"rule":"repeated","type":"UnaffectedPathError","id":2}}}}}}},"UnaffectedPathError":{"fields":{"unaffectedPath":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3}}}}},"Set":{"fields":{"allowPartial":{"type":"bool","id":1},"updateObjs":{"rule":"repeated","type":"UpdateObject","id":2}},"nested":{"UpdateObject":{"fields":{"objPath":{"type":"string","id":1},"paramSettings":{"rule":"repeated","type":"UpdateParamSetting","id":2}}},"UpdateParamSetting":{"fields":{"param":{"type":"string","id":1},"value":{"type":"string","id":2},"required":{"type":"bool","id":3}}}}},"SetResp":{"fields":{"updatedObjResults":{"rule":"repeated","type":"UpdatedObjectResult","id":1}},"nested":{"UpdatedObjectResult":{"fields":{"requestedPath":{"type":"string","id":1},"operStatus":{"type":"OperationStatus","id":2}},"nested":{"OperationStatus":{"oneofs":{"operStatus":{"oneof":["operFailure","operSuccess"]}},"fields":{"operFailure":{"type":"OperationFailure","id":1},"operSuccess":{"type":"OperationSuccess","id":2}},"nested":{"OperationFailure":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2},"updatedInstFailures":{"rule":"repeated","type":"UpdatedInstanceFailure","id":3}}},"OperationSuccess":{"fields":{"updatedInstResults":{"rule":"repeated","type":"UpdatedInstanceResult","id":1}}}}}}},"UpdatedInstanceFailure":{"fields":{"affectedPath":{"type":"string","id":1},"paramErrs":{"rule":"repeated","type":"ParameterError","id":2}}},"UpdatedInstanceResult":{"fields":{"affectedPath":{"type":"string","id":1},"paramErrs":{"rule":"repeated","type":"ParameterError","id":2},"updatedParams":{"keyType":"string","type":"string","id":3}}},"ParameterError":{"fields":{"param":{"type":"string","id":1},"errCode":{"type":"fixed32","id":2},"errMsg":{"type":"string","id":3}}}}},"Operate":{"fields":{"command":{"type":"string","id":1},"commandKey":{"type":"string","id":2},"sendResp":{"type":"bool","id":3},"inputArgs":{"keyType":"string","type":"string","id":4}}},"OperateResp":{"fields":{"operationResults":{"rule":"repeated","type":"OperationResult","id":1}},"nested":{"OperationResult":{"oneofs":{"operationResp":{"oneof":["reqObjPath","reqOutputArgs","cmdFailure"]}},"fields":{"executedCommand":{"type":"string","id":1},"reqObjPath":{"type":"string","id":2},"reqOutputArgs":{"type":"OutputArgs","id":3},"cmdFailure":{"type":"CommandFailure","id":4}},"nested":{"OutputArgs":{"fields":{"outputArgs":{"keyType":"string","type":"string","id":1}}},"CommandFailure":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2}}}}}}},"Notify":{"oneofs":{"notification":{"oneof":["event","valueChange","objCreation","objDeletion","operComplete","onBoardReq"]}},"fields":{"subscriptionId":{"type":"string","id":1},"sendResp":{"type":"bool","id":2},"event":{"type":"Event","id":3},"valueChange":{"type":"ValueChange","id":4},"objCreation":{"type":"ObjectCreation","id":5},"objDeletion":{"type":"ObjectDeletion","id":6},"operComplete":{"type":"OperationComplete","id":7},"onBoardReq":{"type":"OnBoardRequest","id":8}},"nested":{"Event":{"fields":{"objPath":{"type":"string","id":1},"eventName":{"type":"string","id":2},"params":{"keyType":"string","type":"string","id":3}}},"ValueChange":{"fields":{"paramPath":{"type":"string","id":1},"paramValue":{"type":"string","id":2}}},"ObjectCreation":{"fields":{"objPath":{"type":"string","id":1},"uniqueKeys":{"keyType":"string","type":"string","id":2}}},"ObjectDeletion":{"fields":{"objPath":{"type":"string","id":1}}},"OperationComplete":{"oneofs":{"operationResp":{"oneof":["reqOutputArgs","cmdFailure"]}},"fields":{"objPath":{"type":"string","id":1},"commandName":{"type":"string","id":2},"commandKey":{"type":"string","id":3},"reqOutputArgs":{"type":"OutputArgs","id":4},"cmdFailure":{"type":"CommandFailure","id":5}},"nested":{"OutputArgs":{"fields":{"outputArgs":{"keyType":"string","type":"string","id":1}}},"CommandFailure":{"fields":{"errCode":{"type":"fixed32","id":1},"errMsg":{"type":"string","id":2}}}}},"OnBoardRequest":{"fields":{"oui":{"type":"string","id":1},"productClass":{"type":"string","id":2},"serialNumber":{"type":"string","id":3},"agentSupportedProtocolVersions":{"type":"string","id":4}}}}},"NotifyResp":{"fields":{"subscriptionId":{"type":"string","id":1}}}}}}} \ No newline at end of file +export default{nested:{usp:{nested:{Msg:{fields:{header:{type:"Header",id:1},body:{type:"Body",id:2}}},Header:{fields:{msgId:{type:"string",id:1},msgType:{type:"MsgType",id:2}},nested:{MsgType:{values:{ERROR:0,GET:1,GET_RESP:2,NOTIFY:3,SET:4,SET_RESP:5,OPERATE:6,OPERATE_RESP:7,ADD:8,ADD_RESP:9,DELETE:10,DELETE_RESP:11,GET_SUPPORTED_DM:12,GET_SUPPORTED_DM_RESP:13,GET_INSTANCES:14,GET_INSTANCES_RESP:15,NOTIFY_RESP:16,GET_SUPPORTED_PROTO:17,GET_SUPPORTED_PROTO_RESP:18}}}},Body:{oneofs:{msgBody:{oneof:["request","response","error"]}},fields:{request:{type:"Request",id:1},response:{type:"Response",id:2},error:{type:"Error",id:3}}},Request:{oneofs:{reqType:{oneof:["get","getSupportedDm","getInstances","set","add","delete","operate","notify","getSupportedProtocol"]}},fields:{get:{type:"Get",id:1},getSupportedDm:{type:"GetSupportedDM",id:2},getInstances:{type:"GetInstances",id:3},set:{type:"Set",id:4},add:{type:"Add",id:5},delete:{type:"Delete",id:6},operate:{type:"Operate",id:7},notify:{type:"Notify",id:8},getSupportedProtocol:{type:"GetSupportedProtocol",id:9}}},Response:{oneofs:{respType:{oneof:["getResp","getSupportedDmResp","getInstancesResp","setResp","addResp","deleteResp","operateResp","notifyResp","getSupportedProtocolResp"]}},fields:{getResp:{type:"GetResp",id:1},getSupportedDmResp:{type:"GetSupportedDMResp",id:2},getInstancesResp:{type:"GetInstancesResp",id:3},setResp:{type:"SetResp",id:4},addResp:{type:"AddResp",id:5},deleteResp:{type:"DeleteResp",id:6},operateResp:{type:"OperateResp",id:7},notifyResp:{type:"NotifyResp",id:8},getSupportedProtocolResp:{type:"GetSupportedProtocolResp",id:9}}},Error:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2},paramErrs:{rule:"repeated",type:"ParamError",id:3}},nested:{ParamError:{fields:{paramPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Get:{fields:{paramPaths:{rule:"repeated",type:"string",id:1}}},GetResp:{fields:{reqPathResults:{rule:"repeated",type:"RequestedPathResult",id:1}},nested:{RequestedPathResult:{fields:{requestedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},resolvedPathResults:{rule:"repeated",type:"ResolvedPathResult",id:4}}},ResolvedPathResult:{fields:{resolvedPath:{type:"string",id:1},resultParams:{keyType:"string",type:"string",id:2}}}}},GetSupportedDM:{fields:{objPaths:{rule:"repeated",type:"string",id:1},firstLevelOnly:{type:"bool",id:2},returnCommands:{type:"bool",id:3},returnEvents:{type:"bool",id:4},returnParams:{type:"bool",id:5}}},GetSupportedDMResp:{fields:{reqObjResults:{rule:"repeated",type:"RequestedObjectResult",id:1}},nested:{RequestedObjectResult:{fields:{reqObjPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},dataModelInstUri:{type:"string",id:4},supportedObjs:{rule:"repeated",type:"SupportedObjectResult",id:5}}},SupportedObjectResult:{fields:{supportedObjPath:{type:"string",id:1},access:{type:"ObjAccessType",id:2},isMultiInstance:{type:"bool",id:3},supportedCommands:{rule:"repeated",type:"SupportedCommandResult",id:4},supportedEvents:{rule:"repeated",type:"SupportedEventResult",id:5},supportedParams:{rule:"repeated",type:"SupportedParamResult",id:6}}},SupportedParamResult:{fields:{paramName:{type:"string",id:1},access:{type:"ParamAccessType",id:2}}},SupportedCommandResult:{fields:{commandName:{type:"string",id:1},inputArgNames:{rule:"repeated",type:"string",id:2},outputArgNames:{rule:"repeated",type:"string",id:3}}},SupportedEventResult:{fields:{eventName:{type:"string",id:1},argNames:{rule:"repeated",type:"string",id:2}}},ParamAccessType:{values:{PARAM_READ_ONLY:0,PARAM_READ_WRITE:1,PARAM_WRITE_ONLY:2}},ObjAccessType:{values:{OBJ_READ_ONLY:0,OBJ_ADD_DELETE:1,OBJ_ADD_ONLY:2,OBJ_DELETE_ONLY:3}}}},GetInstances:{fields:{objPaths:{rule:"repeated",type:"string",id:1},firstLevelOnly:{type:"bool",id:2}}},GetInstancesResp:{fields:{reqPathResults:{rule:"repeated",type:"RequestedPathResult",id:1}},nested:{RequestedPathResult:{fields:{requestedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},currInsts:{rule:"repeated",type:"CurrInstance",id:4}}},CurrInstance:{fields:{instantiatedObjPath:{type:"string",id:1},uniqueKeys:{keyType:"string",type:"string",id:2}}}}},GetSupportedProtocol:{fields:{controllerSupportedProtocolVersions:{type:"string",id:1}}},GetSupportedProtocolResp:{fields:{agentSupportedProtocolVersions:{type:"string",id:1}}},Add:{fields:{allowPartial:{type:"bool",id:1},createObjs:{rule:"repeated",type:"CreateObject",id:2}},nested:{CreateObject:{fields:{objPath:{type:"string",id:1},paramSettings:{rule:"repeated",type:"CreateParamSetting",id:2}}},CreateParamSetting:{fields:{param:{type:"string",id:1},value:{type:"string",id:2},required:{type:"bool",id:3}}}}},AddResp:{fields:{createdObjResults:{rule:"repeated",type:"CreatedObjectResult",id:1}},nested:{CreatedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}},OperationSuccess:{fields:{instantiatedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2},uniqueKeys:{keyType:"string",type:"string",id:3}}}}}}},ParameterError:{fields:{param:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Delete:{fields:{allowPartial:{type:"bool",id:1},objPaths:{rule:"repeated",type:"string",id:2}}},DeleteResp:{fields:{deletedObjResults:{rule:"repeated",type:"DeletedObjectResult",id:1}},nested:{DeletedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}},OperationSuccess:{fields:{affectedPaths:{rule:"repeated",type:"string",id:1},unaffectedPathErrs:{rule:"repeated",type:"UnaffectedPathError",id:2}}}}}}},UnaffectedPathError:{fields:{unaffectedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Set:{fields:{allowPartial:{type:"bool",id:1},updateObjs:{rule:"repeated",type:"UpdateObject",id:2}},nested:{UpdateObject:{fields:{objPath:{type:"string",id:1},paramSettings:{rule:"repeated",type:"UpdateParamSetting",id:2}}},UpdateParamSetting:{fields:{param:{type:"string",id:1},value:{type:"string",id:2},required:{type:"bool",id:3}}}}},SetResp:{fields:{updatedObjResults:{rule:"repeated",type:"UpdatedObjectResult",id:1}},nested:{UpdatedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2},updatedInstFailures:{rule:"repeated",type:"UpdatedInstanceFailure",id:3}}},OperationSuccess:{fields:{updatedInstResults:{rule:"repeated",type:"UpdatedInstanceResult",id:1}}}}}}},UpdatedInstanceFailure:{fields:{affectedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2}}},UpdatedInstanceResult:{fields:{affectedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2},updatedParams:{keyType:"string",type:"string",id:3}}},ParameterError:{fields:{param:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Operate:{fields:{command:{type:"string",id:1},commandKey:{type:"string",id:2},sendResp:{type:"bool",id:3},inputArgs:{keyType:"string",type:"string",id:4}}},OperateResp:{fields:{operationResults:{rule:"repeated",type:"OperationResult",id:1}},nested:{OperationResult:{oneofs:{operationResp:{oneof:["reqObjPath","reqOutputArgs","cmdFailure"]}},fields:{executedCommand:{type:"string",id:1},reqObjPath:{type:"string",id:2},reqOutputArgs:{type:"OutputArgs",id:3},cmdFailure:{type:"CommandFailure",id:4}},nested:{OutputArgs:{fields:{outputArgs:{keyType:"string",type:"string",id:1}}},CommandFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}}}}}},Notify:{oneofs:{notification:{oneof:["event","valueChange","objCreation","objDeletion","operComplete","onBoardReq"]}},fields:{subscriptionId:{type:"string",id:1},sendResp:{type:"bool",id:2},event:{type:"Event",id:3},valueChange:{type:"ValueChange",id:4},objCreation:{type:"ObjectCreation",id:5},objDeletion:{type:"ObjectDeletion",id:6},operComplete:{type:"OperationComplete",id:7},onBoardReq:{type:"OnBoardRequest",id:8}},nested:{Event:{fields:{objPath:{type:"string",id:1},eventName:{type:"string",id:2},params:{keyType:"string",type:"string",id:3}}},ValueChange:{fields:{paramPath:{type:"string",id:1},paramValue:{type:"string",id:2}}},ObjectCreation:{fields:{objPath:{type:"string",id:1},uniqueKeys:{keyType:"string",type:"string",id:2}}},ObjectDeletion:{fields:{objPath:{type:"string",id:1}}},OperationComplete:{oneofs:{operationResp:{oneof:["reqOutputArgs","cmdFailure"]}},fields:{objPath:{type:"string",id:1},commandName:{type:"string",id:2},commandKey:{type:"string",id:3},reqOutputArgs:{type:"OutputArgs",id:4},cmdFailure:{type:"CommandFailure",id:5}},nested:{OutputArgs:{fields:{outputArgs:{keyType:"string",type:"string",id:1}}},CommandFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}}}},OnBoardRequest:{fields:{oui:{type:"string",id:1},productClass:{type:"string",id:2},serialNumber:{type:"string",id:3},agentSupportedProtocolVersions:{type:"string",id:4}}}}},NotifyResp:{fields:{subscriptionId:{type:"string",id:1}}}}}}}; \ No newline at end of file diff --git a/src/specs/usp-msg-1-2.js b/src/specs/usp-msg-1-2.js new file mode 100644 index 0000000..d04a8ca --- /dev/null +++ b/src/specs/usp-msg-1-2.js @@ -0,0 +1 @@ +export default{nested:{usp:{nested:{Msg:{fields:{header:{type:"Header",id:1},body:{type:"Body",id:2}}},Header:{fields:{msgId:{type:"string",id:1},msgType:{type:"MsgType",id:2}},nested:{MsgType:{values:{ERROR:0,GET:1,GET_RESP:2,NOTIFY:3,SET:4,SET_RESP:5,OPERATE:6,OPERATE_RESP:7,ADD:8,ADD_RESP:9,DELETE:10,DELETE_RESP:11,GET_SUPPORTED_DM:12,GET_SUPPORTED_DM_RESP:13,GET_INSTANCES:14,GET_INSTANCES_RESP:15,NOTIFY_RESP:16,GET_SUPPORTED_PROTO:17,GET_SUPPORTED_PROTO_RESP:18}}}},Body:{oneofs:{msgBody:{oneof:["request","response","error"]}},fields:{request:{type:"Request",id:1},response:{type:"Response",id:2},error:{type:"Error",id:3}}},Request:{oneofs:{reqType:{oneof:["get","getSupportedDm","getInstances","set","add","delete","operate","notify","getSupportedProtocol"]}},fields:{get:{type:"Get",id:1},getSupportedDm:{type:"GetSupportedDM",id:2},getInstances:{type:"GetInstances",id:3},set:{type:"Set",id:4},add:{type:"Add",id:5},delete:{type:"Delete",id:6},operate:{type:"Operate",id:7},notify:{type:"Notify",id:8},getSupportedProtocol:{type:"GetSupportedProtocol",id:9}}},Response:{oneofs:{respType:{oneof:["getResp","getSupportedDmResp","getInstancesResp","setResp","addResp","deleteResp","operateResp","notifyResp","getSupportedProtocolResp"]}},fields:{getResp:{type:"GetResp",id:1},getSupportedDmResp:{type:"GetSupportedDMResp",id:2},getInstancesResp:{type:"GetInstancesResp",id:3},setResp:{type:"SetResp",id:4},addResp:{type:"AddResp",id:5},deleteResp:{type:"DeleteResp",id:6},operateResp:{type:"OperateResp",id:7},notifyResp:{type:"NotifyResp",id:8},getSupportedProtocolResp:{type:"GetSupportedProtocolResp",id:9}}},Error:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2},paramErrs:{rule:"repeated",type:"ParamError",id:3}},nested:{ParamError:{fields:{paramPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Get:{fields:{paramPaths:{rule:"repeated",type:"string",id:1},maxDepth:{type:"fixed32",id:2}}},GetResp:{fields:{reqPathResults:{rule:"repeated",type:"RequestedPathResult",id:1}},nested:{RequestedPathResult:{fields:{requestedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},resolvedPathResults:{rule:"repeated",type:"ResolvedPathResult",id:4}}},ResolvedPathResult:{fields:{resolvedPath:{type:"string",id:1},resultParams:{keyType:"string",type:"string",id:2}}}}},GetSupportedDM:{fields:{objPaths:{rule:"repeated",type:"string",id:1},firstLevelOnly:{type:"bool",id:2},returnCommands:{type:"bool",id:3},returnEvents:{type:"bool",id:4},returnParams:{type:"bool",id:5}}},GetSupportedDMResp:{fields:{reqObjResults:{rule:"repeated",type:"RequestedObjectResult",id:1}},nested:{RequestedObjectResult:{fields:{reqObjPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},dataModelInstUri:{type:"string",id:4},supportedObjs:{rule:"repeated",type:"SupportedObjectResult",id:5}}},SupportedObjectResult:{fields:{supportedObjPath:{type:"string",id:1},access:{type:"ObjAccessType",id:2},isMultiInstance:{type:"bool",id:3},supportedCommands:{rule:"repeated",type:"SupportedCommandResult",id:4},supportedEvents:{rule:"repeated",type:"SupportedEventResult",id:5},supportedParams:{rule:"repeated",type:"SupportedParamResult",id:6},divergentPaths:{rule:"repeated",type:"string",id:7}}},SupportedParamResult:{fields:{paramName:{type:"string",id:1},access:{type:"ParamAccessType",id:2},valueType:{type:"ParamValueType",id:3},valueChange:{type:"ValueChangeType",id:4}}},SupportedCommandResult:{fields:{commandName:{type:"string",id:1},inputArgNames:{rule:"repeated",type:"string",id:2},outputArgNames:{rule:"repeated",type:"string",id:3},commandType:{type:"CmdType",id:4}}},SupportedEventResult:{fields:{eventName:{type:"string",id:1},argNames:{rule:"repeated",type:"string",id:2}}},ParamAccessType:{values:{PARAM_READ_ONLY:0,PARAM_READ_WRITE:1,PARAM_WRITE_ONLY:2}},ObjAccessType:{values:{OBJ_READ_ONLY:0,OBJ_ADD_DELETE:1,OBJ_ADD_ONLY:2,OBJ_DELETE_ONLY:3}},ParamValueType:{values:{PARAM_UNKNOWN:0,PARAM_BASE_64:1,PARAM_BOOLEAN:2,PARAM_DATE_TIME:3,PARAM_DECIMAL:4,PARAM_HEX_BINARY:5,PARAM_INT:6,PARAM_LONG:7,PARAM_STRING:8,PARAM_UNSIGNED_INT:9,PARAM_UNSIGNED_LONG:10}},ValueChangeType:{values:{VALUE_CHANGE_UNKNOWN:0,VALUE_CHANGE_ALLOWED:1,VALUE_CHANGE_WILL_IGNORE:2}},CmdType:{values:{CMD_UNKNOWN:0,CMD_SYNC:1,CMD_ASYNC:2}}}},GetInstances:{fields:{objPaths:{rule:"repeated",type:"string",id:1},firstLevelOnly:{type:"bool",id:2}}},GetInstancesResp:{fields:{reqPathResults:{rule:"repeated",type:"RequestedPathResult",id:1}},nested:{RequestedPathResult:{fields:{requestedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3},currInsts:{rule:"repeated",type:"CurrInstance",id:4}}},CurrInstance:{fields:{instantiatedObjPath:{type:"string",id:1},uniqueKeys:{keyType:"string",type:"string",id:2}}}}},GetSupportedProtocol:{fields:{controllerSupportedProtocolVersions:{type:"string",id:1}}},GetSupportedProtocolResp:{fields:{agentSupportedProtocolVersions:{type:"string",id:1}}},Add:{fields:{allowPartial:{type:"bool",id:1},createObjs:{rule:"repeated",type:"CreateObject",id:2}},nested:{CreateObject:{fields:{objPath:{type:"string",id:1},paramSettings:{rule:"repeated",type:"CreateParamSetting",id:2}}},CreateParamSetting:{fields:{param:{type:"string",id:1},value:{type:"string",id:2},required:{type:"bool",id:3}}}}},AddResp:{fields:{createdObjResults:{rule:"repeated",type:"CreatedObjectResult",id:1}},nested:{CreatedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}},OperationSuccess:{fields:{instantiatedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2},uniqueKeys:{keyType:"string",type:"string",id:3}}}}}}},ParameterError:{fields:{param:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Delete:{fields:{allowPartial:{type:"bool",id:1},objPaths:{rule:"repeated",type:"string",id:2}}},DeleteResp:{fields:{deletedObjResults:{rule:"repeated",type:"DeletedObjectResult",id:1}},nested:{DeletedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}},OperationSuccess:{fields:{affectedPaths:{rule:"repeated",type:"string",id:1},unaffectedPathErrs:{rule:"repeated",type:"UnaffectedPathError",id:2}}}}}}},UnaffectedPathError:{fields:{unaffectedPath:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Set:{fields:{allowPartial:{type:"bool",id:1},updateObjs:{rule:"repeated",type:"UpdateObject",id:2}},nested:{UpdateObject:{fields:{objPath:{type:"string",id:1},paramSettings:{rule:"repeated",type:"UpdateParamSetting",id:2}}},UpdateParamSetting:{fields:{param:{type:"string",id:1},value:{type:"string",id:2},required:{type:"bool",id:3}}}}},SetResp:{fields:{updatedObjResults:{rule:"repeated",type:"UpdatedObjectResult",id:1}},nested:{UpdatedObjectResult:{fields:{requestedPath:{type:"string",id:1},operStatus:{type:"OperationStatus",id:2}},nested:{OperationStatus:{oneofs:{operStatus:{oneof:["operFailure","operSuccess"]}},fields:{operFailure:{type:"OperationFailure",id:1},operSuccess:{type:"OperationSuccess",id:2}},nested:{OperationFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2},updatedInstFailures:{rule:"repeated",type:"UpdatedInstanceFailure",id:3}}},OperationSuccess:{fields:{updatedInstResults:{rule:"repeated",type:"UpdatedInstanceResult",id:1}}}}}}},UpdatedInstanceFailure:{fields:{affectedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2}}},UpdatedInstanceResult:{fields:{affectedPath:{type:"string",id:1},paramErrs:{rule:"repeated",type:"ParameterError",id:2},updatedParams:{keyType:"string",type:"string",id:3}}},ParameterError:{fields:{param:{type:"string",id:1},errCode:{type:"fixed32",id:2},errMsg:{type:"string",id:3}}}}},Operate:{fields:{command:{type:"string",id:1},commandKey:{type:"string",id:2},sendResp:{type:"bool",id:3},inputArgs:{keyType:"string",type:"string",id:4}}},OperateResp:{fields:{operationResults:{rule:"repeated",type:"OperationResult",id:1}},nested:{OperationResult:{oneofs:{operationResp:{oneof:["reqObjPath","reqOutputArgs","cmdFailure"]}},fields:{executedCommand:{type:"string",id:1},reqObjPath:{type:"string",id:2},reqOutputArgs:{type:"OutputArgs",id:3},cmdFailure:{type:"CommandFailure",id:4}},nested:{OutputArgs:{fields:{outputArgs:{keyType:"string",type:"string",id:1}}},CommandFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}}}}}},Notify:{oneofs:{notification:{oneof:["event","valueChange","objCreation","objDeletion","operComplete","onBoardReq"]}},fields:{subscriptionId:{type:"string",id:1},sendResp:{type:"bool",id:2},event:{type:"Event",id:3},valueChange:{type:"ValueChange",id:4},objCreation:{type:"ObjectCreation",id:5},objDeletion:{type:"ObjectDeletion",id:6},operComplete:{type:"OperationComplete",id:7},onBoardReq:{type:"OnBoardRequest",id:8}},nested:{Event:{fields:{objPath:{type:"string",id:1},eventName:{type:"string",id:2},params:{keyType:"string",type:"string",id:3}}},ValueChange:{fields:{paramPath:{type:"string",id:1},paramValue:{type:"string",id:2}}},ObjectCreation:{fields:{objPath:{type:"string",id:1},uniqueKeys:{keyType:"string",type:"string",id:2}}},ObjectDeletion:{fields:{objPath:{type:"string",id:1}}},OperationComplete:{oneofs:{operationResp:{oneof:["reqOutputArgs","cmdFailure"]}},fields:{objPath:{type:"string",id:1},commandName:{type:"string",id:2},commandKey:{type:"string",id:3},reqOutputArgs:{type:"OutputArgs",id:4},cmdFailure:{type:"CommandFailure",id:5}},nested:{OutputArgs:{fields:{outputArgs:{keyType:"string",type:"string",id:1}}},CommandFailure:{fields:{errCode:{type:"fixed32",id:1},errMsg:{type:"string",id:2}}}}},OnBoardRequest:{fields:{oui:{type:"string",id:1},productClass:{type:"string",id:2},serialNumber:{type:"string",id:3},agentSupportedProtocolVersions:{type:"string",id:4}}}}},NotifyResp:{fields:{subscriptionId:{type:"string",id:1}}}}}}}; \ No newline at end of file diff --git a/src/specs/usp-record-1-1.js b/src/specs/usp-record-1-1.js index 040d0ce..dff964f 100644 --- a/src/specs/usp-record-1-1.js +++ b/src/specs/usp-record-1-1.js @@ -1 +1 @@ -export default {"nested":{"usp_record":{"nested":{"Record":{"oneofs":{"recordType":{"oneof":["noSessionContext","sessionContext"]}},"fields":{"version":{"type":"string","id":1},"toId":{"type":"string","id":2},"fromId":{"type":"string","id":3},"payloadSecurity":{"type":"PayloadSecurity","id":4},"macSignature":{"type":"bytes","id":5},"senderCert":{"type":"bytes","id":6},"noSessionContext":{"type":"NoSessionContextRecord","id":7},"sessionContext":{"type":"SessionContextRecord","id":8}},"nested":{"PayloadSecurity":{"values":{"PLAINTEXT":0,"TLS12":1}}}},"NoSessionContextRecord":{"fields":{"payload":{"type":"bytes","id":2}}},"SessionContextRecord":{"fields":{"sessionId":{"type":"uint64","id":1},"sequenceId":{"type":"uint64","id":2},"expectedId":{"type":"uint64","id":3},"retransmitId":{"type":"uint64","id":4},"payloadSarState":{"type":"PayloadSARState","id":5},"payloadrecSarState":{"type":"PayloadSARState","id":6},"payload":{"rule":"repeated","type":"bytes","id":7}},"nested":{"PayloadSARState":{"values":{"NONE":0,"BEGIN":1,"INPROCESS":2,"COMPLETE":3}}}}}}}} \ No newline at end of file +export default{nested:{usp_record:{nested:{Record:{oneofs:{recordType:{oneof:["noSessionContext","sessionContext"]}},fields:{version:{type:"string",id:1},toId:{type:"string",id:2},fromId:{type:"string",id:3},payloadSecurity:{type:"PayloadSecurity",id:4},macSignature:{type:"bytes",id:5},senderCert:{type:"bytes",id:6},noSessionContext:{type:"NoSessionContextRecord",id:7},sessionContext:{type:"SessionContextRecord",id:8}},nested:{PayloadSecurity:{values:{PLAINTEXT:0,TLS12:1}}}},NoSessionContextRecord:{fields:{payload:{type:"bytes",id:2}}},SessionContextRecord:{fields:{sessionId:{type:"uint64",id:1},sequenceId:{type:"uint64",id:2},expectedId:{type:"uint64",id:3},retransmitId:{type:"uint64",id:4},payloadSarState:{type:"PayloadSARState",id:5},payloadrecSarState:{type:"PayloadSARState",id:6},payload:{rule:"repeated",type:"bytes",id:7}},nested:{PayloadSARState:{values:{NONE:0,BEGIN:1,INPROCESS:2,COMPLETE:3}}}}}}}}; \ No newline at end of file diff --git a/src/specs/usp-record-1-2.js b/src/specs/usp-record-1-2.js new file mode 100644 index 0000000..b98a1f8 --- /dev/null +++ b/src/specs/usp-record-1-2.js @@ -0,0 +1 @@ +export default{nested:{usp_record:{nested:{Record:{oneofs:{recordType:{oneof:["noSessionContext","sessionContext","websocketConnect","mqttConnect","stompConnect","disconnect"]}},fields:{version:{type:"string",id:1},toId:{type:"string",id:2},fromId:{type:"string",id:3},payloadSecurity:{type:"PayloadSecurity",id:4},macSignature:{type:"bytes",id:5},senderCert:{type:"bytes",id:6},noSessionContext:{type:"NoSessionContextRecord",id:7},sessionContext:{type:"SessionContextRecord",id:8},websocketConnect:{type:"WebSocketConnectRecord",id:9},mqttConnect:{type:"MQTTConnectRecord",id:10},stompConnect:{type:"STOMPConnectRecord",id:11},disconnect:{type:"DisconnectRecord",id:12}},nested:{PayloadSecurity:{values:{PLAINTEXT:0,TLS12:1}}}},NoSessionContextRecord:{fields:{payload:{type:"bytes",id:2}}},SessionContextRecord:{fields:{sessionId:{type:"uint64",id:1},sequenceId:{type:"uint64",id:2},expectedId:{type:"uint64",id:3},retransmitId:{type:"uint64",id:4},payloadSarState:{type:"PayloadSARState",id:5},payloadrecSarState:{type:"PayloadSARState",id:6},payload:{rule:"repeated",type:"bytes",id:7}},nested:{PayloadSARState:{values:{NONE:0,BEGIN:1,INPROCESS:2,COMPLETE:3}}}},WebSocketConnectRecord:{fields:{}},MQTTConnectRecord:{fields:{version:{type:"MQTTVersion",id:1},subscribedTopic:{type:"string",id:2}},nested:{MQTTVersion:{values:{V3_1_1:0,V5:1}}}},STOMPConnectRecord:{fields:{version:{type:"STOMPVersion",id:1},subscribedDestination:{type:"string",id:2}},nested:{STOMPVersion:{values:{V1_2:0}}}},DisconnectRecord:{fields:{reason:{type:"string",id:1},reasonCode:{type:"fixed32",id:2}}}}}}}; \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index 9f857e9..5f66f14 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,6 +11,9 @@ export type CommandType = export type GetCommandOptions = { raw?: boolean; + /** + * Defaults to 2 (Only applies to usp version 1.2 ) + */ max_depth?: number; }; @@ -69,7 +72,7 @@ export type InstancesCommand = ( paths: string | string[], opts?: { firstLevelOnly?: boolean } ) => Promise<Record<string, any>>; -export type SupportedProtoCommand = (versions: string) => Promise<string>; +export type SupportedProtoCommand = () => Promise<string[]>; export type SubscribeRecipe = ( opts: SubscriptionOptions, callback: SubscriptionCallback @@ -337,7 +340,7 @@ export interface USP { * await usp.supportedProto("1.0") * ``` */ - supportedProto: SupportedProtoCommand; + getSupportedProtocols: SupportedProtoCommand; /** * Get instances @@ -458,6 +461,9 @@ export type HostConnectionOptions = { } & OtherConnectionOptions; export type CertType = string | string[] | Buffer | Buffer[]; + +export type USPVersion = "1.0" | "1.1" | "1.2"; + export interface OtherConnectionOptions { username: string; password: string; @@ -466,6 +472,7 @@ export interface OtherConnectionOptions { idEndpoint?: string; publishEndpoint?: string; subscribeEndpoint?: string; + version?: USPVersion; ca?: CertType | Object[]; key?: CertType; cert?: CertType; @@ -556,7 +563,9 @@ export type ConnectionClient = { end: () => void; }; -export type ConnectClientFn = (options: ConnectionOptions) => Promise<ConnectionClient>; +export type ConnectClientFn = ( + options: ConnectionOptions +) => Promise<ConnectionClient>; export type DecodeIDFn = (data: any) => string; @@ -566,7 +575,7 @@ export type Proto = { header: any; }; -export type LoadProtobufFn = () => Promise<Proto>; +export type LoadProtobufFn = (version: USPVersion) => Promise<Proto>; export type BuildConnectionFn = (connectConfig: { connectClient: ConnectClientFn; -- GitLab