mirror of
https://github.com/Koenkk/zigbee-OTA.git
synced 2026-10-07 11:27:43 +00:00
feat: Add autodl for Hue (partial) (#663)
This commit is contained in:
@@ -78,18 +78,18 @@ Any field not in this list will be ignored. Any field not matching the required
|
|||||||
|
|
||||||
###### To place restrictions
|
###### To place restrictions
|
||||||
|
|
||||||
- "force": boolean _(ignore `fileVersion` and always present as 'available')_
|
- "force": boolean _(ignore `fileVersion` and always present as 'available')_
|
||||||
- "hardwareVersionMax": number
|
- "hardwareVersionMax": number
|
||||||
- "hardwareVersionMin": number
|
- "hardwareVersionMin": number
|
||||||
- "manufacturerName": array of strings _(target only devices with one of these manufacturer names)_
|
- "manufacturerName": array of strings _(target only devices with one of these manufacturer names)_
|
||||||
- "maxFileVersion": number _(target only devices with this version or below)_
|
- "maxFileVersion": number _(target only devices with this version or below)_
|
||||||
- "minFileVersion": number _(target only devices with this version or above)_
|
- "minFileVersion": number _(target only devices with this version or above)_
|
||||||
- "modelId": string _(target only devices with this model ID)_
|
- "modelId": string _(target only devices with this model ID)_
|
||||||
|
|
||||||
###### For record purpose
|
###### For record purpose
|
||||||
|
|
||||||
- "originalUrl": string
|
- "originalUrl": string
|
||||||
- "releaseNotes": 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.
|
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
|
### Notes for maintainers & developers
|
||||||
|
|
||||||
- `images` and `index.json` contain added (PR or auto download) "upgrade" images.
|
- `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).
|
- `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.
|
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
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "zigbee-ota",
|
"name": "zigbee-ota",
|
||||||
"version": "1.1.1",
|
"version": "1.2.0",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/Koenkk/zigbee-OTA.git"
|
"url": "git+https://github.com/Koenkk/zigbee-OTA.git"
|
||||||
|
|||||||
@@ -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 = [
|
export const ALL_AUTODL_MANUFACTURERS = [
|
||||||
'gammatroniques',
|
'gammatroniques',
|
||||||
|
'hue',
|
||||||
'ikea_new',
|
'ikea_new',
|
||||||
'ikea',
|
'ikea',
|
||||||
'inovelli',
|
'inovelli',
|
||||||
|
|||||||
@@ -462,6 +462,7 @@ describe('Github Workflow: Re-Process All Images', () => {
|
|||||||
ok: fetchReturnedStatus.ok,
|
ok: fetchReturnedStatus.ok,
|
||||||
status: fetchReturnedStatus.status,
|
status: fetchReturnedStatus.status,
|
||||||
body: fetchReturnedStatus.body,
|
body: fetchReturnedStatus.body,
|
||||||
|
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath((input as string).split('/').pop()!)),
|
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath((input as string).split('/').pop()!)),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@@ -762,6 +763,7 @@ describe('Github Workflow: Re-Process All Images', () => {
|
|||||||
ok: fetchReturnedStatus.ok,
|
ok: fetchReturnedStatus.ok,
|
||||||
status: fetchReturnedStatus.status,
|
status: fetchReturnedStatus.status,
|
||||||
body: fetchReturnedStatus.body,
|
body: fetchReturnedStatus.body,
|
||||||
|
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(fileName)),
|
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(fileName)),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ describe('Process Firmware Image', () => {
|
|||||||
ok: fetchReturnedStatus.ok,
|
ok: fetchReturnedStatus.ok,
|
||||||
status: fetchReturnedStatus.status,
|
status: fetchReturnedStatus.status,
|
||||||
body: fetchReturnedStatus.body,
|
body: fetchReturnedStatus.body,
|
||||||
|
// @ts-expect-error Buffer <> ArrayBuffer (props not used)
|
||||||
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(input as string)),
|
arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath(input as string)),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user