UNPKG

homebridge-rachio-irrigation

Version:

Rachio Irrigation System platform plugin for [Homebridge](https://github.com/nfarina/homebridge).

1,209 lines (1,205 loc) 57 kB
//// Public API info https://rachio.readme.io/v1.0/docs //// Public API info https://rachio.readme.io/v2.0/docs /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable no-useless-catch */ import axios from 'axios'; import { PLUGIN_NAME, PLUGIN_VERSION } from './settings.js'; const api_endpoint = 'https://api.rach.io/1/public'; const alt_api_endpoint = 'https://cloud-rest.rach.io'; export default class RachioAPI { platform; log; constructor(platform, log = platform.log) { this.platform = platform; this.log = log; } async getPersonInfo(token) { try { this.log.debug('Retrieving Person Info'); const response = await axios({ method: 'get', baseURL: api_endpoint, url: '/person/info/', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting person, Status ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get person info response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { //this.log.error(`Error retrieving personId \n${err}`) throw err; } } async getPersonId(token, personId) { try { this.log.debug('Retrieving Person ID'); const response = await axios({ method: 'get', baseURL: api_endpoint, url: `/person/${personId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting device ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get person id response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { //this.log.error(`Error retrieving deviceId \n${err}`) throw err; } } async getListProperties(token, userId) { try { this.log.debug('Getting Property list'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/property/listProperties/${userId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting property list ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get property list response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { this.log.error(`Error getting property list \n${err}`); } } async getPropertyEntity(token, resource, id) { try { this.log.debug('Getting Property info'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: 'property/findPropertyByEntity', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, params: { [`resource_id.${resource}`]: `${id}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting property info ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get property info response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { this.log.error(`Error getting property info \n${err}`); } } async getDevice(token, device) { try { this.log.debug(`Getting current device ${device}`); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/device/getDevice/${device}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting device ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get device response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { //this.log.error(`Error getting device \n${err}`) throw err; } } async getDeviceState(token, device) { try { this.log.debug('Getting current device state', device); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/device/getDeviceState/${device}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting device state ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get device state response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { //this.log.error(`Error getting device state \n${err}`) throw err; } } async getDeviceDetails(token, device) { try { this.log.debug('Getting current device state', device); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/device/getDeviceDetails/${device}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting device details ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get device details response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { //this.log.error(`Error getting device details \n${err}`) throw err; } } async getDeviceInfo(token, device) { try { this.log.debug('Getting current device state', device); const response = await axios({ method: 'get', baseURL: api_endpoint, url: `/device/${device}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting device info ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get device info response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { //this.log.error(`Error getting device info \n${err}`) throw err; } } async getLocationList(token) { try { this.log.debug('Getting Location List'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: '/location/listLocations/true', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting location list ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get list locations response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { //this.log.error(`Error getting location list \n${err}`) throw err; } } async currentSchedule(token, device) { try { this.log.debug('Getting current schedule', device); const response = await axios({ method: 'get', baseURL: api_endpoint, url: `/device/${device}/current_schedule`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting schedule ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); this.log.debug('status', response.data.status || 'No active schedule'); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get current schedule response', JSON.stringify(response.data, null, 2)); } return response; } } catch (err) { this.log.error(`Error getting current schedule \n${err}`); } } async deviceStandby(token, device, state) { try { this.log.debug('Setting Standby Mode on', device.id); const response = await axios({ method: 'put', baseURL: api_endpoint, url: `/device/${state}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { id: device.id, }, responseType: 'json', }).catch(err => { this.log.error(`Error setting standby to ${state} ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('device standby response status', response?.status); return response; } catch (err) { this.log.error(`Error setting standby \n${err}`); } } async startZone(token, zone, runtime) { try { this.log.debug('Starting Zone', zone); const response = await axios({ method: 'put', baseURL: api_endpoint, url: '/zone/start', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { id: zone, duration: runtime, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending start zone ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('start response', response?.status); return response; } catch (err) { this.log.error(`Error Starting Zone \n${err}`); } } async startSchedule(token, schedule) { try { this.log.debug('Starting Schedule', schedule); const response = await axios({ method: 'put', baseURL: api_endpoint, url: '/schedulerule/start', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { id: schedule, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending start schedule ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('start schedule response', response?.status); return response; } catch (err) { this.log.error(`Error Starting Schedule \n${err}`); } } async stopDevice(token, deviceId) { try { this.log.debug('Stopping', deviceId); const response = await axios({ method: 'put', baseURL: api_endpoint, url: '/device/stop_water', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { id: deviceId, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending stop ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('stop response', response?.status); return response; } catch (err) { this.log.error(`Error Stopping Device \n${err}`); } } async startMultipleZone(token, zones, duration) { try { const body = []; //this.log.debug('Starting Multiple Zones', zones) zones.forEach((zone, index) => { if (zone.enabled) { body.push({ name: zone.name, id: zone.id, duration: duration, sortOrder: index, }); } }); this.log.debug('multiple run data', JSON.stringify(body, null, 2)); const response = await axios({ method: 'put', baseURL: api_endpoint, url: '/zone/start_multiple', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { zones: body, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending start ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('start multiple response', response?.status); return response; } catch (err) { this.log.error(`Error Starting Multiple Zones \n${err}`); } } async listBaseStations(token, userid) { try { this.log.debug('Getting Base Stations List'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/valve/listBaseStations/${userid}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting base stations list ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get base stations list response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { this.log.error(`Error getting base stations list \n${err}`); } } async getBaseStation(token, baseStationId) { try { this.log.debug('Getting Base Station'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/valve/getBaseStation/${baseStationId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting base station ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get base station response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { this.log.error(`Error getting base station \n${err}`); } } async getValveDayViews(token, baseStationId) { try { this.log.debug('Getting Base Station'); const response = await axios({ method: 'post', baseURL: alt_api_endpoint, url: '/summary/getValveDayViews', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', data: { 'start': { 'year': new Date().getFullYear(), 'month': new Date().getMonth() + 1, 'day': new Date().getDate(), }, 'end': { 'year': new Date().getFullYear(), 'month': new Date().getMonth() + 1, 'day': new Date().getDate(), }, 'resourceId': { 'baseStationId': baseStationId, }, }, }).catch(err => { this.log.error(`Error getting base station daily views ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.debug(JSON.stringify(err.response.data, null, 2)); } else if (err.code) { this.log.debug(err.code); } else { this.log.warn(`Error ${err.name}`); } throw err?.code ?? err; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug(`get base station daily view response ${JSON.stringify(response.data, null, 2)}`); } return response.data; } } catch (err) { throw err; //this.log.error(`Error getting base station daily view \n${err}`) } } async createSkip(token, runId) { try { this.log.debug('Creating Skip Event'); const response = await axios({ method: 'post', baseURL: alt_api_endpoint, url: '/program/createPlannedRunSkipOverrides', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', data: { 'date': { 'year': new Date().getFullYear(), 'month': new Date().getMonth() + 1, 'day': new Date().getDate(), }, 'plannedRunId': runId, }, }).catch(err => { this.log.error(`Error creating skip event ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('Create skip response', JSON.stringify(response.data, null, 2)); } return response; } } catch (err) { this.log.error(`Error creating skip event \n${err}`); } } async deleteSkip(token, runId) { try { this.log.debug('Deleting Skip Event'); const response = await axios({ method: 'post', baseURL: alt_api_endpoint, url: '/program/deletePlannedRunSkipOverrides', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', data: { 'date': { 'year': new Date().getFullYear(), 'month': new Date().getMonth() + 1, 'day': new Date().getDate(), }, 'plannedRunId': runId, }, }).catch(err => { this.log.error(`Error deleting skip event ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('Delete skip response', JSON.stringify(response.data, null, 2)); } return response; } } catch (err) { this.log.error(`Error deleting skip event \n${err}`); } } async listValves(token, baseStationId) { try { this.log.debug('Getting valves List'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/valve/listValves/${baseStationId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting valves list ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } return err.response; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get valves list response', JSON.stringify(response.data, null, 2)); } return response.data; } } catch (err) { this.log.error(`Error getting valves list \n${err}`); } } async getValve(token, valveId) { try { this.log.debug('Getting Valve'); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `/valve/getValve/${valveId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting valve ${err.message}`); this.log.debug(JSON.stringify(err, null, 2)); if (err.response) { this.log.debug(JSON.stringify(err.response.data, null, 2)); } else if (err.code) { this.log.debug(err.code); } else { this.log.warn(`Error ${err.name}`); } throw err?.code ?? err; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('get valve response', JSON.stringify(response.data, null, 2)); } this.log.debug(`${response.headers['x-ratelimit-remaining']} API calls remaining`); return response; } } catch (err) { throw err; //this.log.error(`Error getting valve \n${err}`) } } async startWatering(token, valveId, runtime) { try { this.log.debug('Start Watering', valveId); const response = await axios({ method: 'put', baseURL: alt_api_endpoint, url: '/valve/startWatering', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { valveId: valveId, durationSeconds: runtime, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending start watering ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('start watering response', response?.status); return response; } catch (err) { this.log.error(`Error starting watering \n${err}`); } } async stopWatering(token, valveId) { try { this.log.debug('Stop Watering', valveId); const response = await axios({ method: 'put', baseURL: alt_api_endpoint, url: '/valve/stopWatering', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { valveId: valveId, }, responseType: 'json', }).catch(err => { this.log.error(`Error sending stop watering ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('stop watering response', response?.status); return response; } catch (err) { this.log.error(`Error stopping watering \n${err}`); } } async setDefaultRuntime(token, valveId, defaultRuntime) { try { this.log.debug('Set Default Runtime', valveId); const response = await axios({ method: 'put', baseURL: alt_api_endpoint, url: '/valve/setDefaultRuntime', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, data: { id: valveId, defaultRuntimeSeconds: defaultRuntime, }, responseType: 'json', }).catch(err => { this.log.error(`Error setting default runtime ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('set default runtime response', response?.status); return response; } catch (err) { this.log.error(`Error setting default runtime \n${err}`); } } async listPrograms(token, valveId) { try { this.log.debug('Set Default Runtime', valveId); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `program/listPrograms/${valveId}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error setting default runtime ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('set default runtime response', response?.status); return response; } catch (err) { this.log.error(`Error setting default runtime \n${err}`); } } async listControllerWebhooks(token, id) { try { this.log.debug(`Get webhook ${id}`); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `webhook/listWebhooks?resource_id.irrigation_controller_id=${id}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting webhooks ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('get webhooks', response?.status); return response; } catch (err) { this.log.error(`Error getting webhooks \n${err}`); } } async listValveWebhooks(token, id) { try { this.log.debug(`Get webhook ${id}`); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: `webhook/listWebhooks?resource_id.valve_id=${id}`, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.error(`Error getting webhooks ${err.message}`); this.log.warn(JSON.stringify(err.response.data, null, 2)); this.log.debug(JSON.stringify(err, null, 2)); }); this.log.debug('get webhooks', response?.status); return response; } catch (err) { this.log.error(`Error getting webhooks \n${err}`); } } async configureWebhooks(token, external_webhook_address, delete_webhooks, device_id, device_name, webhook_key) { try { /********************************************* Event Type options from get events "id": 5 ="DEVICE_STATUS_EVENT" "id": 6 ="RAIN_DELAY_EVENT" "id": 7 ="WEATHER_INTELLIGENCE_EVENT" "id": 8 ="WATER_BUDGET" "id": 9= "SCHEDULE_STATUS_EVENT" "id": 8 ="WATER_BUDGET" "id": 10="ZONE_STATUS_EVENT" "id": 11="RAIN_SENSOR_DETECTION_EVENT" "id": 12="ZONE_DELTA" "id": 14="DELTA" **********************************************/ const events = [ { id: 5 }, { id: 6 }, ]; this.log.info(`Configuring Rachio webhooks for controller ID ${device_id}`); const response = await axios({ method: 'get', baseURL: api_endpoint, url: '/notification/' + device_id + '/webhook', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error retrieving webhooks ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('configured webhooks response', JSON.stringify(response.data, null, 2)); } } const webhooks = response.data; if (this.platform.showAPIMessages) { this.log.debug('configured webhooks response', JSON.stringify(response.data, null, 2)); } if (!webhooks || !Array.isArray(webhooks)) { return; } if (delete_webhooks) { //delete exsisting webhooks webhooks.forEach(async (webhook) => { if (webhook.externalId == webhook_key) { return; } //Skip the current webhook and let it be updated const response = await axios({ method: 'delete', baseURL: api_endpoint, url: '/notification/webhook/' + webhook.id, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error deleting old webhook ${webhook.id} error ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 204) { this.log.debug(`Successfully deleted old webhook ${webhook.id}`); } }); } let updateWebhook = false; let count = 0; webhooks.forEach(async (webhook) => { if (webhook.externalId == webhook_key || webhook.url == external_webhook_address) { count++; if (count == 1) { updateWebhook = webhook; return; } const response = await axios({ method: 'delete', baseURL: api_endpoint, url: '/notification/' + 'webhook/' + webhook.id, headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error deleting old webhook ${webhook.id} error ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 204) { this.log.debug(`Successfully deleted extra webhook ${webhook.id}`); } } }); if (updateWebhook) { this.log.info(`Updating Rachio Webhook ID ${updateWebhook.id}, for destination ${external_webhook_address}`); const response = await axios({ method: 'put', baseURL: api_endpoint, url: '/notification/webhook/', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', data: { id: updateWebhook.id, externalId: webhook_key, url: external_webhook_address, eventTypes: events, }, }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error updating exsisting webhook ${updateWebhook.id} error ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 204) { this.log.debug(`Successfully updated webhook ${response}`); } } else { this.log.info('Creating webhook for ' + external_webhook_address); const response = await axios({ method: 'post', baseURL: api_endpoint, url: '/notification/webhook/', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, responseType: 'json', data: { device: { id: device_id }, externalId: webhook_key, url: external_webhook_address, eventTypes: events, }, }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error configuring new webhook ${updateWebhook.id} error ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 204) { this.log.debug(`Successfully created webhook ${response}`); } } if (this.platform.showAPIMessages) { this.log.debug('create/update webhook response', JSON.stringify(response.data, null, 2)); } if (response.status == 200) { this.log.success(`Successfully configured webhook for ${device_name} with external id "${webhook_key}"`); } return; } catch (err) { this.log.error(`Error configuring webhook for ${device_name} \n${err}`); } } async configureWebhooksv2(token, external_webhook_address, delete_webhooks, device_id, device_name, webhook_key, type) { try { /********************************************* Event Type options from webhook info "resourceType": "VALVE", "eventTypes": [ "VALVE_RUN_START_EVENT", "VALVE_RUN_END_EVENT" "resourceType": "PROGRAM", "eventTypes": [ "PROGRAM_RAIN_SKIP_CREATED_EVENT", "PROGRAM_RAIN_SKIP_CANCELED_EVENT" "resourceType": "IRRIGATION_CONTROLLER", "eventTypes": [ "SCHEDULE_STARTED_EVENT", "SCHEDULE_STOPPED_EVENT", "SCHEDULE_COMPLETED_EVENT", "DEVICE_ZONE_RUN_STARTED_EVENT", "DEVICE_ZONE_RUN_PAUSED_EVENT", "DEVICE_ZONE_RUN_STOPPED_EVENT", "DEVICE_ZONE_RUN_COMPLETED_EVENT", "CLIMATE_SKIP_NOTIFICATION_EVENT", "FREEZE_SKIP_NOTIFICATION_EVENT", "RAIN_SKIP_NOTIFICATION_EVENT", "WIND_SKIP_NOTIFICATION_EVENT", "NO_SKIP_NOTIFICATION_EVENT" "resourceType": "LIGHTING_CONTROLLER", "eventTypes": [ "LIGHTING_ZONE_STATE_CHANGE_EVENT" **********************************************/ let param; let resource; let event; let events; if (type == 'irrigation_controller_id') { param = { 'resource_id.irrigation_controller_id': device_id, }; resource = { irrigation_controller_id: device_id, }; events = [ 'DEVICE_ZONE_RUN_STARTED_EVENT', 'DEVICE_ZONE_RUN_PAUSED_EVENT', 'DEVICE_ZONE_RUN_STOPPED_EVENT', 'DEVICE_ZONE_RUN_COMPLETED_EVENT', 'SCHEDULE_STARTED_EVENT', 'SCHEDULE_STOPPED_EVENT', 'SCHEDULE_COMPLETED_EVENT', ]; event = { event_types: events, }; } else if (type == 'valve_id') { param = { 'resource_id.valve_id': device_id, }; resource = { valve_id: device_id, }; events = [ 'VALVE_RUN_START_EVENT', 'VALVE_RUN_END_EVENT', ]; event = { event_types: events, }; } this.log.debug(`Configuring Rachio SHT webhooks for device ID ${device_id}`); const response = await axios({ method: 'get', baseURL: alt_api_endpoint, url: 'webhook/listWebhooks', headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json', 'User-Agent': `${PLUGIN_NAME}/${PLUGIN_VERSION}`, }, params: param, responseType: 'json', }).catch(err => { this.log.debug(JSON.stringify(err, null, 2)); this.log.error(`Error retrieving SHT webhooks ${err.message}`); if (err.response) { this.log.warn(JSON.stringify(err.response.data, null, 2)); } throw err.code; }); if (response.status == 200) { if (this.platform.showAPIMessages) { this.log.debug('configure