diff --git a/lib/ServiceDelegate/History.js b/lib/ServiceDelegate/History.js index 433d6f7..e1042af 100644 --- a/lib/ServiceDelegate/History.js +++ b/lib/ServiceDelegate/History.js @@ -76,7 +76,7 @@ class HistoryValue { * @params {Buffer} buffer - The buffer to write to. * @params {integer} offset - The offset within the buffer. */ - writeEntry (entry, buffer, offset) { buffer.writeUInt16LE(entry[this.id], offset) } + writeEntry (entry, buffer, offset) { buffer.writeInt16LE(entry[this.id], offset) } } class TemperatureValue extends HistoryValue { @@ -133,69 +133,97 @@ class ContactValue extends HistoryValue { } } +// Device delivers consumption in kWh. class ConsumptionValue extends HistoryValue { get tag () { return 0x07 } get id () { return 'p' } constructor (parent, delegate) { super(parent, delegate) - this._consumption = delegate.value + this._consumption = delegate.value // kWh this._time = History.now() } prepareEntry (entry) { - const delta = this._delegate.value - this._consumption // kWh - const period = entry.time - this._time // s - const power = period === 0 ? 0 : 1000 * 3600 * delta / period // W + let delta = this._delegate.value - this._consumption // kWh + delta *= 1000 // Wh + entry[this.id] = Math.round(delta * 10) // 0.1 Wh if (this._parent.computedPowerDelegate != null) { + // Optionally compute (average) power. + delta *= 3600 // Ws + const period = entry.time - this._time // s + const power = period === 0 ? 0 : delta / period // W this._parent.computedPowerDelegate.value = Math.round(power) // W } - entry[this.id] = Math.round(power * 10) // 0.1 W * 10 min - this._consumption = this._delegate.value + this._consumption -= this._delegate.value this._time = entry.time } } +// Device delivers power in W. class PowerValue extends HistoryValue { get tag () { return 0x07 } get id () { return 'p' } constructor (parent, delegate) { super(parent, delegate) - this._runningConsumption = 0 // 10-min-interval running value - this._totalConsumption = parent.computedConsumptionDelegate.value * 100 - this._power = delegate.value // current power - this._time = History.now() // start time of current power + this._runningConsumption = 0 // Ws + this._totalConsumption = parent.computedConsumptionDelegate.value // kWh + this._totalConsumption *= 3600 * 1000 // Ws + this._power = delegate.value // W + this._time = History.now() delegate.on('didSet', (value) => { const now = History.now() const delta = this._power * (now - this._time) // Ws - this._runningConsumption += Math.round(delta / 60.0) // 0.1W * 10 min - this._totalConsumption += delta / 36000.0 // 0.01 kWh - this._power = value + this._runningConsumption += delta // Ws + this._totalConsumption += delta // Ws + this._power = value // W this._time = now }) parent.addCharacteristicDelegate({ key: 'resetTotal', Characteristic: parent.Characteristics.eve.ResetTotal }).on('didSet', (value) => { - this._runningConsumption = 0 - this._totalConsumption = 0 - parent.computedConsumptionDelegate.value = this._totalConsumption + this._runningConsumption = 0 // Ws + this._totalConsumption = 0 // Ws + const totalConsumption = this._totalConsumption * 3600 * 1000 * 100 // 0.01 kWh + parent.computedConsumptionDelegate.value = Math.round(totalConsumption) / 100.0 // kWh }) } prepareEntry (entry) { const delta = this._power * (entry.time - this._time) // Ws - this._runningConsumption += delta / 60.0 // 0.1 W * 10 min - this._totalConsumption += delta / 36000.0 // 0.01 kWh - this._parent.computedConsumptionDelegate.value = Math.round(this._totalConsumption) / 100.0 // kWh - entry[this.id] = Math.round(this._runningConsumption) // 0.1 W * 10 min + this._runningConsumption += delta // Ws + this._totalConsumption += delta // Ws + const consumption = this.this._runningConsumption * 3600 // Wh + entry[this.id] = Math.round(consumption * 10) // 0.1 Wh + const totalConsumption = this._totalConsumption * 3600 * 1000 * 100 // 0.01 kWh + this._parent.computedConsumptionDelegate.value = Math.round(totalConsumption) / 100.0 // kWh this._power = this._delegate.value this._time = entry.time this._runningConsumption = 0 } } +// Device delivers running avarage of power in W. +class AveragePowerValue extends HistoryValue { + get tag () { return 0x07 } + get id () { return 'p' } + + constructor (parent, delegate) { + super(parent, delegate) + this._time = History.now() + } + + prepareEntry (entry) { + const delta = entry.time - this._time // s + let consumption = this._delegate.value * delta // Ws + consumption *= 3600 // Wh + entry[this.id] = Math.round(consumption * 10) // 0.1 Wh + this._time = entry.time + } +} + class SwitchOnValue extends HistoryValue { get tag () { return 0x0E } get length () { return 1 } @@ -285,6 +313,7 @@ const historyValueTypes = { airPressure: AirPressureValue, contact: ContactValue, power: PowerValue, + averagePower: AveragePowerValue, switchOn: SwitchOnValue, consumption: ConsumptionValue, valvePosition: ValvePositionValue, @@ -597,12 +626,14 @@ class History extends ServiceDelegate { let bitmap = 0 let offset = 1 for (const i in this._valueTypes) { - const valueType = this._valueTypes[i] - if (entry[valueType.id] != null) { - bitmap |= 0x01 << i - valueType.writeEntry(entry, buffer, offset) - offset += valueType.length - } + try { + const valueType = this._valueTypes[i] + if (entry[valueType.id] != null) { + bitmap |= 0x01 << i + valueType.writeEntry(entry, buffer, offset) + offset += valueType.length + } + } catch (error) { this.warn(error) } } buffer.writeUInt8(bitmap, 0) return buffer.slice(0, offset)