-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a widget that indicates activity state for a given zone
- Loading branch information
Showing
14 changed files
with
378 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import { ExtendedDeviceCapability, ExtendedHomeyAPIV3Local, ExtendedZone } from "homey-api"; | ||
import Homey from "homey/lib/Homey"; | ||
import handleZoneAutocomplete from "../utils/handleZoneAutocomplete"; | ||
import ZonesDb from "./ZonesDb"; | ||
import getIconForZone from "./../utils/getIconForZone"; | ||
|
||
export default class WidgetZoneActivityState { | ||
|
||
private static instance: WidgetZoneActivityState | null = null; | ||
|
||
widget: unknown; | ||
|
||
syncDevicesTimeoutId: NodeJS.Timeout | undefined; | ||
|
||
capabilityInstances: Map<string, ExtendedDeviceCapability> = new Map(); | ||
|
||
private constructor(private homey: Homey, private homeyApi: ExtendedHomeyAPIV3Local, private zonesDb: ZonesDb, private log: (...args: unknown[]) => void, private error: (...args: unknown[]) => void) { | ||
|
||
// @ts-expect-error Ignore the error for the non-existing method / property | ||
this.widget = this.homey.dashboards.getWidget('zone-activity-state'); | ||
} | ||
|
||
public static async initialize(homey: Homey, homeyApi: ExtendedHomeyAPIV3Local, zonesDb: ZonesDb, log: (...args: unknown[]) => void, error: (...args: unknown[]) => void): Promise<WidgetZoneActivityState> { | ||
if (WidgetZoneActivityState.instance === null) { | ||
WidgetZoneActivityState.instance = new WidgetZoneActivityState(homey, homeyApi, zonesDb, log, error); | ||
await WidgetZoneActivityState.instance.setup(); | ||
} | ||
return WidgetZoneActivityState.instance; | ||
} | ||
|
||
private async setup(): Promise<void> { | ||
// @ts-expect-error Ignore the error for the non-existing method / property | ||
this.widget.registerSettingAutocompleteListener('zone', async (query: string) => { | ||
const result = (await handleZoneAutocomplete(query, this.zonesDb)) | ||
// Remap icon to image for all results | ||
.map((zone) => { | ||
zone.image = zone.icon; | ||
delete zone.icon; | ||
return zone; | ||
}); | ||
|
||
this.log('Zone autocomplete results:', result); | ||
return result; | ||
}); | ||
|
||
this.homeyApi.zones.on('zone.update', async (zone: ExtendedZone) => { | ||
this.homey.api.realtime('zone-update', this.transformZone(zone)); | ||
}); | ||
} | ||
|
||
public async isZoneActive(zoneId: string): Promise<unknown> { | ||
const zone = await this.homeyApi.zones.getZone({ id: zoneId }); | ||
if (zone === null) | ||
return null; | ||
|
||
return this.transformZone(zone); | ||
} | ||
|
||
private transformZone(zone: ExtendedZone): unknown { | ||
const lastUpdated = new Date(zone.activeLastUpdated); | ||
const now = new Date(); | ||
let date: string; | ||
|
||
const language = this.homey.i18n.getLanguage(); | ||
const timezone = this.homey.clock.getTimezone(); | ||
|
||
const timeDifference = now.getTime() - lastUpdated.getTime(); | ||
const minutesDifference = Math.floor(timeDifference / (1000 * 60)); | ||
const hoursDifference = Math.floor(timeDifference / (1000 * 60 * 60)); | ||
|
||
if (lastUpdated.toDateString() === now.toDateString()) { | ||
date = lastUpdated.toLocaleTimeString(language, { timeZone: timezone }); | ||
} else { | ||
date = lastUpdated.toLocaleString(language, { timeZone: timezone }); | ||
} | ||
|
||
let subtitle: string; | ||
if (zone.active) { | ||
subtitle = this.homey.__('active'); | ||
} else if (hoursDifference >= 24) { | ||
subtitle = `${this.homey.__('last_active')}: ${date}`; | ||
} else if (hoursDifference > 0) { | ||
subtitle = `${this.homey.__('last_active')}: ${hoursDifference} ${this.homey.__('hours_ago')}`; | ||
} else { | ||
subtitle = `${this.homey.__('last_active')}: ${minutesDifference} ${this.homey.__('minutes_ago')}`; | ||
} | ||
|
||
const result = { | ||
id: zone.id, | ||
icon: getIconForZone(zone.icon), | ||
name: zone.name, | ||
subtitle: subtitle, | ||
active: zone.active, | ||
activeLastUpdated: zone.activeLastUpdated, | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,8 @@ | ||
{ | ||
"any_type": "Any type", | ||
"any_sensor": "Any sensor" | ||
"any_sensor": "Any sensor", | ||
"active": "Active", | ||
"last_active": "Last active", | ||
"hours_ago": "hours ago", | ||
"minutes_ago": "minutes ago" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,8 @@ | ||
{ | ||
"any_type": "Elk type", | ||
"any_sensor": "Elke sensor" | ||
"any_sensor": "Elke sensor", | ||
"active": "Actief", | ||
"last_active": "Laatst actief", | ||
"hours_ago": "uur geleden", | ||
"minutes_ago": "minuten geleden" | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
|
||
import Homey from "homey/lib/Homey"; | ||
|
||
class ZoneActivityStateWidget { | ||
public async getSomething({ homey, query }: ApiRequest) : Promise<string> { | ||
// you can access query parameters like "/?foo=bar" through `query.foo` | ||
|
||
console.log('query', query); | ||
|
||
//@ts-expect-error: Ignore the error for the non-existing method 'test' | ||
const result = await homey.app.widget.isZoneActive(query.zoneId); | ||
|
||
console.log('result', result); | ||
|
||
|
||
|
||
|
||
// perform other logic like mapping result data | ||
return result; | ||
} | ||
|
||
// public async addSomething({ homey, body }: ApiRequest) : Promise<string> { | ||
// // access the post body and perform some action on it. | ||
// return homey.app.addSomething(body); | ||
// } | ||
|
||
// // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
// public async updateSomething({ homey, params, body }: ApiRequest) : Promise<string> { | ||
// return homey.app.setSomething(body); | ||
// } | ||
|
||
// public async deleteSomething({ homey, params } : ApiRequest) : Promise<string> { | ||
// return homey.app.deleteSomething(params.id); | ||
// } | ||
} | ||
|
||
module.exports = new ZoneActivityStateWidget(); | ||
|
||
type ApiRequest = { homey: Homey; query: string, body: unknown, params: unknown }; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.