mirror of
https://github.com/Koenkk/zigbee-OTA.git
synced 2026-06-24 12:44:25 +00:00
Add OTA for LUPUS LS12128 (#42)
* Add manufacturer 10132: ClimaxTechnology, Add OTA for LUPUS LS12128, update all -Add.js: add manufacturer 10132: ClimaxTechnology (resold by LUPUS) -Add OTA for LUPUS LS12128 image -update add.js, index.json, images (updateall.js) * Update add.js * Update add.js * Create 12128_OTA_3.18.ZIGBEE Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
This commit is contained in:
BIN
images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE
Normal file
BIN
images/ClimaxTechnology/12128_OTA_3.18.ZIGBEE
Normal file
Binary file not shown.
@@ -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"
|
||||
}
|
||||
]
|
||||
265
scripts/add.js
265
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();
|
||||
|
||||
Reference in New Issue
Block a user