From c57ca557438c3785f907c95146007bb865c2bcae Mon Sep 17 00:00:00 2001 From: Jamie Magee Date: Fri, 18 Sep 2026 23:06:14 -0700 Subject: [PATCH] Revert Inovelli GitHub firmware discovery (#1310) --- .cache/InovelliGitHub.json | 1 - src/autodl/inovelli.ts | 91 ++--------------------------------- tests/autodl_inovelli.test.ts | 77 ----------------------------- 3 files changed, 5 insertions(+), 164 deletions(-) delete mode 100644 .cache/InovelliGitHub.json delete mode 100644 tests/autodl_inovelli.test.ts diff --git a/.cache/InovelliGitHub.json b/.cache/InovelliGitHub.json deleted file mode 100644 index 61df859..0000000 --- a/.cache/InovelliGitHub.json +++ /dev/null @@ -1 +0,0 @@ -[{"path":"Blue-Series/Zigbee/VZM30-SN-Switch/Beta/1.01/VZM30-SN_1.01.ota","sha":"5a6ccf5613694c477d612bb08524fcfcb20f7356"},{"path":"Blue-Series/Zigbee/VZM30-SN-Switch/Beta/1.02/VZM30-SN_1.02.ota","sha":"cf9799b5e0908bd32545d026a929721f78140196"},{"path":"Blue-Series/Zigbee/VZM30-SN-Switch/Production/1.00/VZM30-SN_1.00.ota","sha":"79017bc57bc70ec54bd7888386881b70cef03b67"},{"path":"Blue-Series/Zigbee/VZM30-SN-Switch/Production/1.01/VZM30-SN_1.01.ota","sha":"5a6ccf5613694c477d612bb08524fcfcb20f7356"},{"path":"Blue-Series/Zigbee/VZM30-SN-Switch/Production/1.03/VZM30-SN_1.03.ota","sha":"c0d092babe2bbcf6fa95b7b648241901276f7e74"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.02/VZM31-SN_2.02-Beta.ota","sha":"309f2f385aeac8b1a8fbaf0112d45567631363f7"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.03/VZM31-SN_2.03-Beta.ota","sha":"a62ff2e295fbdb6b091ae3ae35ccb9f7a4d7417f"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.05/VZM31-SN_2.05-Beta.ota","sha":"389240901e0b969331ada67a2ece4382d8b9e670"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.06/VZM31-SN_2.06-Beta.ota","sha":"43c964e65f87c20bfcf7a109ab6afd35652723f0"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.07/VZM31-SN_2.07-Beta.ota","sha":"75e5226ead7d0e585ed214bbf3c1c1d98986d233"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.10/VZM31-SN_2.10-Beta.ota","sha":"a1291243f9730f88f5bf21d4c17951ce9adfebad"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.12/VZM31-SN_2.12-Beta.ota","sha":"c7c5aa1f87b7989f6b7cdf178b3ba214bbb73fcd"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.13/VZM31-SN_2.13-Beta.ota","sha":"e94a9fb1f01156b52c0da9b1e565b0536dcc5c3c"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.14/VZM31-SN_2.14-Beta.ota","sha":"f31223f659772846722ffe93ff2f32d74f9ebd82"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/2.17/VZM31-SN_2.17-Beta.ota","sha":"4610130eaef2990608e2cdb00a6094079473acc7"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Beta/3.07/VZM31-SN_ota_V307_20260326.ota","sha":"772a94473c0cfbf7fe10134da5ead7a5e8890ccb"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Production/2.08/VZM31-SN_2.08-Production.ota","sha":"470caefbc7e23f16a93b15cab391ba9d6be30250"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Production/2.11/VZM31-SN_2.11-Production.ota","sha":"2e11ae38fb8818f6e417711b86bbddaf08817896"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Production/2.15/VZM31-SN_2.15-Production.ota","sha":"a01c72c10f67dda0ebd8c5d0ae5c36c64b165b48"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Production/2.18/VZM31-SN_2.18-Production.ota","sha":"af2dc93ee033ed301208fbbad3fa1768390dcff8"},{"path":"Blue-Series/Zigbee/VZM31-SN-2-1-Switch/Production/3.04/VZM31-SN_3.04.ota","sha":"4804f29ee619f64d9e6dad7735f7444a005beec3"},{"path":"Blue-Series/Zigbee/VZM32-SN-MMWave-Switch/Beta/1.01/VZM32-SN_1.01.ota","sha":"8a54df449a31ba23d7a603947e9c241411496f06"},{"path":"Blue-Series/Zigbee/VZM32-SN-MMWave-Switch/Beta/1.02/vzm32-sn_mmWave_OTA_V102_20260330.ota","sha":"4766df93ec971556c6840a63db24dab530a80aec"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Beta/1.00/VZM35-SN_1.00-Beta.ota","sha":"64762ddcc442cf457f62c1c0c2dae2e4524f74f4"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Beta/1.02/VZM35-SN_1.02-Beta.ota","sha":"839a5cff006c0ffaed88b3dd18d3931f18917c21"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Beta/1.05/VZM35-SN_1.05.ota","sha":"f6450ef1c721cf95e54cd9da5f377dd8218b193e"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Beta/1.07/VZM35-SN_1.07.ota","sha":"4a5f8e88cfebdc9be97a23c467fcbcd4f2231492"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Production/1.04/VZM35-SN_1.04-Production.ota","sha":"abc0afc3bcbe4a5db4d410da27c221fcef74aa4e"},{"path":"Blue-Series/Zigbee/VZM35-SN-Fan-Switch/Production/1.08/VZM35-SN_1.08.ota","sha":"2d5986ec858cd12bc7d3d71a000a45faf64a1376"},{"path":"Blue-Series/Zigbee/VZM36-Fan-Plus-Light/Beta/0.04/VZM36_0.04.ota","sha":"9c756944ec73bfd0eb1247b7d0ba1f017736599b"},{"path":"Blue-Series/Zigbee/VZM36-Fan-Plus-Light/Beta/1.01/VZM36_1.01-Beta.ota","sha":"bb191e9730bdaacff206e87c343f76ac08faa25e"}] \ No newline at end of file diff --git a/src/autodl/inovelli.ts b/src/autodl/inovelli.ts index 6c8242d..e5056f0 100644 --- a/src/autodl/inovelli.ts +++ b/src/autodl/inovelli.ts @@ -1,5 +1,5 @@ import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js"; -import {ProcessFirmwareImageStatus, processFirmwareImage} from "../process_firmware_image.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type DeviceImageJson = { version: string; @@ -11,27 +11,10 @@ type DeviceImageJson = { type ModelsJson = { [k: string]: DeviceImageJson[]; }; -type GitHubTreeEntryJson = { - path: string; - sha: string; - type: "blob" | "commit" | "tree"; -}; -type GitHubTreeJson = { - tree: GitHubTreeEntryJson[]; - truncated: boolean; -}; -type GitHubFirmwareFile = { - path: string; - sha: string; -}; const NAME = "Inovelli"; const LOG_PREFIX = `[${NAME}]`; -const LEGACY_FIRMWARE_URL = "https://files.inovelli.com/firmware/firmware.json"; -const GITHUB_FIRMWARE_TREE_URL = "https://api.github.com/repos/InovelliUSA/Firmware/git/trees/main?recursive=1"; -const GITHUB_RAW_FIRMWARE_URL = "https://raw.githubusercontent.com/InovelliUSA/Firmware/main/"; -const GITHUB_ZIGBEE_PATH_PREFIX = "Blue-Series/Zigbee/"; -const GITHUB_CACHE_NAME = `${NAME}GitHub`; +const FIRMWARE_URL = "https://files.inovelli.com/firmware/firmware.json"; function sortByVersion(a: DeviceImageJson, b: DeviceImageJson): number { const aRadix = a.version.match(/[a-fA-F]/) ? 16 : 10; @@ -46,55 +29,16 @@ function isDifferent(newData: DeviceImageJson, cachedData?: DeviceImageJson): bo return Boolean(process.env.IGNORE_CACHE) || !cachedData || cachedData.version !== newData.version; } -export function getGitHubFirmwareFiles(githubTree: GitHubTreeJson): GitHubFirmwareFile[] { - if (githubTree.truncated) { - throw new Error(`${LOG_PREFIX} GitHub firmware tree is truncated.`); - } - - return githubTree.tree - .filter((entry) => entry.type === "blob" && entry.path.startsWith(GITHUB_ZIGBEE_PATH_PREFIX) && entry.path.toLowerCase().endsWith(".ota")) - .map(({path, sha}) => ({path, sha})) - .sort((a, b) => a.path.localeCompare(b.path)); -} - -export function getChangedGitHubFirmwareFiles( - githubFiles: GitHubFirmwareFile[], - cachedFiles: GitHubFirmwareFile[] = [], - ignoreCache = Boolean(process.env.IGNORE_CACHE), -): GitHubFirmwareFile[] { - if (ignoreCache) { - return githubFiles; - } - - const cachedFilesByPath = new Map(cachedFiles.map((file) => [file.path, file.sha])); - - return githubFiles.filter((file) => cachedFilesByPath.get(file.path) !== file.sha); -} - -export function getGitHubFirmwareUrl(filePath: string): string { - return GITHUB_RAW_FIRMWARE_URL + filePath.split("/").map(encodeURIComponent).join("/"); -} - export async function writeCache(): Promise { - const [models, githubTree] = await Promise.all([ - getJson(NAME, LEGACY_FIRMWARE_URL), - getJson(NAME, GITHUB_FIRMWARE_TREE_URL), - ]); + const models = await getJson(NAME, FIRMWARE_URL); if (models) { writeCacheJson(NAME, models); } - - if (githubTree) { - writeCacheJson(GITHUB_CACHE_NAME, getGitHubFirmwareFiles(githubTree)); - } } export async function download(): Promise { - const [models, githubTree] = await Promise.all([ - getJson(NAME, LEGACY_FIRMWARE_URL), - getJson(NAME, GITHUB_FIRMWARE_TREE_URL), - ]); + const models = await getJson(NAME, FIRMWARE_URL); if (models) { const cachedData = readCacheJson(NAME); @@ -123,31 +67,6 @@ export async function download(): Promise { writeCacheJson(NAME, models); } else { - console.error(`${LOG_PREFIX} No legacy image data.`); - } - - if (githubTree) { - const githubFiles = getGitHubFirmwareFiles(githubTree); - const cachedFiles = readCacheJson(GITHUB_CACHE_NAME); - const changedFiles = getChangedGitHubFirmwareFiles(githubFiles, cachedFiles); - const processedFiles = new Map(cachedFiles?.map((file) => [file.path, file])); - - for (const file of changedFiles) { - const firmwareFileName = file.path.split("/").pop()!; - const status = await processFirmwareImage(NAME, firmwareFileName, getGitHubFirmwareUrl(file.path)); - - if (status === ProcessFirmwareImageStatus.Success) { - processedFiles.set(file.path, file); - } else { - processedFiles.delete(file.path); - } - } - - writeCacheJson( - GITHUB_CACHE_NAME, - githubFiles.filter((file) => processedFiles.get(file.path)?.sha === file.sha), - ); - } else { - console.error(`${LOG_PREFIX} No GitHub image data.`); + console.error(`${LOG_PREFIX} No image data.`); } } diff --git a/tests/autodl_inovelli.test.ts b/tests/autodl_inovelli.test.ts deleted file mode 100644 index a9f35f7..0000000 --- a/tests/autodl_inovelli.test.ts +++ /dev/null @@ -1,77 +0,0 @@ -import {describe, expect, it} from "vitest"; -import {getChangedGitHubFirmwareFiles, getGitHubFirmwareFiles, getGitHubFirmwareUrl} from "../src/autodl/inovelli.js"; - -describe("Inovelli autodl", () => { - it("finds Zigbee OTA files in the GitHub tree", () => { - const files = getGitHubFirmwareFiles({ - truncated: false, - tree: [ - { - path: "Blue-Series/Zigbee/VZM31/Production/3.04/VZM31-SN_3.04.ota", - sha: "production", - type: "blob", - }, - { - path: "Blue-Series/Zigbee/VZM31/Beta/3.07/VZM31-SN_3.07.OTA", - sha: "beta", - type: "blob", - }, - { - path: "Blue-Series/Zigbee/VZM31/README.md", - sha: "readme", - type: "blob", - }, - { - path: "Red-Series/Z-Wave/VZW31/VZW31-SN_2.04.ota", - sha: "z-wave", - type: "blob", - }, - { - path: "Blue-Series/Zigbee/VZM31/Beta", - sha: "tree", - type: "tree", - }, - ], - }); - - expect(files).toStrictEqual([ - { - path: "Blue-Series/Zigbee/VZM31/Beta/3.07/VZM31-SN_3.07.OTA", - sha: "beta", - }, - { - path: "Blue-Series/Zigbee/VZM31/Production/3.04/VZM31-SN_3.04.ota", - sha: "production", - }, - ]); - }); - - it("rejects a truncated GitHub tree", () => { - expect(() => getGitHubFirmwareFiles({truncated: true, tree: []})).toThrow("GitHub firmware tree is truncated"); - }); - - it("finds new and changed GitHub firmware files", () => { - const files = [ - {path: "changed.ota", sha: "new"}, - {path: "new.ota", sha: "new"}, - {path: "unchanged.ota", sha: "same"}, - ]; - const cachedFiles = [ - {path: "changed.ota", sha: "old"}, - {path: "removed.ota", sha: "old"}, - {path: "unchanged.ota", sha: "same"}, - ]; - - expect(getChangedGitHubFirmwareFiles(files, cachedFiles, false)).toStrictEqual([ - {path: "changed.ota", sha: "new"}, - {path: "new.ota", sha: "new"}, - ]); - expect(getChangedGitHubFirmwareFiles(files, cachedFiles, true)).toStrictEqual(files); - }); - - it("builds an encoded raw GitHub URL", () => { - expect(getGitHubFirmwareUrl("Blue-Series/Zigbee/Fan Plus/Firmware 1.0.ota")).toBe( - "https://raw.githubusercontent.com/InovelliUSA/Firmware/main/Blue-Series/Zigbee/Fan%20Plus/Firmware%201.0.ota", - ); - }); -});