diff --git a/images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE b/images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE new file mode 100644 index 00000000..a71a5cde Binary files /dev/null and b/images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE differ diff --git a/index.json b/index.json index 73e02fa9..ad70156f 100644 --- a/index.json +++ b/index.json @@ -1274,5 +1274,14 @@ "modelId": "GL-B-008P", "url": "https://github.com/Koenkk/zigbee-OTA/raw/master/images/Gledopto/GL-B-008P_V17A1_OTAV7.ota", "path": "images/Gledopto/GL-B-008P_V17A1_OTAV7.ota" + }, + { + "fileVersion": 318, + "fileSize": 176624, + "manufacturerCode": 10132, + "imageType": 2017, + "sha512": "5e36ceaa44c4b3e12f4ff415b00fb16a3d64aaa3d8bebaecc0590480f4850e8ff226be20356417da223679c4210b5c69e8159ae15628c098c59d074e86d97258", + "url": "https://github.com/Koenkk/zigbee-OTA/raw/master/images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE", + "path": "images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE" } ] \ No newline at end of file diff --git a/scripts/add.js b/scripts/add.js index 4b965187..a26ee647 100644 --- a/scripts/add.js +++ b/scripts/add.js @@ -1,132 +1,133 @@ -const path = require('path'); -const fs = require('fs'); -const crypto = require('crypto'); -const ota = require('../lib/ota'); -const filenameOrURL = process.argv[2]; -const modelId = process.argv[3]; -const baseURL = 'https://github.com/Koenkk/zigbee-OTA/raw/master'; - -const manufacturerNameLookup = { - 4107: 'Hue', - 4474: 'Insta', - 4448: 'Sengled', - 4420: 'Lutron', - 4405: 'DresdenElektronik', - 4489: 'Ledvance', - 4364: 'Osram', - 4648: 'Terncy', - 4098: 'Tuya', - 4151: 'Eurotronic', - 4678: 'Danfoss', - 4687: 'Gledopto', - 4919: 'Datek', - 4447: 'Xiaomi', -}; - -const main = async () => { - if (!filenameOrURL) { - throw new Error('Please provide a filename or URL'); - } - - const isURL = filenameOrURL.toLowerCase().startsWith("http"); - let file = null; - - if (isURL) { - const downloadFile = async (url, path) => { - const lib = url.toLowerCase().startsWith("https") ? require('https') : require('http'); - const file = fs.createWriteStream(path); - - return new Promise((resolve) => { - const request = lib.get(url, function(response) { - response.pipe(file); - file.on('finish', function() { - file.close(function() { - resolve(); - }); - }); - }); - }); - } - - file = path.resolve("temp"); - await downloadFile(filenameOrURL, file); - } else { - file = path.resolve(filenameOrURL); - if (!fs.existsSync(file)) { - throw new Error(`${file} does not exist`); - } - } - - const buffer = fs.readFileSync(file); - const parsed = ota.parseImage(buffer); - - if (!manufacturerNameLookup[parsed.header.manufacturerCode]) { - throw new Error(`${parsed.header.manufacturerCode} not in manufacturerNameLookup (please add it)`); - } - - const manufacturerName = manufacturerNameLookup[parsed.header.manufacturerCode]; - const indexJSON = JSON.parse(fs.readFileSync('index.json')); - const destination = path.join('images', manufacturerName, path.basename(file)); - - const hash = crypto.createHash('sha512'); - hash.update(buffer); - - const entry = { - fileVersion: parsed.header.fileVersion, - fileSize: parsed.header.totalImageSize, - manufacturerCode: parsed.header.manufacturerCode, - imageType: parsed.header.imageType, - sha512: hash.digest('hex'), - }; - - if (modelId) { - entry.modelId = modelId; - } - - if (isURL) { - entry.url = filenameOrURL; - } else { - const destinationPosix = destination.replace(/\\/g, '/'); - entry.url = `${baseURL}/${escape(destinationPosix)}`; - entry.path = destinationPosix; - } - - const index = indexJSON.findIndex((i) => { - return i.manufacturerCode === entry.manufacturerCode && i.imageType === entry.imageType && (!i.modelId || i.modelId === entry.modelId) - }); - - if (index !== -1) { - console.log(`Updated existing entry (${JSON.stringify(entry)})`); - indexJSON[index] = entry; - - if (entry.path && entry.path !== destination) { - try { - fs.unlinkSync(path.resolve(entry.path)); - } catch (err) { - if (err && err.code != 'ENOENT') { - console.error("Error in call to fs.unlink", err); - throw err; - } - } - } - } else { - console.log(`Added new entry (${JSON.stringify(entry)})`); - indexJSON.push(entry); - } - - if (!isURL && file !== path.resolve(destination)) { - if (!fs.existsSync(path.dirname(destination))) { - fs.mkdirSync(path.dirname(destination)); - } - - fs.copyFileSync(file, destination); - } - - fs.writeFileSync('index.json', JSON.stringify(indexJSON, null, ' ')); - - if (isURL) { - fs.unlinkSync(file); - } -} - -return main(); +const path = require('path'); +const fs = require('fs'); +const crypto = require('crypto'); +const ota = require('../lib/ota'); +const filenameOrURL = process.argv[2]; +const modelId = process.argv[3]; +const baseURL = 'https://github.com/Koenkk/zigbee-OTA/raw/master'; + +const manufacturerNameLookup = { + 4107: 'Hue', + 4474: 'Insta', + 4448: 'Sengled', + 4420: 'Lutron', + 4405: 'DresdenElektronik', + 4489: 'Ledvance', + 4364: 'Osram', + 4648: 'Terncy', + 4098: 'Tuya', + 4151: 'Eurotronic', + 4678: 'Danfoss', + 4687: 'Gledopto', + 4919: 'Datek', + 4447: 'Xiaomi', + 10132: 'ClimaxTechnology', +}; + +const main = async () => { + if (!filenameOrURL) { + throw new Error('Please provide a filename or URL'); + } + + const isURL = filenameOrURL.toLowerCase().startsWith("http"); + let file = null; + + if (isURL) { + const downloadFile = async (url, path) => { + const lib = url.toLowerCase().startsWith("https") ? require('https') : require('http'); + const file = fs.createWriteStream(path); + + return new Promise((resolve) => { + const request = lib.get(url, function(response) { + response.pipe(file); + file.on('finish', function() { + file.close(function() { + resolve(); + }); + }); + }); + }); + } + + file = path.resolve("temp"); + await downloadFile(filenameOrURL, file); + } else { + file = path.resolve(filenameOrURL); + if (!fs.existsSync(file)) { + throw new Error(`${file} does not exist`); + } + } + + const buffer = fs.readFileSync(file); + const parsed = ota.parseImage(buffer); + + if (!manufacturerNameLookup[parsed.header.manufacturerCode]) { + throw new Error(`${parsed.header.manufacturerCode} not in manufacturerNameLookup (please add it)`); + } + + const manufacturerName = manufacturerNameLookup[parsed.header.manufacturerCode]; + const indexJSON = JSON.parse(fs.readFileSync('index.json')); + const destination = path.join('images', manufacturerName, path.basename(file)); + + const hash = crypto.createHash('sha512'); + hash.update(buffer); + + const entry = { + fileVersion: parsed.header.fileVersion, + fileSize: parsed.header.totalImageSize, + manufacturerCode: parsed.header.manufacturerCode, + imageType: parsed.header.imageType, + sha512: hash.digest('hex'), + }; + + if (modelId) { + entry.modelId = modelId; + } + + if (isURL) { + entry.url = filenameOrURL; + } else { + const destinationPosix = destination.replace(/\\/g, '/'); + entry.url = `${baseURL}/${escape(destinationPosix)}`; + entry.path = destinationPosix; + } + + const index = indexJSON.findIndex((i) => { + return i.manufacturerCode === entry.manufacturerCode && i.imageType === entry.imageType && (!i.modelId || i.modelId === entry.modelId) + }); + + if (index !== -1) { + console.log(`Updated existing entry (${JSON.stringify(entry)})`); + indexJSON[index] = entry; + + if (entry.path && entry.path !== destination) { + try { + fs.unlinkSync(path.resolve(entry.path)); + } catch (err) { + if (err && err.code != 'ENOENT') { + console.error("Error in call to fs.unlink", err); + throw err; + } + } + } + } else { + console.log(`Added new entry (${JSON.stringify(entry)})`); + indexJSON.push(entry); + } + + if (!isURL && file !== path.resolve(destination)) { + if (!fs.existsSync(path.dirname(destination))) { + fs.mkdirSync(path.dirname(destination)); + } + + fs.copyFileSync(file, destination); + } + + fs.writeFileSync('index.json', JSON.stringify(indexJSON, null, ' ')); + + if (isURL) { + fs.unlinkSync(file); + } +} + +return main();