Skip to content

Commit

Permalink
Fix: Attempt (temporary hack) to address zigbee-OTA#328
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianMangold committed Sep 24, 2023
1 parent 9f31dbb commit caade1e
Showing 1 changed file with 20 additions and 5 deletions.
25 changes: 20 additions & 5 deletions src/lib/ota/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,27 @@ async function requestOTA(endpoint: Zh.Endpoint): Promise<{payload: Ota.ImageInf
}
}

function getImageBlockResponsePayload(image: Ota.Image, imageBlockRequest: KeyValueAny, pageOffset: number, pageSize: number) {
const start = imageBlockRequest.payload.fileOffset + pageOffset;
function getImageBlockResponsePayload(image: Ota.Image, imageBlockRequest: KeyValueAny, pageOffset: number, pageSize: number, logger: Logger) {
let start = imageBlockRequest.payload.fileOffset + pageOffset;
// When the data size is too big, OTA gets unstable, so default it to 50 bytes maximum.
// For Insta devices, OTA only works for data sizes 40 and smaller (= manufacturerCode 4474).
const maximumDataSize = imageBlockRequest.payload.manufacturerCode === 4474 ? 40 : 50;
// Legrand devices (newer firmware) require up to 64 bytes (= manufacturerCode 4129).
let maximumDataSize = 50;
if (imageBlockRequest.payload.manufacturerCode === 4474) maximumDataSize = 40;
else if (imageBlockRequest.payload.manufacturerCode === 4129) maximumDataSize = Infinity;

let dataSize = Math.min(maximumDataSize, imageBlockRequest.payload.maximumDataSize);

// Hack for Koenkk-OTA#328
if (imageBlockRequest.payload.manufacturerCode === 4129 &&
imageBlockRequest.payload.fileOffset === 50 &&
imageBlockRequest.payload.maximumDataSize === 12) {
logger.debug(`>> Detected Legrand Firmware issue (Koenkk-OTA#328). Attempting to reset the OTA stack <<`);
// The following vector seems to buffer overflow the device to reset the OTA stack!
start = 78;
dataSize = 64;
}

if (pageSize) {
dataSize = Math.min(dataSize, pageSize - pageOffset);
}
Expand Down Expand Up @@ -319,7 +334,7 @@ export async function updateToLatest(device: Zh.Device, logger: Logger, onProgre
let pageSize = 0;

const sendImageBlockResponse = (imageBlockRequest: KeyValueAny, thenCallback: () => void, transactionSequenceNumber: number) => {
const payload = getImageBlockResponsePayload(image, imageBlockRequest, pageOffset, pageSize);
const payload = getImageBlockResponsePayload(image, imageBlockRequest, pageOffset, pageSize, logger);
const now = Date.now();
const timeSinceLastImageBlockResponse = now - lastImageBlockResponse;

Expand Down Expand Up @@ -401,7 +416,7 @@ export async function updateToLatest(device: Zh.Device, logger: Logger, onProgre

let timer: ReturnType<typeof setTimeout> = null;
const cb = () => {
logger.debug('Got device announce or timed out, call resolve');
logger.debug(`Got device announce or timed out, call resolve`);
clearInterval(timer);
device.removeListener('deviceAnnounce', cb);
resolve(image.header.fileVersion);
Expand Down

0 comments on commit caade1e

Please sign in to comment.