Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: do API calls from driver #14

Merged
merged 5 commits into from
Jan 19, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 0 additions & 61 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,67 +77,6 @@
"id": "add_devices",
"template": "add_devices"
}
],
"settings": [
{
"type": "group",
"label": {
"en": "IP address",
"nl": "IP addres"
},
"children": [
{
"id": "discovered_address",
"label": {
"en": "Auto-discovered address",
"nl": "Automatisch ontdekte adres"
},
"type": "label",
"required": false,
"value": ""
},
{
"id": "address",
"label": {
"en": "Override IP Address",
"nl": "IP-adres overschrijven"
},
"type": "text",
"required": false,
"hint": {
"en": "Overrides the auto-discovered IP address of the device.",
"nl": "Overschrijft het automatisch ontdekte IP-adres van het apparaat."
}
}
]
},
{
"type": "group",
"label": {
"en": "Troubleshooting",
"nl": "Probleemoplossing"
},
"children": [
{
"id": "debugEnabled",
"type": "checkbox",
"label": {
"en": "Enable debug data",
"nl": "Schakel probleemverhelping in"
},
"value": false
},
{
"id": "apiData",
"type": "textarea",
"label": {
"en": "Last API response",
"nl": "Laatste API-reactie"
},
"value": "{}"
}
]
}
]
}
],
Expand Down
120 changes: 27 additions & 93 deletions drivers/uponor/device.ts
Original file line number Diff line number Diff line change
@@ -1,135 +1,69 @@
import { isIPv4 } from 'net'
import { Device, DiscoveryResultMAC } from 'homey'
import { UponorHTTPClient } from '../../lib/UponorHTTPClient'

const POLL_INTERVAL_MS = 1000 * 60 * 1
import { UponorDriver } from './driver'
import { MEASURE_TEMPERATURE_CAPABILITY, TARGET_TEMPERATURE_CAPABILITY, POLL_INTERVAL_MS, INIT_TIMEOUT_MS } from '../../lib/constants'

class UponorThermostatDevice extends Device {

private _syncInterval?: NodeJS.Timer
private _client?: UponorHTTPClient

async onInit(): Promise<void> {
this._init()
}

async onAdded(): Promise<void> {
this._init()
}

async onUninit(): Promise<void> {
this._uninit()
}

onDeleted(): void {
this.homey.clearInterval(this._syncInterval)
await this._syncCapabilities()
this.homey.setInterval(this._syncAttributes.bind(this), POLL_INTERVAL_MS)
this.homey.setTimeout(this._syncAttributes.bind(this), INIT_TIMEOUT_MS)
}

onDiscoveryResult(discoveryResult: DiscoveryResultMAC): boolean {
return this.getData().id.includes(discoveryResult.id)
}

async onDiscoveryAvailable(discoveryResult: DiscoveryResultMAC): Promise<void> {
await this._updateDiscoveredAddress(discoveryResult.address)
await this._updateAddress(discoveryResult.address, true)
await this._updateAddress(discoveryResult.address)
}

async onDiscoveryAddressChanged(discoveryResult: DiscoveryResultMAC): Promise<void> {
await this._updateDiscoveredAddress(discoveryResult.address)
await this._updateAddress(discoveryResult.address, true)
}

async onSettings({ newSettings }: { newSettings: { [key: string]: any } }): Promise<void> {
const addressUpdated = await this._updateAddress(newSettings.address as string)
if (!addressUpdated) throw new Error(`Could not connect to Uponor controller on IP address ${newSettings.address}`)
}

private _getAddress(): string | undefined {
const settingAddress = this.getSetting('address')
if (settingAddress && isIPv4(settingAddress)) return settingAddress
const storeAddress = this.getStoreValue('address')
if (storeAddress && isIPv4(storeAddress)) return storeAddress
return undefined
}

private async _updateAddress(newAddress: string, persist = false): Promise<boolean> {
if (newAddress.length === 0) {
newAddress = await this.getStoreValue('address')
}

if (!isIPv4(newAddress)) {
return false
}

if (persist) {
await this.setStoreValue('address', newAddress)
}

if (!this._client) return false
const success = await this._client.updateAddress(newAddress)
return success
}

private async _updateDiscoveredAddress(newAddress: string): Promise<void> {
if (newAddress.length === 0) return
await this.setSettings({ 'discovered_address': newAddress })
await this._updateAddress(discoveryResult.address)
}

async _init(): Promise<void> {
const address = this._getAddress()
if (!address) return this.setUnavailable('No IP address configured')
this._client = new UponorHTTPClient(address)
this._syncInterval = this.homey.setInterval(this._sync.bind(this), POLL_INTERVAL_MS)
this.homey.setTimeout(this._sync.bind(this), 2000)
private _getClient(): UponorHTTPClient {
const driver = this.driver as UponorDriver
return driver.getClient()
}

async _uninit(): Promise<void> {
this.homey.clearInterval(this._syncInterval)
this._syncInterval = undefined
this._client = undefined
private async _updateAddress(newAddress: string): Promise<boolean> {
const driver = this.driver as UponorDriver
return await driver.setIpAddress(newAddress)
}

private async _sync(): Promise<void> {
await this._syncCapabilities()
await this._syncAttributes()
private async _syncCapabilities(): Promise<void> {
await this._ensureCapability(MEASURE_TEMPERATURE_CAPABILITY)
await this._ensureCapability(TARGET_TEMPERATURE_CAPABILITY, this._setTargetTemperature.bind(this))
}

private async _syncCapabilities(): Promise<void> {
this.registerCapabilityListener('target_temperature', this._setTargetTemperature.bind(this))
private async _ensureCapability(capability: string, callback: Device.CapabilityCallback | undefined = undefined): Promise<void> {
if (!this.hasCapability(capability)) await this.addCapability(capability)
if (callback) this.registerCapabilityListener(capability, callback)
}

private async _syncAttributes(): Promise<void> {
if (!this._client) return this.setUnavailable('No Uponor client')
const canConnect = await this._client.testConnection()
if (!canConnect) return this.setUnavailable('Could not connect to Uponor controller on local network')

try {
await this._client.syncAttributes()
await this._getClient().syncAttributes()
const { controllerID, thermostatID } = this.getData()
const data = this._client.getThermostat(controllerID, thermostatID)
const data = this._getClient().getThermostat(controllerID, thermostatID)
if (!data) return this.setUnavailable('Could not find thermostat data')
this.setAvailable()
this.setCapabilityValue('measure_temperature', data.temperature)
this.setCapabilityValue('target_temperature', data.setPoint)
this.setCapabilityValue(MEASURE_TEMPERATURE_CAPABILITY, data.temperature)
this.setCapabilityValue(TARGET_TEMPERATURE_CAPABILITY, data.setPoint)
} catch (error) {
this.homey.error(error)
this.setUnavailable('Could not fetch data from Uponor controller')
}

try {
const { debugEnabled } = this.getSettings()
if (!debugEnabled) return
const debug = await this._client.debug()
this.setSettings({ apiData: JSON.stringify(debug) })
} catch (error) { }
}

private async _setTargetTemperature(value: number): Promise<void> {
if (!this._client) return this.setUnavailable('No Uponor client')
private async _setTargetTemperature(value: number, _opts: any): Promise<void> {
const { controllerID, thermostatID } = this.getData()

try {
await this._client.setTargetTemperature(controllerID, thermostatID, value)
await this._getClient().setTargetTemperature(controllerID, thermostatID, value)
} catch (error) {
this.homey.error(error)
this.setUnavailable('Could not send data to Uponor controller')
}
}
Expand Down
61 changes: 0 additions & 61 deletions drivers/uponor/driver.compose.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,66 +40,5 @@
"id": "add_devices",
"template": "add_devices"
}
],
"settings": [
{
"type": "group",
"label": {
"en": "IP address",
"nl": "IP addres"
},
"children": [
{
"id": "discovered_address",
"label": {
"en": "Auto-discovered address",
"nl": "Automatisch ontdekte adres"
},
"type": "label",
"required": false,
"value": ""
},
{
"id": "address",
"label": {
"en": "Override IP Address",
"nl": "IP-adres overschrijven"
},
"type": "text",
"required": false,
"hint": {
"en": "Overrides the auto-discovered IP address of the device.",
"nl": "Overschrijft het automatisch ontdekte IP-adres van het apparaat."
}
}
]
},
{
"type": "group",
"label": {
"en": "Troubleshooting",
"nl": "Probleemoplossing"
},
"children": [
{
"id": "debugEnabled",
"type": "checkbox",
"label": {
"en": "Enable debug data",
"nl": "Schakel probleemverhelping in"
},
"value": false
},
{
"id": "apiData",
"type": "textarea",
"label": {
"en": "Last API response",
"nl": "Laatste API-reactie"
},
"value": "{}"
}
]
}
]
}
Loading
Loading