homebridge-orbit-irrigation
Version:
Orbit Irrigation System platform plugin for [Homebridge](https://github.com/nfarina/homebridge).
584 lines (583 loc) • 60 kB
JavaScript
/* eslint-disable @typescript-eslint/no-explicit-any */
'use strict';
import OrbitAPI from './orbitapi.js';
export default class Orbit {
platform;
orbitapi;
log;
Service;
Characteristic;
constructor(platform, orbitapi = new OrbitAPI(platform), log = platform.log) {
this.platform = platform;
this.orbitapi = orbitapi;
this.log = log;
this.Service = platform.Service;
this.Characteristic = platform.Characteristic;
}
async updateService(message) {
//process incoming messages
try {
const jsonBody = JSON.parse(message);
if (jsonBody.source == 'local') {
this.log.debug('simulated message');
}
const deviceName = this.platform.deviceGraph.devices.filter((result) => result.id == jsonBody.device_id)[0].name;
const deviceModel = this.platform.deviceGraph.devices.filter((result) => result.id == jsonBody.device_id)[0].hardware_version;
const eventType = this.platform.deviceGraph.devices.filter((result) => result.id == jsonBody.device_id)[0].type;
let activeService;
const uuid = this.platform.genUUID(jsonBody.device_id);
const index = this.platform.accessories.findIndex(accessory => accessory.UUID === uuid);
/*****************************
Possible states
Active InUse HomeKit Shows
False False Off
True False Waiting
True True Running
False True Stopping
******************************/
if (this.platform.showExtraDebugMessages) {
this.log.debug('extra message', jsonBody);
} //additional debug info before suppressing duplicates
this.platform.lastMessage.timestamp = jsonBody.timestamp; //ignore message with no timestamp deltas, ignoring mode changes
this.platform.secondLastMessage.timestamp = jsonBody.timestamp; //ignore message with no timestamp deltas, ignoring mode changes
if (JSON.stringify(this.platform.lastMessage) == JSON.stringify(jsonBody) || JSON.stringify(this.platform.secondLastMessage) == JSON.stringify(jsonBody)) {
return;
} //suppress duplicate websocket messages and checks sequence
if (this.platform.showExtraDebugMessages) {
this.log.info('extra message', jsonBody);
} //additional debug info after suppressing duplicates
if (jsonBody.event != 'battery_status') {
//ignore event that is not logged
this.platform.secondLastMessage = this.platform.lastMessage;
}
this.platform.lastMessage = jsonBody;
switch (eventType) {
case 'sprinkler_timer': {
let irrigationAccessory;
let irrigationSystemService;
let valveAccessory;
let percent;
if (this.platform.showIrrigation) {
//**Valve**//
if (this.platform.showSimpleValve && deviceModel.includes('HT25')) {
valveAccessory = this.platform.accessories[index];
if (!valveAccessory) {
return;
}
const batteryService = valveAccessory.getService(this.Service.Battery);
const switchServiceStandby = valveAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + 'Standby'));
const switchServiceRunall = valveAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + 'Run All'));
switch (jsonBody.event) {
case 'watering_in_progress_notification':
activeService = valveAccessory.getService(this.Service.Valve);
if (activeService) {
//stop last if program is running
if (jsonBody.program != 'manual') {
if (!this.platform.activeProgram) {
if (this.platform.showSchedules) {
const switchServiceSchedule = valveAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + jsonBody.program));
this.log.info('Running Program %s, %s', jsonBody.program, switchServiceSchedule.getCharacteristic(this.Characteristic.Name).value);
}
else {
this.log.info('Running Program %s', jsonBody.program);
}
}
if (this.platform.activeZone[jsonBody.device_id]) {
activeService = valveAccessory.getServiceById(this.Service.Valve, this.platform.activeZone[jsonBody.device_id]);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
this.platform.activeZone[jsonBody.device_id] = false;
if (jsonBody.source != 'local') {
if (this.platform.activeProgram) {
this.log.info('Device %s, Faucet %s scheduled watering', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value);
}
}
}
this.platform.activeProgram = jsonBody.program;
}
//start active zone
if (jsonBody.source != 'local') {
this.platform.activeZone[jsonBody.device_id] = jsonBody.current_station;
this.log.info('Device %s faucet, %s watering in progress for %s mins', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value, Math.round(jsonBody.run_time));
}
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.ACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.IN_USE);
activeService.getCharacteristic(this.Characteristic.SetDuration).updateValue(jsonBody.total_run_time_sec);
activeService.getCharacteristic(this.Characteristic.RemainingDuration).updateValue(parseInt(jsonBody.run_time) * 60);
this.platform.endTime[activeService.subtype] = new Date(Date.now() + parseInt(jsonBody.run_time) * 60 * 1000).toISOString();
}
break;
case 'watering_complete':
activeService = valveAccessory.getService(this.Service.Valve);
if (activeService) {
if (jsonBody.source != 'local') {
this.log.info('Device %s faucet, %s watering completed', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value);
this.platform.activeZone[jsonBody.device_id] = false;
}
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
break;
case 'device_idle':
activeService = valveAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + this.platform.activeProgram));
if (this.platform.showRunall && switchServiceRunall) {
switchServiceRunall.getCharacteristic(this.Characteristic.On).updateValue(false);
this.log.info('Device is idle');
}
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Program %s completed', activeService.getCharacteristic(this.Characteristic.Name).value);
activeService.getCharacteristic(this.Characteristic.On).updateValue(false);
this.platform.activeProgram = false;
}
else {
if (this.platform.activeProgram) {
this.log.info('Program %s completed', this.platform.activeProgram);
this.platform.activeProgram = false;
}
}
activeService = valveAccessory.getService(this.Service.Valve);
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Device %s idle', deviceName);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
break;
case 'change_mode':
this.log.debug('%s mode changed to %s', deviceName, jsonBody.mode);
switch (jsonBody.mode) {
case 'auto':
if (this.platform.showStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(false);
}
break;
case 'manual':
if (this.platform.showStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(false);
}
break;
case 'off':
if (this.platform.howStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(true);
}
break;
}
break;
case 'device_connected':
this.log.info('%s connected at %s', deviceName, new Date(jsonBody.timestamp).toString());
valveAccessory.services.forEach((service) => {
if (this.Service.AccessoryInformation.UUID != service.UUID) {
if (this.Service.Battery.UUID != service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.NO_FAULT);
}
}
});
break;
case 'device_disconnected':
this.log.warn('%s disconnected at %s! This will show as non-responding in Homekit until the connection is restored.', deviceName, jsonBody.timestamp);
valveAccessory.services.forEach((service) => {
if (this.Service.AccessoryInformation.UUID != service.UUID) {
if (this.Service.Battery.UUID != service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.GENERAL_FAULT);
}
}
});
break;
case 'battery_status':
percent = 0;
if (jsonBody.percent) {
percent = jsonBody.percent;
}
else if (jsonBody.mv) {
percent = ((jsonBody.mv - 2000) / (3400 - 2000)) * 100 > 100 ? 100 : ((jsonBody.mv - 2000) / (3400 - 2000)) * 100;
}
if (jsonBody.charging == undefined) {
jsonBody.charging = false;
}
this.log.debug('update battery status %s to %s%, charging=%s', deviceName, percent, jsonBody.charging);
batteryService.getCharacteristic(this.Characteristic.ChargingState).updateValue(jsonBody.charging);
batteryService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(percent);
break;
case 'low_battery':
this.log.warn('%s battery low', deviceName);
activeService = valveAccessory.getServiceById(this.Service.Battery, jsonBody.device_id);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.StatusLowBattery).updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW);
//activeService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(jsonBody.percent_remaining)
}
break;
case 'clear_low_battery':
this.log.debug('%s battery good', deviceName);
activeService = valveAccessory.getServiceById(this.Service.Battery, jsonBody.device_id);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.StatusLowBattery).updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL);
//activeService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(jsonBody.percent_remaining)
}
break;
case 'device_status':
if (this.platform.showExtraDebugMessages) {
this.log.debug('%s updated at %s', deviceName, new Date(jsonBody.timestamp).toString());
}
break;
case 'program_changed':
this.log.debug('%s program %s %s changed', deviceName, jsonBody.program.program, jsonBody.program.name);
break;
case 'rain_delay':
this.log.debug('%s rain delay %s hours for %s', deviceName, jsonBody.delay, jsonBody.rain_delay_weather_type);
if (jsonBody.delay > 0) {
//device is idle
activeService = valveAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + this.platform.activeProgram));
if (this.platform.showRunall && switchServiceRunall) {
switchServiceRunall.getCharacteristic(this.Characteristic.On).updateValue(false);
this.log.info('Device is idle');
}
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Program %s completed', activeService.getCharacteristic(this.Characteristic.Name).value);
activeService.getCharacteristic(this.Characteristic.On).updateValue(false);
this.platform.activeProgram = false;
}
else {
if (this.platform.activeProgram) {
this.log.info('Program %s completed', this.platform.activeProgram);
this.platform.activeProgram = false;
}
}
activeService = valveAccessory.getService(this.Service.Valve);
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Device %s idle', deviceName);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
}
break;
case 'firmware_update_progress':
//do nothing
this.log.info('Firmware update in progress for %s to version %s - %s% ', deviceName, jsonBody.version, (jsonBody.offset / jsonBody.size));
break;
case 'fault':
this.log.debug('Message received: %s for device id %s stations %s', jsonBody.event, jsonBody.device_id, jsonBody.stations);
break;
default:
this.log.warn('%s Unknown faucet device message received: %s', deviceName, jsonBody.event);
break;
}
}
else {
//irrigation system
irrigationAccessory = this.platform.accessories[index];
irrigationSystemService = irrigationAccessory.getService(this.Service.IrrigationSystem);
if (!irrigationAccessory) {
return;
}
const batteryService = irrigationAccessory.getService(this.Service.Battery);
const switchServiceStandby = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + 'Standby'));
const switchServiceRunall = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + 'Run All'));
switch (jsonBody.event) {
case 'watering_in_progress_notification':
irrigationSystemService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.IN_USE);
activeService = irrigationAccessory.getServiceById(this.Service.Valve, jsonBody.current_station);
if (activeService) {
//stop last if program is running
if (jsonBody.program != 'manual') {
if (!this.platform.activeProgram) {
if (this.platform.showSchedules) {
const switchServiceSchedule = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + jsonBody.program));
this.log.info('Program %s, %s started', jsonBody.program, switchServiceSchedule.getCharacteristic(this.Characteristic.Name).value);
}
else {
this.log.info('Program %s started', jsonBody.program);
}
}
if (this.platform.activeZone[jsonBody.device_id]) {
activeService = irrigationAccessory.getServiceById(this.Service.Valve, this.platform.activeZone[jsonBody.device_id]);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
this.platform.activeZone[jsonBody.device_id] = false;
if (jsonBody.source != 'local') {
if (this.platform.activeProgram) {
this.log.info('Device %s, Zone %s watering completed, starting next Zone', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value);
}
}
}
this.platform.activeProgram = jsonBody.program;
}
//start active zone
if (jsonBody.source != 'local') {
this.platform.activeZone[jsonBody.device_id] = jsonBody.current_station;
if (this.platform.activeProgram) {
this.log.info('Device %s, Zone %s watering in progress for %s mins', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value, Math.round(jsonBody.run_time));
}
}
if (!jsonBody.total_run_time_sec) {
//added for older firmware that may not have this field populated
jsonBody.total_run_time_sec = jsonBody.run_time * 60;
}
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.ACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.IN_USE);
activeService.getCharacteristic(this.Characteristic.SetDuration).updateValue(jsonBody.total_run_time_sec);
activeService.getCharacteristic(this.Characteristic.RemainingDuration).updateValue(parseInt(jsonBody.run_time) * 60);
this.platform.endTime[activeService.subtype] = new Date(Date.now() + parseInt(jsonBody.run_time) * 60 * 1000).toISOString();
}
//update other zones in quque with status
if (jsonBody.water_event_queue) {
if (jsonBody.water_event_queue.length > 0) {
let match;
const deviceResponse = await this.orbitapi.getDevice(this.platform.token, jsonBody.device_id).catch(err => {
this.log.error('Failed to get device response %s', err);
});
for (let n = 0; n < deviceResponse.zones.length; n++) {
match = false;
deviceResponse.zones[n].enabled = true; // need orbit version of enabled
if (deviceResponse.zones[n]) {
for (let i = 0; i < jsonBody.water_event_queue.length; i++) {
if (deviceResponse.zones[n].station == jsonBody.current_station && jsonBody.current_station == jsonBody.water_event_queue[i].station) {
this.log.debug('%s program %s for zone-%s %s running', deviceName, jsonBody.program, deviceResponse.zones[n].station, deviceResponse.zones[n].name);
//zone already running
/*
activeService=irrigationAccessory.getServiceById(this.Service.Valve, deviceResponse.zones[n].station)
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.ACTIVE)
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.IN_USE)
activeService.getCharacteristic(this.Characteristic.SetDuration).updateValue(jsonBody.total_run_time_sec)
activeService.getCharacteristic(this.Characteristic.RemainingDuration).updateValue(parseInt(jsonBody.run_time * 60))
this.endTime[activeService.subtype]= new Date(Date.now() + parseInt(jsonBody.run_time * 60 * 1000)).toISOString()
*/
match = true;
break;
}
else if (deviceResponse.zones[n].station == jsonBody.water_event_queue[i].station) {
this.log.debug('%s program %s for zone-%s %s waiting', deviceName, jsonBody.program, deviceResponse.zones[n].station, deviceResponse.zones[n].name);
activeService = irrigationAccessory.getServiceById(this.Service.Valve, deviceResponse.zones[n].station);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.ACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
match = true;
break;
}
}
if (!match) {
this.log.debug('%s program %s for zone-%s %s stopped', deviceName, jsonBody.program, deviceResponse.zones[n].station, deviceResponse.zones[n].name);
activeService = irrigationAccessory.getServiceById(this.Service.Valve, deviceResponse.zones[n].station);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
continue;
}
}
}
}
//turn program switch off at last zone
if (jsonBody.water_event_queue.length == 1) {
activeService = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + this.platform.activeProgram));
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Program %s finishing last zone', activeService.getCharacteristic(this.Characteristic.Name).value);
setTimeout(() => {
activeService.getCharacteristic(this.Characteristic.On).updateValue(false);
}, jsonBody.water_event_queue[0].run_time_sec * 1000);
//activeService.getCharacteristic(this.Characteristic.On).updateValue(false)
this.platform.activeProgram = false;
}
else {
if (this.platform.activeProgram) {
this.log.info('Program %s finished', this.platform.activeProgram);
this.platform.activeProgram = false;
}
}
}
}
break;
case 'watering_complete':
irrigationSystemService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
activeService = irrigationAccessory.getServiceById(this.Service.Valve, this.platform.activeZone[jsonBody.device_id]);
if (activeService) {
if (jsonBody.source != 'local') {
this.log.info('Device %s, Zone %s watering completed', deviceName, activeService.getCharacteristic(this.Characteristic.Name).value);
this.platform.activeZone[jsonBody.device_id] = false;
}
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
break;
case 'device_idle':
irrigationSystemService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
activeService = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + this.platform.activeProgram));
if (this.platform.showRunall && switchServiceRunall) {
switchServiceRunall.getCharacteristic(this.Characteristic.On).updateValue(false);
this.log.info('Device is idle');
}
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Program %s completed', activeService.getCharacteristic(this.Characteristic.Name).value);
activeService.getCharacteristic(this.Characteristic.On).updateValue(false);
this.platform.activeProgram = false;
}
else {
if (this.platform.activeProgram) {
this.log.info('Program %s completed', this.platform.activeProgram);
this.platform.activeProgram = false;
}
}
activeService = irrigationAccessory.getServiceById(this.Service.Valve, this.platform.activeZone[jsonBody.device_id]);
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Device %s idle', deviceName);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
break;
case 'change_mode':
this.log.debug('%s mode changed to %s', deviceName, jsonBody.mode);
//this.log.info(activeService.getCharacteristic(this.Characteristic.Name))
switch (jsonBody.mode) {
case 'auto':
irrigationSystemService.getCharacteristic(this.Characteristic.ProgramMode).updateValue(this.Characteristic.ProgramMode.PROGRAM_SCHEDULED);
if (this.platform.showStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(false);
}
break;
case 'manual':
irrigationSystemService.getCharacteristic(this.Characteristic.ProgramMode).updateValue(this.Characteristic.ProgramMode.PROGRAM_SCHEDULED_MANUAL_MODE);
if (this.platform.showStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(false);
}
break;
case 'off':
irrigationSystemService.getCharacteristic(this.Characteristic.ProgramMode).updateValue(this.Characteristic.ProgramMode.NO_PROGRAM_SCHEDULED);
if (this.platform.showStandby && switchServiceStandby) {
switchServiceStandby.getCharacteristic(this.Characteristic.On).updateValue(true);
}
break;
}
break;
case 'device_connected':
this.log.info('%s connected at %s', deviceName, new Date(jsonBody.timestamp).toString());
irrigationAccessory.services.forEach((service) => {
if (this.Service.AccessoryInformation.UUID != service.UUID) {
if (this.Service.Battery.UUID != service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.NO_FAULT);
}
}
if (this.Service.Valve.UUID == service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.NO_FAULT);
}
if (this.Service.Switch.UUID == service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.NO_FAULT);
}
});
break;
case 'device_disconnected':
this.log.warn('%s disconnected at %s! This will show as non-responding in Homekit until the connection is restored.', deviceName, jsonBody.timestamp);
irrigationAccessory.services.forEach((service) => {
if (this.Service.AccessoryInformation.UUID != service.UUID) {
if (this.Service.Battery.UUID != service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.GENERAL_FAULT);
}
}
if (this.Service.Valve.UUID == service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.GENERAL_FAULT);
}
if (this.Service.Switch.UUID == service.UUID) {
service.getCharacteristic(this.Characteristic.StatusFault).updateValue(this.Characteristic.StatusFault.GENERAL_FAULT);
}
});
break;
case 'battery_status':
percent = 0;
if (jsonBody.percent) {
percent = jsonBody.percent;
}
else if (jsonBody.mv) {
percent = ((jsonBody.mv - 2000) / (3400 - 2000)) * 100 > 100 ? 100 : ((jsonBody.mv - 2000) / (3400 - 2000)) * 100;
}
if (jsonBody.charging == undefined) {
jsonBody.charging = false;
}
this.log.debug('update battery status %s to %s%, charging=%s', deviceName, percent, jsonBody.charging);
batteryService.getCharacteristic(this.Characteristic.ChargingState).updateValue(jsonBody.charging);
batteryService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(percent);
break;
case 'low_battery':
this.log.warn('%s battery low', deviceName);
activeService = irrigationAccessory.getServiceById(this.Service.Battery, jsonBody.device_id);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.StatusLowBattery).updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW);
//activeService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(jsonBody.percent_remaining)
}
break;
case 'clear_low_battery':
this.log.debug('%s battery good', deviceName);
activeService = irrigationAccessory.getServiceById(this.Service.Battery, jsonBody.device_id);
if (activeService) {
activeService.getCharacteristic(this.Characteristic.StatusLowBattery).updateValue(this.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL);
//activeService.getCharacteristic(this.Characteristic.BatteryLevel).updateValue(jsonBody.percent_remaining)
}
break;
case 'device_status':
if (this.platform.CharacteristicshowExtraDebugMessages) {
this.log.debug('%s updated at %s', deviceName, new Date(jsonBody.timestamp).toString());
}
break;
case 'program_changed':
this.log.debug('%s program %s %s changed', deviceName, jsonBody.program.program, jsonBody.program.name);
break;
case 'rain_delay':
this.log.debug('%s rain delay %s hours for %s', deviceName, jsonBody.delay, jsonBody.rain_delay_weather_type);
if (jsonBody.delay > 0) {
//device is idle
irrigationSystemService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
activeService = irrigationAccessory.getServiceById(this.Service.Switch, this.platform.genUUID(jsonBody.device_id + this.platform.activeProgram));
if (this.platform.showRunall && switchServiceRunall) {
switchServiceRunall.getCharacteristic(this.Characteristic.On).updateValue(false);
this.log.info('Device is idle');
}
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Program %s completed', activeService.getCharacteristic(this.Characteristic.Name).value);
activeService.getCharacteristic(this.Characteristic.On).updateValue(false);
this.platform.activeProgram = false;
}
else {
if (this.platform.activeProgram) {
this.log.info('Program %s completed', this.platform.activeProgram);
this.platform.activeProgram = false;
}
}
activeService = irrigationAccessory.getServiceById(this.Service.Valve, this.platform.activeZone[jsonBody.device_id]);
if (activeService) {
//this.log.info('Device %s, %s zone idle',deviceName, activeService.getCharacteristic(this.Characteristic.Name).value)
this.log.info('Device %s idle', deviceName);
activeService.getCharacteristic(this.Characteristic.Active).updateValue(this.Characteristic.Active.INACTIVE);
activeService.getCharacteristic(this.Characteristic.InUse).updateValue(this.Characteristic.InUse.NOT_IN_USE);
}
}
break;
case 'rain_sensor_status':
//do nothing
this.log.debug('%s rain sensor event', deviceName);
break;
case 'firmware_update_progress':
//do nothing
this.log.info('Firmware update in progress for %s to version %s - %s% ', deviceName, jsonBody.version, (jsonBody.offset / jsonBody.size));
break;
case 'fault':
this.log.debug('Message received: %s for device id %s stations %s', jsonBody.event, jsonBody.device_id, jsonBody.stations);
break;
default:
this.log.warn('%s Unknown sprinkler device message received: %s', deviceName, jsonBody.event);
break;
}
}
}
break;
}
case 'bridge': {
let bridgeAccessory;
if (this.platform.showBridge) {
bridgeAccessory = this.platform.accessories[index];
if (!bridgeAccessory) {
return;