From e49b4eb7b85dd93aa0ca44670de8b0d7814b04f6 Mon Sep 17 00:00:00 2001 From: Sieren Date: Sun, 5 Sep 2021 18:35:34 +0200 Subject: [PATCH] Add Eve Room 2 Support Add support for Eve Room 2 using its characteristics and different data stream. Room 2 accepts VOC in ug/m3, though the app displays these values as ppb (ug/m3 * 4.57 = ppb). --- README.md | 9 ++++++++- fakegato-history.js | 27 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 687ba84..0351dfb 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ And if your plugin is using V2 of the platform API, also add the above to your c where -- accessoryType can be "weather", "energy", "room", "door", motion", "switch", "thermo", "aqua", or "custom" +- accessoryType can be "weather", "energy", "room", "room2, "door", motion", "switch", "thermo", "aqua", or "custom" - Accessory should be the accessory using the service, in order to correctly set the service name and pass the log to the parent object. Your Accessory should have a `this.log` variable pointing to the homebridge logger passed to the plugin constructor (add a line `this.log=log;` to your plugin). Debug messages will be shown if homebridge is launched with -D option. - length is the history length; if no value is given length is set to 4032 samples @@ -65,6 +65,12 @@ Depending on your accessory type: Temperature in Celsius, Humidity in %. Entries are internally averaged and sent every 10 minutes using the global fakegato timer. Your entries should be in any case periodic, in order to avoid error with the average. Average is done independently on each quantity (i.e. you may different periods, and entries with only one or two quantities) +* Add entries to history of accessory emulating **Eve Room 2** (TempSensor, HumiditySensor and AirQuality Services) using something like this: + + this.loggingService.addEntry({time: Math.round(new Date().valueOf() / 1000), temp: this.temperature, humidity: this.humidity, voc: this.voc}); + + Temperature in Celsius, Humidity in % and VOC in µg/m3. The Eve App will convert µg/m3 to ppb (by dividing by 4.57). Entries are internally averaged and sent every 10 minutes using the global fakegato timer. Your entries should be in any case periodic, in order to avoid error with the average. Average is done independently on each quantity (i.e. you may different periods, and entries with only one or two quantities) + * Add entries to history of accessory emulating **Eve Door** (ContactSensor service) using something like this on every status change: this.loggingService.addEntry({time: Math.round(new Date().valueOf() / 1000), status: this.status}); @@ -114,6 +120,7 @@ Depending on your accessory type: contact | contact sensor state ( 0 / 1 ) status | switch status ( 0 / 1 ) motion | motion sensor state ( 0 / 1 ) + voc | µg/m3 For Energy and Door accessories it is also worth to add the custom characteristic E863F112 for resetting, respectively, the Total Consumption accumulated value or the Aperture Counter (not the history). See Wiki. The value of this characteristic is changed whenever the reset button is tapped on Eve, so it can be used to reset the locally stored value. The value seems to be the number of seconds from 1.1.2001. I left this characteristics out of fakegato-history because it is not part of the common history service. diff --git a/fakegato-history.js b/fakegato-history.js index ec0e799..480ae00 100644 --- a/fakegato-history.js +++ b/fakegato-history.js @@ -9,6 +9,7 @@ const EPOCH_OFFSET = 978307200; const TYPE_ENERGY = 'energy', TYPE_ROOM = 'room', + TYPE_ROOM2 = 'room2', TYPE_WEATHER = 'weather', TYPE_DOOR = 'door', TYPE_MOTION = 'motion', @@ -232,6 +233,13 @@ module.exports = function (pHomebridge) { homebridge.globalFakeGatoTimer.subscribe(this, this.calculateAverage); } break; + case TYPE_ROOM2: + this.accessoryType116 = "07 0102 0202 2202 2901 2501 2302 2801"; + this.accessoryType117 = "7f"; + if (!this.disableTimer) { + homebridge.globalFakeGatoTimer.subscribe(this, this.calculateAverage); + } + break; case TYPE_DOOR: this.accessoryType116 = "01 0601"; this.accessoryType117 = "01"; @@ -321,6 +329,9 @@ module.exports = function (pHomebridge) { case Characteristic.CurrentTemperature.UUID: // Temperature this.signatures.push({ signature: '0102', length: 4, uuid: this.uuid.toShortFormUUID(characteristic.UUID), factor: 100, entry: "temp" }); break; + case Characteristic.VOCDensity.UUID: // Temperature + this.signatures.push({ signature: '2202', length: 4, uuid: this.uuid.toShortFormUUID(characteristic.UUID), factor: 1, entry: "voc" }); + break; case Characteristic.CurrentRelativeHumidity.UUID: // Humidity this.signatures.push({ signature: '0202', length: 4, uuid: this.uuid.toShortFormUUID(characteristic.UUID), factor: 100, entry: "humidity" }); break; @@ -503,6 +514,12 @@ module.exports = function (pHomebridge) { else this._addEntry({ time: entry.time, temp: entry.temp, humidity: entry.humidity, ppm: entry.ppm }); break; + case TYPE_ROOM2: + if (!this.disableTimer) + homebridge.globalFakeGatoTimer.addData({ entry: entry, service: this }); + else + this._addEntry({ time: entry.time, temp: entry.temp, humidity: entry.humidity, voc: entry.voc }); + break; case TYPE_ENERGY: if (!this.disableTimer) homebridge.globalFakeGatoTimer.addData({ entry: entry, service: this }); @@ -731,6 +748,16 @@ module.exports = function (pHomebridge) { numToHex(swap16(this.history[this.memoryAddress].humidity * 100), 4), numToHex(swap16(this.history[this.memoryAddress].ppm), 4)); break; + case TYPE_ROOM2: + this.dataStream += Format( + ",15 %s%s%s%s%s%s0054 a80f01", + numToHex(swap32(this.currentEntry), 8), + numToHex(swap32(this.history[this.memoryAddress].time - this.refTime - EPOCH_OFFSET), 8), + this.accessoryType117, + numToHex(swap16(this.history[this.memoryAddress].temp * 100), 4), + numToHex(swap16(this.history[this.memoryAddress].humidity * 100), 4), + numToHex(swap16(this.history[this.memoryAddress].voc), 4)); + break; case TYPE_DOOR: case TYPE_MOTION: case TYPE_SWITCH: