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