Skip to content

Commit

Permalink
Add repair flow for authentication (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisTerBeke authored Aug 10, 2024
1 parent 4880264 commit da131e5
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 103 deletions.
5 changes: 5 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,11 @@
"template": "add_devices"
}
],
"repair": [
{
"id": "login"
}
],
"settings": [
{
"type": "group",
Expand Down
125 changes: 63 additions & 62 deletions drivers/remeha/driver.compose.json
Original file line number Diff line number Diff line change
@@ -1,70 +1,71 @@
{
"name": {
"en": "Remeha eTwist"
"name": {
"en": "Remeha eTwist"
},
"class": "thermostat",
"capabilities": [
"target_temperature",
"measure_temperature",
"measure_temperature_water",
"measure_temperature_outside",
"measure_pressure",
"alarm_water"
],
"platforms": ["local"],
"connectivity": ["cloud"],
"images": {
"small": "{{driverAssetsPath}}/images/small.png",
"large": "{{driverAssetsPath}}/images/large.png",
"xlarge": "{{driverAssetsPath}}/images/xlarge.png"
},
"pair": [
{
"id": "login"
},
"class": "thermostat",
"capabilities": [
"target_temperature",
"measure_temperature",
"measure_temperature_water",
"measure_temperature_outside",
"measure_pressure",
"alarm_water"
],
"platforms": [
"local"
],
"connectivity": [
"cloud"
],
"images": {
"small": "{{driverAssetsPath}}/images/small.png",
"large": "{{driverAssetsPath}}/images/large.png",
"xlarge": "{{driverAssetsPath}}/images/xlarge.png"
{
"id": "list_devices",
"template": "list_devices",
"navigation": {
"next": "add_devices"
}
},
"pair": [
{
"id": "add_devices",
"template": "add_devices"
}
],
"repair": [
{
"id": "login"
}
],
"settings": [
{
"type": "group",
"label": {
"en": "Troubleshooting",
"nl": "Probleemoplossing"
},
"children": [
{
"id": "login"
"id": "debugEnabled",
"type": "checkbox",
"label": {
"en": "Enable debug data",
"nl": "Schakel probleemverhelping in"
},
"value": false
},
{
"id": "list_devices",
"template": "list_devices",
"navigation": {
"next": "add_devices"
}
},
{
"id": "add_devices",
"template": "add_devices"
}
],
"settings": [
{
"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": "{}"
}
]
"id": "apiData",
"type": "textarea",
"label": {
"en": "Last API response",
"nl": "Laatste API-reactie"
},
"value": "{}"
}
]
]
}
]
}
97 changes: 56 additions & 41 deletions drivers/remeha/driver.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,61 @@
import { Driver } from 'homey'
import { PairSession } from 'homey/lib/Driver'
import { RemehaAuth, TokenData } from '../../lib/RemehaAuth'
import { DeviceData, RemehaMobileApi } from '../../lib/RemehaMobileApi'
import { Device, Driver } from "homey";
import { PairSession } from "homey/lib/Driver";
import { RemehaAuth, TokenData } from "../../lib/RemehaAuth";
import { DeviceData, RemehaMobileApi } from "../../lib/RemehaMobileApi";

class RemehaDriver extends Driver {
private _tokenData: TokenData | null = null;

private _tokenData: TokenData | null = null

async onPair(session: PairSession) {
session.setHandler('login', this._login.bind(this))
session.setHandler('list_devices', this._listDevices.bind(this))
}

private async _login(credentials: string): Promise<any> {
const authorizer = new RemehaAuth()
const [email, password] = credentials.split('|')
if (!email || !password) throw new Error('Invalid credentials')
this._tokenData = await authorizer.login(email, password)
this.homey.settings.set('debug_token', JSON.stringify(this._tokenData))
}

private async _listDevices(): Promise<any[]> {
if (!this._tokenData || !this._tokenData.accessToken) return []
const api = new RemehaMobileApi(this._tokenData.accessToken)
const debug = await api.debug()
this.homey.settings.set('debug_devices', JSON.stringify(debug))
const devices = await api.devices()
return devices.map(this._mapDevice.bind(this))
}

private _mapDevice(device: DeviceData): any {
return {
name: device.name,
data: {
id: device.id,
},
store: {
accessToken: this._tokenData?.accessToken,
refreshToken: this._tokenData?.refreshToken,
}
}
}
async onPair(session: PairSession) {
this.homey.settings.set("debug_token", "");
session.setHandler("login", this._login.bind(this));
session.setHandler("list_devices", this._listDevices.bind(this));
}

async onRepair(session: PairSession, device: Device) {
this.homey.settings.set("debug_token", "");
session.setHandler("repair", this._updateTokenData.bind(this, device));
}

private async _login(credentials: string): Promise<void> {
this.homey.settings.set("debug_token", "");
const authorizer = new RemehaAuth();
const [email, password] = credentials.split("|");
if (!email || !password) throw new Error("Invalid credentials");
this._tokenData = await authorizer.login(email, password);
this.homey.settings.set("debug_token", JSON.stringify(this._tokenData));
}

private async _updateTokenData(
device: Device,
credentials: string,
): Promise<void> {
await this._login(credentials);
await device.setStoreValue("accessToken", this._tokenData?.accessToken);
await device.setStoreValue("refreshToken", this._tokenData?.refreshToken);
}

private async _listDevices(): Promise<any[]> {
if (!this._tokenData || !this._tokenData.accessToken) return [];
const api = new RemehaMobileApi(this._tokenData.accessToken);
const debug = await api.debug();
this.homey.settings.set("debug_devices", JSON.stringify(debug));
const devices = await api.devices();
return devices.map(this._mapDevice.bind(this));
}

private _mapDevice(device: DeviceData): any {
return {
name: device.name,
data: {
id: device.id,
},
store: {
accessToken: this._tokenData?.accessToken,
refreshToken: this._tokenData?.refreshToken,
},
};
}
}

module.exports = RemehaDriver
module.exports = RemehaDriver;
66 changes: 66 additions & 0 deletions drivers/remeha/repair/login.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script type="application/javascript">
function login() {
var email = document.getElementById("email").value;
var password = document.getElementById("password").value;
Homey.showLoadingOverlay();
Homey.emit("repair", `${email}|${password}`)
.then(() => {
Homey.done();
})
.catch((error) => {
Homey.alert(error.message, "error");
})
.finally(() => {
Homey.hideLoadingOverlay();
});
}
</script>

<header class="homey-header">
<h1 class="homey-title" data-i18n="pair.title"></h1>
</header>

<p data-i18n="pair.description"></p>

<form class="homey-form">
<fieldset class="homey-form-fieldset">
<div class="homey-form-group">
<label
class="homey-form-label"
for="email"
data-i18n="pair.email"
></label>
<input
class="homey-form-input"
id="email"
type="email"
autocomplete="email"
value=""
required
/>
</div>
<div class="homey-form-group">
<label
class="homey-form-label"
for="password"
data-i18n="pair.password"
></label>
<input
class="homey-form-input"
id="password"
type="password"
autocomplete="current-password"
value=""
required
/>
</div>
</fieldset>
</form>

<br />

<button
class="homey-button-primary-full"
onclick="login()"
data-i18n="pair.submit"
></button>

0 comments on commit da131e5

Please sign in to comment.