diff --git a/package-lock.json b/package-lock.json index ad86bf3003dde2f11a241e276e0f8c9b5e854490..66f1ebdaaa44b08f77df9f9b71646bd166fb1959 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5563,9 +5563,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", @@ -9667,9 +9667,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -13139,9 +13139,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -20257,9 +20257,9 @@ } }, "jszip": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.6.0.tgz", - "integrity": "sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.7.1.tgz", + "integrity": "sha512-ghL0tz1XG9ZEmRMcEN2vt7xabrDdqHHeykgARpmZ0BiIctWxM47Vt63ZO2dnp4QYt/xJVLLy5Zv1l/xRdh2byg==", "dev": true, "requires": { "lie": "~3.3.0", @@ -21576,9 +21576,9 @@ } }, "tar": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", - "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", "dev": true, "requires": { "chownr": "^2.0.0", @@ -22562,9 +22562,9 @@ "dev": true }, "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, "path-to-regexp": { @@ -26995,6 +26995,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "totalist": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", @@ -27697,9 +27702,9 @@ } }, "url-parse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", - "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", "dev": true, "requires": { "querystringify": "^2.1.1", diff --git a/package.json b/package.json index 0ab9d22dc08a626220a523d885764756a4c031c8..06c1c9ce756554aed7270a9f486f93427efcf9fd 100644 --- a/package.json +++ b/package.json @@ -102,6 +102,7 @@ "request": "^2.88.2", "source-map-support": "^0.5.19", "sqlite3": "^5.0.2", + "toposort": "^2.0.2", "utf-8-validate": "^5.0.5", "uuid": "^8.3.2", "ws": "^7.5.2", diff --git a/src-electron/db/query-zcl.js b/src-electron/db/query-zcl.js index 536cae266cda0f3bedde83aced10d41ea1e8fce7..0aa2d95ae9ad721f211d9511f9b2f2b4dc03e3d4 100644 --- a/src-electron/db/query-zcl.js +++ b/src-electron/db/query-zcl.js @@ -206,6 +206,7 @@ async function selectAllStructsWithItems(db, packageId) { db, ` SELECT + STRUCT.STRUCT_ID AS STRUCT_ID, STRUCT.NAME AS STRUCT_NAME, ITEM.NAME AS ITEM_NAME, ITEM.FIELD_IDENTIFIER AS ITEM_IDENTIFIER, @@ -231,7 +232,9 @@ ORDER BY STRUCT.NAME, ITEM.FIELD_IDENTIFIER`, if (acc.length == 0 || acc[acc.length - 1].name != value.STRUCT_NAME) { // Create a new object objectToActOn = { + id: value.STRUCT_ID, name: value.STRUCT_NAME, + label: value.STRUCT_NAME, items: [], } acc.push(objectToActOn) diff --git a/src-electron/generator/helper-zcl.js b/src-electron/generator/helper-zcl.js index 6eecc6d8d45948f6c81c6b9d6acc45007d652a5c..0b3d117e5d080f231d55fc8acd47af60a997b59c 100644 --- a/src-electron/generator/helper-zcl.js +++ b/src-electron/generator/helper-zcl.js @@ -92,7 +92,7 @@ function zcl_structs(options) { let promise = templateUtil .ensureZclPackageId(this) .then((packageId) => - queryZcl.selectAllStructsWithItemCount(this.global.db, packageId) + queryZcl.selectAllStructsWithItems(this.global.db, packageId) ) .then((structs) => zclUtil.sortStructsByDependency(structs)) .then((structs) => templateUtil.collectBlocks(structs, options, this)) diff --git a/src-electron/util/zcl-util.js b/src-electron/util/zcl-util.js index 8f4d9d92e5decfa17c8a5a0f798c0ba5414f830c..02f0af592ec67917bb7553aca7ce25ca20de8345 100644 --- a/src-electron/util/zcl-util.js +++ b/src-electron/util/zcl-util.js @@ -20,6 +20,7 @@ * * @module REST API: various zcl utilities */ +const toposort = require('toposort') /** * Comparator for sorting clusters. @@ -69,16 +70,51 @@ function commandComparator(a, b) { return 0 } +function findStructByName(structs, name) { + for (const s of structs) { + if (s.name == name) { + return s + } + } + return null +} + /** * This method retrieves a bunch of structs sorted * alphabetically. It's expected to resort the structs into a list * where they are sorted in a way where dependency is observed. * + * It uses the DFS algorithm to traverse the DAG in a way the + * dependencies are observed. + * * @param {*} structs * @returns */ async function sortStructsByDependency(structs) { - return structs + let allStructNames = structs.map((s) => s.name) + let edges = [] + + // Add edges + structs.forEach((s) => { + s.items.forEach((i) => { + const type = i.type + if (allStructNames.includes(type)) { + edges.push([s.name, type]) + } + }) + }) + + let sortedEdges = toposort(edges).reverse() + + let finalSort = [] + sortedEdges.forEach((s) => { + finalSort.push(findStructByName(structs, s)) + }) + allStructNames.forEach((s) => { + if (!sortedEdges.includes(s)) finalSort.push(findStructByName(structs, s)) + }) + + return finalSort } exports.clusterComparator = clusterComparator diff --git a/test/resource/meta/types.xml b/test/resource/meta/types.xml index fd8e872517b8c4b1c12a40769ead9f87682bb917..86d2c82c8e110108fc53f1418f7546a5b3e94aaa 100644 --- a/test/resource/meta/types.xml +++ b/test/resource/meta/types.xml @@ -86,4 +86,21 @@ limitations under the License. <item name="b" type="BOOLEAN" optional="false"/> <item name="c" type="SimpleStruct" optional="false"/> </struct> + + <struct name="A"> + <item name="x" type="UINT8U"/> + <item name="b" type="B"/> + <item name="c" type="C"/> + </struct> + <struct name="B"> + <item name="x" type="UINT8U"/> + <item name="d" type="D"/> + </struct> + <struct name="C"> + <item name="x" type="UINT8U"/> + </struct> + <struct name="D"> + <item name="x" type="UINT8U"/> + <item name="c" type="C"/> + </struct> </configurator>