From f652d084ca349d9b6450dfc8585221e8b9a2de7a Mon Sep 17 00:00:00 2001 From: Jan Wolf Date: Sun, 23 Jun 2024 14:08:34 +0200 Subject: [PATCH] fix: historic updates --- .../homeassistant/modules/irrigation.ts | 116 +++++++++--------- .../plugins/homeassistant/modules/light.ts | 35 +++--- .../backend/plugins/homeassistant/registry.ts | 29 +++++ smartblueberry/config.json | 2 +- 4 files changed, 100 insertions(+), 82 deletions(-) diff --git a/smartblueberry/backend/plugins/homeassistant/modules/irrigation.ts b/smartblueberry/backend/plugins/homeassistant/modules/irrigation.ts index 68aa84e..bbf4f92 100644 --- a/smartblueberry/backend/plugins/homeassistant/modules/irrigation.ts +++ b/smartblueberry/backend/plugins/homeassistant/modules/irrigation.ts @@ -238,70 +238,66 @@ async function getPastIrrigationRecords( ) { // Get irrigation amounts of valve const now = dayjs() - return await server.plugins.hassConnect.rest - .get[][]>( - `/history/period/${dayjs(sinceDay).startOf('day').toISOString()}?${[ - `end_time=${now.toISOString()}`, - `filter_entity_id=${entityId}` - ].join('&')}` - ) - .then(({ ok, json }) => { - const recordMap = (ok ? json! : []) - .flat() - .reduce( - (recordMap: IrrigationRecordMap, newRecord, index, array) => { - const recordDate = dayjs(newRecord.last_changed) - const recordKey = recordDate.format('YYYY-MM-DD') - let isFirstOfDay = recordMap[recordKey] === undefined - recordMap[recordKey] = isFirstOfDay - ? { - irrigation: 0, - lastChanged: recordDate.startOf('day').toISOString(), - lastState: newRecord.state === 'off' ? 'on' : 'off' - } - : { - ...recordMap[recordKey], - lastChanged: newRecord.last_changed, - lastState: newRecord.state - } - - recordMap[recordKey].irrigation += - newRecord.state === 'off' - ? ((recordDate.unix() - - dayjs(recordMap[recordKey].lastChanged).unix()) / - 60) * - irrigationVolumePerMinute - : 0 - - let isLastRecord = array.length - 1 === index - if (isLastRecord) { - recordMap = Object.fromEntries( - Object.entries(recordMap).map(([key, value]) => { - if (value.lastState === 'on') { - const recordDate = dayjs(value.lastChanged) - const recordDateEndOfDay = recordDate.endOf('day') - value.irrigation += - ((recordDateEndOfDay.unix() - recordDate.unix()) / - 60) * - irrigationVolumePerMinute - } - return [key, value] - }) - ) - } + return await server.app.hassRegistry + .history({ + startTime: dayjs(sinceDay).startOf('day').toISOString(), + endTime: now.toISOString(), + entityIds: [entityId] + }) + .then((result) => { + const recordMap = (result?.[entityId] || []).reduce( + (recordMap: IrrigationRecordMap, newRecord, index, array) => { + const recordDate = dayjs(newRecord.lu) + const recordKey = recordDate.format('YYYY-MM-DD') + let isFirstOfDay = recordMap[recordKey] === undefined + recordMap[recordKey] = isFirstOfDay + ? { + irrigation: 0, + lastChanged: recordDate.startOf('day').toISOString(), + lastState: newRecord.s === 'off' ? 'on' : 'off' + } + : { + ...recordMap[recordKey], + lastChanged: newRecord.lu, + lastState: newRecord.s + } - return recordMap - }, - {} + recordMap[recordKey].irrigation += + newRecord.s === 'off' + ? ((recordDate.unix() - + dayjs(recordMap[recordKey].lastChanged).unix()) / + 60) * + irrigationVolumePerMinute + : 0 + + let isLastRecord = array.length - 1 === index + if (isLastRecord) { + recordMap = Object.fromEntries( + Object.entries(recordMap).map(([key, value]) => { + if (value.lastState === 'on') { + const recordDate = dayjs(value.lastChanged) + const recordDateEndOfDay = recordDate.endOf('day') + value.irrigation += + ((recordDateEndOfDay.unix() - recordDate.unix()) / 60) * + irrigationVolumePerMinute + } + return [key, value] + }) ) + } + + return recordMap + }, + {} + ) - const amount = Object.values(recordMap).reduce( - (summed, next) => summed + next.irrigation, - 0 - ) + const amount = Object.values(recordMap).reduce( + (summed, next) => summed + next.irrigation, + 0 + ) - return [amount, recordMap] as [number, IrrigationRecordMap] - }) + return [amount, recordMap] as [number, IrrigationRecordMap] + }) } /** diff --git a/smartblueberry/backend/plugins/homeassistant/modules/light.ts b/smartblueberry/backend/plugins/homeassistant/modules/light.ts index 052632b..085af6e 100644 --- a/smartblueberry/backend/plugins/homeassistant/modules/light.ts +++ b/smartblueberry/backend/plugins/homeassistant/modules/light.ts @@ -340,10 +340,7 @@ async function setupSimulateLightMode(server: hapi.Server) { const { mode, options } = (await getAreaLightMode(server, area_id)) || {} if (mode == 'simulate') { - const historyTimestamp = dayjs(dayjs()) - .subtract(1, 'month') - .toISOString() - + const pastTimestamp = dayjs().subtract(1, 'week').toISOString() const lightEntityNames = server.app.hassRegistry .getStates({ ...LIGHT_ENTITY, @@ -352,23 +349,19 @@ async function setupSimulateLightMode(server: hapi.Server) { .map(({ entity_id }) => entity_id) if (lightEntityNames.length > 0) { - const { ok, json } = await server.plugins.hassConnect.rest.get< - Pick[][] - >( - `/history/period/${historyTimestamp}?${[ - `end_time=${historyTimestamp}`, - `minimal_response=true`, - `filter_entity_id=${lightEntityNames.join(',')}` - ].join('&')}` - ) - - const hadActiveLight = - ok && - !!json?.some((entityHistory) => { - return entityHistory.some( - (entityHistoryRecord) => entityHistoryRecord.state == 'on' - ) - }) + const historicLightStates = await server.app.hassRegistry.history({ + startTime: pastTimestamp, + endTime: pastTimestamp, + entityIds: lightEntityNames + }) + + const hadActiveLight = Object.values( + historicLightStates || {} + ).some((historicLightState) => { + return historicLightState.some( + (historicLightStateItem) => historicLightStateItem.s == 'on' + ) + }) const service = hadActiveLight ? 'turn_on' : 'turn_off' const service_data: { brightness?: number } = {} diff --git a/smartblueberry/backend/plugins/homeassistant/registry.ts b/smartblueberry/backend/plugins/homeassistant/registry.ts index 366d44e..a102882 100644 --- a/smartblueberry/backend/plugins/homeassistant/registry.ts +++ b/smartblueberry/backend/plugins/homeassistant/registry.ts @@ -28,6 +28,12 @@ interface StateAttributes { | StateAttributes } +interface HistoryPayload { + s: StatePayload['state'] + lu: StatePayload['last_updated'] + a: StateAttributes +} + interface StatePayload { entity_id: string state: string @@ -479,6 +485,29 @@ class Registry { }) } + public async history({ + startTime, + endTime, + entityIds + }: { + startTime: string + endTime: string + entityIds: EntityIds + }) { + const connection = await this.server.plugins.hassConnect.globalConnect() + + return connection + ?.sendMessagePromise<{ + result?: { [key: string]: HistoryPayload[] } + }>({ + type: 'history/history_during_period', + start_time: startTime, + end_time: endTime, + entity_ids: entityIds + }) + .then((response) => response.result) + } + /** * Updates parameters of an entity. * @param entityId The id of the entity to update. diff --git a/smartblueberry/config.json b/smartblueberry/config.json index bb80076..e589097 100644 --- a/smartblueberry/config.json +++ b/smartblueberry/config.json @@ -1,7 +1,7 @@ { "slug": "smartblueberry", "name": "Smart Blueberry 🫐", - "version": "1.0.9", + "version": "1.0.10", "description": "Smart Blueberry is a Home Assistant environment providing multiple extensions to simplify the configuration of light, presence and irrigation management.", "url": "https://github.com/janwo/smartblueberry/tree/main/smartblueberry", "image": "janwo/smartblueberry-{arch}",