OTA updates: add update_check_interval and disable_automatic_update_check options (#6268)

* OTA privacy enhancement

Adds the option to disallow device-initiated OTA update checks.

Currently these OTA update checks can be quite frequent, and essentially mean the device is indirectly able to ping a cloud server. In the EU it's wise to handle an IP address as personal information, and therefore it might be wise to not enable OTA checking by default. Ideally a user would agree to a privacy policy that clarifies things a bit first.

* Added default settings for OTA update management

* Set update interval in minutes

* OTA update settings

* Adds both settings for OTA updates control

* Update settings.schema.json

* Update settings.js

* Update otaUpdate.js

* Update otaUpdate.test.js

* Update bridge.test.js

Co-authored-by: Koen Kanters <koenkanters94@gmail.com>
This commit is contained in:
flatsiedatsie
2021-02-14 18:20:32 +01:00
committed by GitHub
co-authored by Koen Kanters
parent 89a9dbba42
commit 9dd9f33b4a
5 changed files with 49 additions and 5 deletions
+5 -4
View File
@@ -8,7 +8,6 @@ const topicRegex =
new RegExp(`^${settings.get().mqtt.base_topic}/bridge/request/device/ota_update/(update|check)`, 'i');
const Extension = require('./extension');
const MINUTES_10 = 1000 * 60 * 10;
class OTAUpdate extends Extension {
constructor(zigbee, mqtt, state, publishEntityState, eventBus) {
@@ -36,15 +35,17 @@ class OTAUpdate extends Extension {
}
async onZigbeeEvent(type, data, resolvedEntity) {
if (settings.get().ota.disable_automatic_update_check) return;
if (data.type !== 'commandQueryNextImageRequest' || !resolvedEntity || !resolvedEntity.definition) return;
const supportsOTA = resolvedEntity.definition.hasOwnProperty('ota');
if (supportsOTA) {
// When a device does a next image request, it will usually do it a few times after each other
// with only 10 - 60 seconds inbetween. It doesn' make sense to check for a new update
// each time.
// with only 10 - 60 seconds inbetween. It doesn't make sense to check for a new update
// each time, so this interval can be set by the user. The default is 10 minutes.
const updateCheckInterval = settings.get().ota.update_check_interval * 1000 * 60;
const check = this.lastChecked.hasOwnProperty(data.device.ieeeAddr) ?
(Date.now() - this.lastChecked[data.device.ieeeAddr]) > MINUTES_10 : true;
(Date.now() - this.lastChecked[data.device.ieeeAddr]) > updateCheckInterval : true;
if (!check || this.inProgress.has(data.device.ieeeAddr)) return;
this.lastChecked[data.device.ieeeAddr] = Date.now();
+11
View File
@@ -137,6 +137,17 @@ const defaults = {
*/
timestamp_format: 'YYYY-MM-DD HH:mm:ss',
},
ota: {
/**
* Minimal time delta in milliseconds between polling third party server for potential firmware updates
*/
update_check_interval: 10,
/**
* Completely disallow Zigbee devices to initiate a search for a potential firmware update.
* If set to true, only a user-initiated update search will be possible.
*/
disable_automatic_update_check: false,
},
external_converters: [],
};
+18
View File
@@ -509,6 +509,24 @@
}
}
},
"ota": {
"type": "object",
"title": "OTA updates",
"properties": {
"update_check_interval": {
"type": "boolean",
"title": "Update check interval",
"description": "Your device may request a check for a new firmware update. This value determines how frequently third party servers may actually be contacted to look for firmware updates. The value is set in minutes, and the default is 10.",
"default": 10
},
"disable_automatic_update_check": {
"type": "boolean",
"title": "Disable automatic update check",
"description": "Zigbee devices may request a firmware update, and do so frequently, causing Zigbee2MQTT to reach out to third party servers. If you disable these device initiated checks, you can still initiate a firmware update check manually.",
"default": false
}
}
},
"devices": {
"type": "object",
"propertyNames": {
+1 -1
View File
File diff suppressed because one or more lines are too long
+14
View File
@@ -250,6 +250,20 @@ describe('OTA update', () => {
);
});
it('Should not check for update when device requests it and disable_automatic_update_check is set to true', async () => {
settings.set(['ota', 'disable_automatic_update_check'], true);
const device = zigbeeHerdsman.devices.bulb;
const data = {imageType: 12382};
const mapped = zigbeeHerdsmanConverters.findByDevice(device)
mockClear(mapped);
mapped.ota.isUpdateAvailable.mockReturnValueOnce(true);
const payload = {data, cluster: 'genOta', device, endpoint: device.getEndpoint(1), type: 'commandQueryNextImageRequest', linkquality: 10};
logger.info.mockClear();
await zigbeeHerdsman.events.message(payload);
await flushPromises();
expect(mapped.ota.isUpdateAvailable).toHaveBeenCalledTimes(0);
});
it('Should respond with NO_IMAGE_AVAILABLE when not supporting OTA', async () => {
const device = zigbeeHerdsman.devices.QBKG04LM;
const data = {imageType: 12382};