1+ import platformConsts from '../utils/constants.js'
2+ import {
3+ cenToFar ,
4+ generateRandomString ,
5+ hasProperty ,
6+ parseError ,
7+ } from '../utils/functions.js'
8+ import platformLang from '../utils/lang-en.js'
9+
10+ export default class {
11+ constructor ( platform , accessory ) {
12+ // Set up variables from the platform
13+ this . hapChar = platform . api . hap . Characteristic
14+ this . hapErr = platform . api . hap . HapStatusError
15+ this . hapServ = platform . api . hap . Service
16+ this . platform = platform
17+ this . httpTimeout = platform . config . bleRefreshTime * 4.5 * 1000
18+
19+ // Set up variables from the accessory
20+ this . accessory = accessory
21+
22+ // Set up custom variables for this device type
23+ const deviceConf = platform . deviceConf [ accessory . context . gvDeviceId ]
24+ this . lowBattThreshold = deviceConf && deviceConf . lowBattThreshold
25+ ? Math . min ( deviceConf . lowBattThreshold , 100 )
26+ : platformConsts . defaultValues . lowBattThreshold
27+
28+ // Remove temperature sensor service if it exists
29+ if ( this . accessory . getService ( this . hapServ . TemperatureSensor ) ) {
30+ this . accessory . removeService ( this . accessory . getService ( this . hapServ . TemperatureSensor ) )
31+ }
32+
33+ // Add the thermostat service if it doesn't already exist
34+ this . thermoService = this . accessory . getService ( this . hapServ . Thermostat )
35+ || this . accessory . addService ( this . hapServ . Thermostat )
36+
37+ // Set up thermostat characteristics
38+ this . cacheTemp = this . thermoService . getCharacteristic ( this . hapChar . CurrentTemperature ) . value || 20
39+
40+ // Configure thermostat to be read-only (sensor only)
41+ this . thermoService . getCharacteristic ( this . hapChar . TargetTemperature )
42+ . updateValue ( this . cacheTemp )
43+ . onGet ( ( ) => {
44+ return this . cacheTemp ;
45+ } ) ;
46+
47+ // Set heating/cooling state to OFF (0)
48+ this . thermoService . getCharacteristic ( this . hapChar . CurrentHeatingCoolingState )
49+ . updateValue ( 0 ) // 0 = OFF
50+ . setProps ( {
51+ validValues : [ 0 ] // Only allow OFF state
52+ } ) ;
53+
54+ this . thermoService . getCharacteristic ( this . hapChar . TargetHeatingCoolingState )
55+ . updateValue ( 0 ) // 0 = OFF
56+ . setProps ( {
57+ validValues : [ 0 ] // Only allow OFF state
58+ } ) ;
59+
60+ // Set temperature display units to Celsius (0)
61+ this . thermoService . getCharacteristic ( this . hapChar . TemperatureDisplayUnits )
62+ . updateValue ( 0 ) ;
63+
64+ this . updateCache ( )
65+
66+ // Add the battery service if it doesn't already exist
67+ this . battService = this . accessory . getService ( this . hapServ . Battery )
68+ || this . accessory . addService ( this . hapServ . Battery )
69+ this . cacheBatt = this . battService . getCharacteristic ( this . hapChar . BatteryLevel ) . value
70+
71+ // Pass the accessory to Fakegato to set up with Eve
72+ this . accessory . eveService = new platform . eveService ( 'custom' , this . accessory , {
73+ log : ( ) => { } ,
74+ } )
75+
76+ // Output the customised options to the log
77+ const opts = JSON . stringify ( {
78+ lowBattThreshold : this . lowBattThreshold ,
79+ } )
80+ platform . log ( '[%s] %s %s.' , accessory . displayName , platformLang . devInitOpts , opts )
81+ }
82+
83+ async externalUpdate ( params ) {
84+ // Check to see if the provided online status is different from the cache value
85+ if ( hasProperty ( params , 'online' ) && this . cacheOnline !== params . online ) {
86+ this . cacheOnline = params . online
87+ this . platform . updateAccessoryStatus ( this . accessory , this . cacheOnline )
88+ }
89+
90+ if ( params . source === 'BLE' ) {
91+ // If we have a BLE update then we should ignore HTTP updates for the next 4 BLE refresh cycles
92+ // Since BLE will be more accurate and may not have updated with the cloud yet
93+ // Generate a random key
94+ const bleKey = generateRandomString ( 5 )
95+ this . bleKey = bleKey
96+ setTimeout ( ( ) => {
97+ if ( this . bleKey === bleKey ) {
98+ this . bleKey = false
99+ }
100+ } , this . httpTimeout )
101+ }
102+ if ( params . source === 'HTTP' && this . bleKey ) {
103+ return
104+ }
105+
106+ // Check to see if the provided battery is different from the cached state
107+ if ( params . battery !== this . cacheBatt && this . battService ) {
108+ // Battery is different so update Homebridge with new values
109+ this . cacheBatt = params . battery
110+ this . battService . updateCharacteristic ( this . hapChar . BatteryLevel , this . cacheBatt )
111+ this . battService . updateCharacteristic (
112+ this . hapChar . StatusLowBattery ,
113+ this . cacheBatt < this . lowBattThreshold ? 1 : 0 ,
114+ )
115+
116+ // Log the change
117+ this . accessory . log ( `${ platformLang . curBatt } [${ this . cacheBatt } %]` )
118+ }
119+
120+ // Check to see if the provided temperature is different from the cached state
121+ if ( hasProperty ( params , 'temperature' ) ) {
122+ let newTemp = Number . parseInt ( params . temperature + this . accessory . context . offTemp , 10 )
123+ newTemp /= 100
124+ if ( newTemp !== this . cacheTemp ) {
125+ // Temperature is different so update Homebridge with new values
126+ this . cacheTemp = newTemp
127+ this . thermoService . updateCharacteristic ( this . hapChar . CurrentTemperature , this . cacheTemp )
128+ this . thermoService . updateCharacteristic ( this . hapChar . TargetTemperature , this . cacheTemp )
129+ this . accessory . eveService . addEntry ( { temp : this . cacheTemp } )
130+
131+ // Log the change
132+ this . accessory . log ( `${ platformLang . curTemp } [${ this . cacheTemp } °C / ${ cenToFar ( this . cacheTemp ) } °F]` )
133+
134+ // Update the cache file with the new temperature
135+ this . updateCache ( )
136+ }
137+ }
138+ }
139+
140+ async updateCache ( ) {
141+ // Don't continue if the storage client hasn't initialised properly
142+ if ( ! this . platform . storageClientData ) {
143+ return
144+ }
145+
146+ // Attempt to save the new temperature to the cache
147+ try {
148+ await this . platform . storageData . setItem (
149+ `${ this . accessory . context . gvDeviceId } _temp` ,
150+ this . cacheTemp ,
151+ )
152+ } catch ( err ) {
153+ this . accessory . logWarn ( `${ platformLang . storageWriteErr } ${ parseError ( err ) } ` )
154+ }
155+ }
156+ }
0 commit comments