fakegato-history
Advanced tools
Comparing version 0.3.2 to 0.3.3
'use strict'; | ||
const Format = require('util').format; | ||
const EPOCH_OFFSET = 978307200; | ||
const TYPE_ENERGY = 'energy', | ||
TYPE_ROOM = 'room', | ||
TYPE_WEATHER = 'weather'; | ||
var homebridge; | ||
var Characteristic; | ||
var Characteristic, Service; | ||
module.exports = function(pHomebridge) { | ||
if (pHomebridge && !homebridge) { | ||
homebridge = pHomebridge; | ||
Characteristic = homebridge.hap.Characteristic; | ||
if (pHomebridge && !homebridge) { | ||
homebridge = pHomebridge; | ||
Characteristic = homebridge.hap.Characteristic; | ||
Service = homebridge.hap.Service; | ||
} | ||
@@ -25,3 +34,3 @@ | ||
| ((val >>> 24) & 0xFF); | ||
}, hexToHPA = function(val) { | ||
}, hexToHPA = function(val) { | ||
return parseInt(swap16(val), 10); | ||
@@ -31,3 +40,3 @@ }, hPAtoHex = function(val) { | ||
}, numToHex = function(val, len) { | ||
var s = Number(val>>>0).toString(16); | ||
var s = Number(val >>> 0).toString(16); | ||
if(s.length % 2 != 0) { | ||
@@ -40,3 +49,2 @@ s = '0' + s; | ||
return s; | ||
} | ||
@@ -46,3 +54,3 @@ | ||
constructor() { | ||
super('S2R1', 'E863F116-079E-48FF-8F27-9C2605A29F52'); | ||
super('S2R1', S2R1Characteristic.UUID); | ||
this.setProps({ | ||
@@ -57,5 +65,7 @@ format: Characteristic.Formats.DATA, | ||
S2R1Characteristic.UUID = 'E863F116-079E-48FF-8F27-9C2605A29F52'; | ||
class S2R2Characteristic extends Characteristic { | ||
constructor() { | ||
super('S2R2', 'E863F117-079E-48FF-8F27-9C2605A29F52'); | ||
super('S2R2', S2R2Characteristic.UUID); | ||
this.setProps({ | ||
@@ -70,5 +80,7 @@ format: Characteristic.Formats.DATA, | ||
S2R2Characteristic.UUID = 'E863F117-079E-48FF-8F27-9C2605A29F52'; | ||
class S2W1Characteristic extends Characteristic { | ||
constructor() { | ||
super('S2W1', 'E863F11C-079E-48FF-8F27-9C2605A29F52'); | ||
super('S2W1', S2W1Characteristic.UUID); | ||
this.setProps({ | ||
@@ -83,5 +95,7 @@ format: Characteristic.Formats.DATA, | ||
S2W1Characteristic.UUID = 'E863F11C-079E-48FF-8F27-9C2605A29F52'; | ||
class S2W2Characteristic extends Characteristic { | ||
constructor() { | ||
super('S2W2', 'E863F121-079E-48FF-8F27-9C2605A29F52'); | ||
super('S2W2', S2W2Characteristic.UUID); | ||
this.setProps({ | ||
@@ -96,7 +110,9 @@ format: Characteristic.Formats.DATA, | ||
class FakeGatoHistoryService extends homebridge.hap.Service { | ||
S2W2Characteristic.UUID = 'E863F121-079E-48FF-8F27-9C2605A29F52'; | ||
class FakeGatoHistoryService extends Service { | ||
constructor(accessoryType, accessory, size) { | ||
if (typeof size === 'undefined') { size = 4032; } | ||
super(accessory.name + " History", 'E863F007-079E-48FF-8F27-9C2605A29F52'); | ||
super(accessory.displayName + " History", FakeGatoHistoryService.UUID); | ||
@@ -109,13 +125,12 @@ var entry2address = function(val) { | ||
this.log = accessory.log; | ||
switch (accessoryType) | ||
{ | ||
case "weather": | ||
switch (accessoryType) { | ||
case TYPE_WEATHER: | ||
this.accessoryType116 = "03"; | ||
this.accessoryType117 = "07"; | ||
break; | ||
case "energy": | ||
case TYPE_ENERGY: | ||
this.accessoryType116 = "07"; | ||
this.accessoryType117 = "1f"; | ||
break; | ||
case "room": | ||
case TYPE_ROOM: | ||
this.accessoryType116 = "04"; | ||
@@ -125,6 +140,4 @@ this.accessoryType117 = "0f"; | ||
} | ||
this.accessoryType=accessoryType; | ||
this.accessoryType = accessoryType; | ||
this.firstEntry = 0; | ||
@@ -134,80 +147,80 @@ this.lastEntry = 0; | ||
this.memorySize = size; | ||
this.usedMemory=0; | ||
this.usedMemory = 0; | ||
this.currentEntry = 1; | ||
this.transfer=false; | ||
this.setTime=true; | ||
this.refTime=0; | ||
this.memoryAddress=0; | ||
this.dataStream=''; | ||
this.transfer = false; | ||
this.setTime = true; | ||
this.refTime = 0; | ||
this.memoryAddress = 0; | ||
this.dataStream = ''; | ||
this.addCharacteristic(S2R1Characteristic); | ||
this.addCharacteristic(S2R2Characteristic) | ||
.on('get', (callback) => { | ||
if ((this.currentEntry<this.lastEntry) && (this.transfer==true)) | ||
{ | ||
this.memoryAddress = entry2address (this.currentEntry); | ||
if ((this.currentEntry < this.lastEntry) && (this.transfer == true)) { | ||
this.memoryAddress = entry2address(this.currentEntry); | ||
if ((this.history[this.memoryAddress].temp==0 && | ||
this.history[this.memoryAddress].pressure==0 && | ||
this.history[this.memoryAddress].humidity==0) || (this.history[this.memoryAddress].power==0xFFFF) || (this.setTime==true)) | ||
{ | ||
this.log.debug("Data "+ this.accessoryType + ": 15" + numToHex(swap16(this.currentEntry),4) + "0000 0000 0000 81" + numToHex(swap32(this.refTime),8) +"0000 0000 00 0000"); | ||
callback(null,hexToBase64('15' + numToHex(swap16(this.currentEntry),4) +' 0000 0000 0000 81' + numToHex(swap32(this.refTime),8) + '0000 0000 00 0000')); | ||
if ((this.history[this.memoryAddress].temp == 0 && | ||
this.history[this.memoryAddress].pressure == 0 && | ||
this.history[this.memoryAddress].humidity == 0) || (this.history[this.memoryAddress].power == 0xFFFF) || (this.setTime == true)) { | ||
var val = Format( | ||
'15%s0000 0000 0000 81%s0000 0000 00 0000', | ||
numToHex(swap16(this.currentEntry),4), | ||
numToHex(swap32(this.refTime),8) | ||
); | ||
this.log.debug("Data %s: %s", this.accessoryType, val); | ||
callback(null, hexToBase64(val)); | ||
this.setTime=false; | ||
this.currentEntry++; | ||
} | ||
else | ||
{ | ||
for (var i=0;i<11;i++) | ||
{ | ||
switch (this.accessoryType) | ||
{ | ||
case "weather": | ||
this.log.debug(this.accessoryType + " Entry: " + this.currentEntry + ", Address: " + this.memoryAddress); | ||
this.dataStream = this.dataStream + " 10 " + numToHex(swap16(this.currentEntry),4) + " 0000 " | ||
+ numToHex(swap32(this.history[this.memoryAddress].time-this.refTime-978307200),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].pressure*10),4); | ||
else { | ||
for (var i = 0;i < 11;i++) { | ||
switch (this.accessoryType) { | ||
case TYPE_WEATHER: | ||
this.log.debug("%s Entry: %s, Address: %s", this.accessoryType, this.currentEntry, this.memoryAddress); | ||
this.dataStream += Format( | ||
" 10 %s 0000 %s%s%s%s%s", | ||
numToHex(swap16(this.currentEntry), 4), | ||
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].pressure*10), 4) | ||
); | ||
break; | ||
case "energy": | ||
this.log.debug(this.accessoryType + " Entry: " + this.currentEntry + ", Address: " + this.memoryAddress); | ||
this.dataStream = this.dataStream + " 14 " + numToHex(swap16(this.currentEntry),4) + " 0000 " | ||
+ numToHex(swap32(this.history[this.memoryAddress].time-this.refTime-978307200),8) | ||
+ this.accessoryType117 | ||
+ "0000 0000" | ||
+ numToHex(swap16(this.history[this.memoryAddress].power*10),4) | ||
+ "0000 0000"; | ||
case TYPE_ENERGY: | ||
this.log.debug("%s Entry: %s, Address: %s", this.accessoryType, this.currentEntry, this.memoryAddress); | ||
this.dataStream += Format( | ||
" 14 %s 0000 %s%s0000 0000%s0000 0000", | ||
numToHex(swap16(this.currentEntry),4), | ||
numToHex(swap32(this.history[this.memoryAddress].time - this.refTime - EPOCH_OFFSET), 8), | ||
this.accessoryType117, | ||
numToHex(swap16(this.history[this.memoryAddress].power * 10), 4) | ||
); | ||
break; | ||
} | ||
this.currentEntry++; | ||
this.memoryAddress = entry2address (this.currentEntry); | ||
if (this.currentEntry==this.lastEntry) | ||
{ | ||
this.memoryAddress = entry2address(this.currentEntry); | ||
if (this.currentEntry > this.lastEntry) { | ||
break; | ||
} | ||
} | ||
this.log.debug("Data " + this.accessoryType + ": " + this.dataStream); | ||
callback(null,hexToBase64(this.dataStream)); | ||
this.dataStream=''; | ||
} | ||
this.log.debug("Data %s: %s", this.accessoryType, this.dataStream); | ||
callback(null, hexToBase64(this.dataStream)); | ||
this.dataStream = ''; | ||
} | ||
} | ||
else | ||
{ | ||
this.transfer=false; | ||
callback(null,hexToBase64('00')); | ||
else { | ||
this.transfer = false; | ||
callback(null, hexToBase64('00')); | ||
} | ||
}); | ||
}); | ||
this.addCharacteristic(S2W1Characteristic) | ||
.on('set', this.setCurrentS2W1.bind(this)); | ||
this.addCharacteristic(S2W2Characteristic) | ||
.on('set', this.setCurrentS2W2.bind(this)); | ||
} | ||
@@ -217,9 +230,11 @@ | ||
var hexAddress= address.toString('16'); | ||
if (address!=0) | ||
if (address != 0) { | ||
this.currentEntry = address; | ||
else | ||
} | ||
else { | ||
this.currentEntry = 1; | ||
} | ||
this.transfer=true; | ||
} | ||
//in order to be consistent with Eve, entry address start from 1 | ||
@@ -232,67 +247,73 @@ addEntry(entry){ | ||
if (this.usedMemory<this.memorySize) | ||
{ | ||
if (this.usedMemory < this.memorySize) { | ||
this.usedMemory++; | ||
this.firstEntry=0; | ||
this.lastEntry=this.usedMemory; | ||
this.firstEntry = 0; | ||
this.lastEntry = this.usedMemory; | ||
} | ||
else | ||
{ | ||
else { | ||
this.firstEntry++; | ||
this.lastEntry = this.firstEntry+this.usedMemory; | ||
this.lastEntry = this.firstEntry + this.usedMemory; | ||
} | ||
if (this.refTime==0) | ||
{ | ||
this.refTime=entry.time-978307200; | ||
switch (this.accessoryType) | ||
{ | ||
case "weather": | ||
this.history[this.lastEntry]= {time: entry.time, temp:0, pressure:0, humidity:0}; | ||
break; | ||
case "energy": | ||
this.history[this.lastEntry]= {time: entry.time, power:0xFFFF}; | ||
break; | ||
} | ||
this.lastEntry++; | ||
this.usedMemory++; | ||
} | ||
if (this.refTime == 0) { | ||
this.refTime = entry.time - EPOCH_OFFSET; | ||
switch (this.accessoryType) | ||
{ | ||
case TYPE_WEATHER: | ||
this.history[this.lastEntry]= {time: entry.time, temp: 0, pressure: 0, humidity: 0}; | ||
break; | ||
case TYPE_ENERGY: | ||
this.history[this.lastEntry]= {time: entry.time, power: 0xFFFF}; | ||
break; | ||
} | ||
this.lastEntry++; | ||
this.usedMemory++; | ||
} | ||
this.history[entry2address(this.lastEntry)] = (entry); | ||
this.getCharacteristic(S2R1Characteristic) | ||
.setValue(hexToBase64(numToHex(swap32(entry.time-this.refTime-978307200),8) + '00000000' + numToHex(swap32(this.refTime),8) + '0401020202' + this.accessoryType116 +'020f03' + numToHex(swap16(this.usedMemory),4) + numToHex(swap16(this.memorySize),4) + numToHex(swap32(this.firstEntry),8) + '000000000101')); | ||
this.log.debug("First entry " + this.accessoryType + ": " + this.firstEntry.toString(16)); | ||
this.log.debug("Last entry " + this.accessoryType + ": " + this.lastEntry.toString(16)); | ||
this.log.debug("Used memory " + this.accessoryType + ": " + this.usedMemory.toString(16)); | ||
this.log.debug("116 " + this.accessoryType + ": " + numToHex(swap32(entry.time-this.refTime-978307200),8) + '00000000' + numToHex(swap32(this.refTime),8) + '0401020202' + this.accessoryType116 +'020f03 ' + numToHex(swap16(this.usedMemory),4) + numToHex(swap16(this.memorySize),4) + numToHex(swap32(this.firstEntry),8) + '000000000101'); | ||
var val = Format( | ||
'%s00000000%s0401020202%s020f03%s%s%s000000000101', | ||
numToHex(swap32(entry.time - this.refTime - EPOCH_OFFSET), 8), | ||
numToHex(swap32(this.refTime), 8), this.accessoryType116, | ||
numToHex(swap16(this.usedMemory), 4), | ||
numToHex(swap16(this.memorySize), 4), | ||
numToHex(swap32(this.firstEntry), 8) | ||
); | ||
this.getCharacteristic(S2R1Characteristic).setValue(hexToBase64(val)); | ||
this.log.debug("First entry %s: %s", this.accessoryType, this.firstEntry.toString(16)); | ||
this.log.debug("Last entry %s: %s", this.accessoryType, this.lastEntry.toString(16)); | ||
this.log.debug("Used memory %s: %s", this.accessoryType, this.usedMemory.toString(16)); | ||
this.log.debug("116 %s: %s", this.accessoryType, val); | ||
} | ||
setCurrentS2W1(val, callback) { | ||
callback(null,val); | ||
this.log.debug("Data request " + this.accessoryType + ": "+ base64ToHex(val)); | ||
this.log.debug("Data request %s: %s", this.accessoryType, base64ToHex(val)); | ||
var valHex = base64ToHex(val); | ||
var substring = valHex.substring(4,12); | ||
var valInt = parseInt(substring,16); | ||
var substring = valHex.substring(4, 12); | ||
var valInt = parseInt(substring, 16); | ||
var address = swap32(valInt); | ||
var hexAddress= address.toString('16'); | ||
this.log.debug("Address requested " + this.accessoryType + ": "+ hexAddress); | ||
this.log.debug("Address requested %s: %s", this.accessoryType, hexAddress); | ||
//if (this.transfer==false) | ||
{ | ||
//{ | ||
//this.transfer=true; | ||
this.sendHistory(address); | ||
} | ||
//} | ||
} | ||
setCurrentS2W2(val, callback) { | ||
this.log.debug("Clock adjust: "+ base64ToHex(val)); | ||
callback(null,val); | ||
this.log.debug("Clock adjust: %s", base64ToHex(val)); | ||
callback(null, val); | ||
} | ||
} | ||
FakeGatoHistoryService.UUID = 'E863F007-079E-48FF-8F27-9C2605A29F52'; | ||
return FakeGatoHistoryService; | ||
} | ||
} |
{ | ||
"name": "fakegato-history", | ||
"version": "0.3.2", | ||
"version": "0.3.3", | ||
"description": "Module emulating Elgato Eve history for homebridge plugins", | ||
@@ -20,3 +20,1 @@ "main": "fakegato-history.js", | ||
} | ||
@@ -17,3 +17,3 @@ # fakegato-history | ||
- accessoryType can be "weather" or "energy" | ||
- 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.name` variable and 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. | ||
- 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 | ||
@@ -45,3 +45,3 @@ | ||
### Known bugs | ||
- There is a delay of one entry between the history and the upload to Eve.app, i.e. entry n will be uploaded only when entry n+1 is added to the history | ||
- ~~There is a delay of one entry between the history and the upload to Eve.app, i.e. entry n will be uploaded only when entry n+1 is added to the history~~ | ||
@@ -48,0 +48,0 @@ ### How to contribute |
18641
265