mirror of
https://github.com/Koenkk/zigbee-OTA.git
synced 2026-06-24 10:58:33 +00:00
feat: Add autodl for Hue (partial) (#663)
This commit is contained in:
22
README.md
22
README.md
@@ -78,18 +78,18 @@ Any field not in this list will be ignored. Any field not matching the required
|
||||
|
||||
###### To place restrictions
|
||||
|
||||
- "force": boolean _(ignore `fileVersion` and always present as 'available')_
|
||||
- "hardwareVersionMax": number
|
||||
- "hardwareVersionMin": number
|
||||
- "manufacturerName": array of strings _(target only devices with one of these manufacturer names)_
|
||||
- "maxFileVersion": number _(target only devices with this version or below)_
|
||||
- "minFileVersion": number _(target only devices with this version or above)_
|
||||
- "modelId": string _(target only devices with this model ID)_
|
||||
- "force": boolean _(ignore `fileVersion` and always present as 'available')_
|
||||
- "hardwareVersionMax": number
|
||||
- "hardwareVersionMin": number
|
||||
- "manufacturerName": array of strings _(target only devices with one of these manufacturer names)_
|
||||
- "maxFileVersion": number _(target only devices with this version or below)_
|
||||
- "minFileVersion": number _(target only devices with this version or above)_
|
||||
- "modelId": string _(target only devices with this model ID)_
|
||||
|
||||
###### For record purpose
|
||||
|
||||
- "originalUrl": string
|
||||
- "releaseNotes": string
|
||||
- "originalUrl": string
|
||||
- "releaseNotes": string
|
||||
|
||||
If the pull request contains multiple files, the metadata is added for all files. If some files require different metadata, add the matching `fileName` to the JSON using an encompassing array instead. It will be used to assign metadata as directed.
|
||||
|
||||
@@ -114,8 +114,8 @@ Example:
|
||||
|
||||
### Notes for maintainers & developers
|
||||
|
||||
- `images` and `index.json` contain added (PR or auto download) "upgrade" images.
|
||||
- `images1` and `index1.json` contain automatically archived "downgrade" images (automatically moved from `images`/`index.json` after a merged PR introduced a newer version, or during auto download).
|
||||
- `images` and `index.json` contain added (PR or auto download) "upgrade" images.
|
||||
- `images1` and `index1.json` contain automatically archived "downgrade" images (automatically moved from `images`/`index.json` after a merged PR introduced a newer version, or during auto download).
|
||||
|
||||
If a manual modification of the manifests is necessary, it should be done in a PR that does not trigger the `update_ota_pr` workflow (no changes in `images/**` directory). As a last resort, the label `ignore-ota-workflow` can be added to prevent the workflow from running.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "zigbee-ota",
|
||||
"version": "1.1.1",
|
||||
"version": "1.2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/Koenkk/zigbee-OTA.git"
|
||||
|
||||
105
src/autodl/hue.ts
Normal file
105
src/autodl/hue.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js';
|
||||
import {processFirmwareImage} from '../process_firmware_image.js';
|
||||
|
||||
type ImageJson = {
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
fileSize: number;
|
||||
md5: string;
|
||||
binaryUrl: string;
|
||||
version: number;
|
||||
versionName: string;
|
||||
releaseNotes: string;
|
||||
};
|
||||
type PageJson = {updates: ImageJson[]};
|
||||
|
||||
const NAME = 'Hue';
|
||||
const BASE_URL = 'https://firmware.meethue.com/v1/checkupdate?version=0&deviceTypeId=';
|
||||
const DEVICE_TYPE_IDS: string[] = [
|
||||
'100b-111',
|
||||
'100b-112',
|
||||
// '100b-113',
|
||||
'100b-114',
|
||||
'100b-115',
|
||||
// '100b-116',
|
||||
'100b-117',
|
||||
'100b-118',
|
||||
// '100b-119',
|
||||
'100b-11a',
|
||||
// '100b-11b',
|
||||
// '100b-11c',
|
||||
'100b-11d',
|
||||
'100b-11e',
|
||||
'100b-11f',
|
||||
'100b-120',
|
||||
// '100b-121',
|
||||
// '100b-122',
|
||||
'100b-123',
|
||||
// '100b-124',
|
||||
'100b-125',
|
||||
// '100b-126',
|
||||
'100b-127',
|
||||
// '100b-128',
|
||||
'100b-129',
|
||||
// '100b-12a',
|
||||
// '100b-12b',
|
||||
// '100b-12c',
|
||||
// '100b-12d',
|
||||
// '100b-12e',
|
||||
// '100b-12f',
|
||||
];
|
||||
|
||||
function sortByVersion(a: ImageJson, b: ImageJson): number {
|
||||
return a.version < b.version ? -1 : a.version > b.version ? 1 : 0;
|
||||
}
|
||||
|
||||
function isDifferent(newData: PageJson, cachedData?: PageJson): boolean {
|
||||
return (
|
||||
Boolean(process.env.IGNORE_CACHE) ||
|
||||
!cachedData?.updates.length ||
|
||||
getLatestImage(cachedData.updates, sortByVersion)?.version !== getLatestImage(newData.updates, sortByVersion)?.version
|
||||
);
|
||||
}
|
||||
|
||||
export async function writeCache(): Promise<void> {
|
||||
for (const deviceTypeId of DEVICE_TYPE_IDS) {
|
||||
const url = `${BASE_URL}${deviceTypeId}`;
|
||||
const page = await getJson<PageJson>(NAME, url);
|
||||
|
||||
if (page?.updates.length) {
|
||||
writeCacheJson(`${NAME}_${deviceTypeId}`, page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function download(): Promise<void> {
|
||||
for (const deviceTypeId of DEVICE_TYPE_IDS) {
|
||||
const logPrefix = `[${NAME}:${deviceTypeId}]`;
|
||||
const url = `${BASE_URL}${deviceTypeId}`;
|
||||
const page = await getJson<PageJson>(NAME, url);
|
||||
|
||||
if (!page?.updates.length) {
|
||||
console.error(`${logPrefix} No image data.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const cacheFileName = `${NAME}_${deviceTypeId}`;
|
||||
|
||||
if (!isDifferent(page, readCacheJson(cacheFileName))) {
|
||||
console.log(`${logPrefix} No change from last run.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
writeCacheJson(cacheFileName, page);
|
||||
|
||||
const image = getLatestImage(page.updates, sortByVersion);
|
||||
|
||||
if (!image) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const firmwareFileName = image.binaryUrl.split('/').pop()!;
|
||||
|
||||
await processFirmwareImage(NAME, firmwareFileName, image.binaryUrl, {releaseNotes: image.releaseNotes || undefined});
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ export const PR_ARTIFACT_NUMBER_FILEPATH = path.join(PR_ARTIFACT_DIR, PR_NUMBER_
|
||||
*/
|
||||
export const ALL_AUTODL_MANUFACTURERS = [
|
||||
'gammatroniques',
|
||||
'hue',
|
||||
'ikea_new',
|
||||
'ikea',
|
||||
'inovelli',
|
||||
|
||||
@@ -462,6 +462,7 @@ describe('Github Workflow: Re-Process All Images', () => {
|
||||
ok: fetchReturnedStatus.ok,
|
||||
status: fetchReturnedStatus.status,
|
||||
body: fetchReturnedStatus.body,
|
||||
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath((input as string).split('/').pop()!)),
|
||||
};
|
||||
},
|
||||
@@ -762,6 +763,7 @@ describe('Github Workflow: Re-Process All Images', () => {
|
||||
ok: fetchReturnedStatus.ok,
|
||||
status: fetchReturnedStatus.status,
|
||||
body: fetchReturnedStatus.body,
|
||||
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(fileName)),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -134,6 +134,7 @@ describe('Process Firmware Image', () => {
|
||||
ok: fetchReturnedStatus.ok,
|
||||
status: fetchReturnedStatus.status,
|
||||
body: fetchReturnedStatus.body,
|
||||
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(input as string)),
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user