Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
a7d48ee
Added translations, removed ps2 driver, reused capabilities
kaohlive Feb 10, 2024
5655dd5
Some addiotional translations
kaohlive Feb 10, 2024
bcc9aeb
Merge branch 'master' of https://github.com/kaohlive/Polestar
kaohlive Feb 10, 2024
0e1f132
Merge conflict handling
kaohlive Feb 10, 2024
cfa38d1
Merge branch 'Coderaxx:master' into master
kaohlive Feb 18, 2024
739fc3d
Remove duplicate battery, confusing
kaohlive Feb 18, 2024
09c303a
Merge branch 'Coderaxx:master' into master
kaohlive Apr 26, 2024
39f5d8b
Added support for charging power
kaohlive Apr 26, 2024
999d245
Bump version to v2.2.0
kaohlive May 6, 2024
17e72ea
Bump version to v2.3.0
kaohlive Aug 9, 2024
af178ad
Changed polestar vehicle to new device class car
kaohlive Aug 9, 2024
4a26250
Bump version to v2.3.1
kaohlive Sep 1, 2024
bbb6852
Fix on flow triggers
kaohlive Sep 1, 2024
bd5b6d1
Bump version to v2.3.2
kaohlive Sep 1, 2024
d8227bf
hotfix on csv driver
kaohlive Sep 1, 2024
21dbc98
Bump version to v2.3.3
kaohlive Oct 6, 2024
05b1558
Improved insights on power measurements
kaohlive Oct 6, 2024
958f296
Bump version to v2.3.4
kaohlive Nov 12, 2024
15091d1
update to fix api changes
kaohlive Nov 12, 2024
e925e16
Bump version to v2.3.5
kaohlive Nov 20, 2024
10ec652
First version of widget support
kaohlive Dec 7, 2024
3cb151b
Bump version to v2.4.0
kaohlive Dec 7, 2024
265149f
Widget, service warning and login bug fix
kaohlive Dec 7, 2024
f7da1c8
Bump version to v2.4.1
kaohlive Dec 7, 2024
fceeb77
fix realtime event to widget
kaohlive Dec 7, 2024
4451b50
Bump version to v2.4.2
kaohlive Dec 7, 2024
6a5094e
fix status updates for widget
kaohlive Dec 7, 2024
b9d3154
Bump version to v2.4.3
kaohlive Dec 8, 2024
c582f39
stability improvement
kaohlive Dec 8, 2024
cf125c2
Bump version to v2.4.4
kaohlive Dec 8, 2024
d4e985b
service warning improvement
kaohlive Dec 8, 2024
71c1c43
Bump version to v2.4.5
kaohlive Dec 9, 2024
e83177b
Update preview of widget
kaohlive Dec 9, 2024
ad084c1
Bump version to v2.4.6
kaohlive Dec 15, 2024
badbb1d
Fix for another api change on polestar side
kaohlive Dec 15, 2024
ad02577
Bump version to v2.5.0
kaohlive Jan 26, 2025
a385aac
Added power meter with estimated overall usage
kaohlive Jan 26, 2025
1369029
Bump version to v2.5.1
kaohlive Feb 4, 2025
21202a2
Attempt to fix new api issue
kaohlive Feb 4, 2025
d22d9c0
Bump version to v2.6.0
kaohlive Apr 3, 2025
b2fdd03
Authentication fix and new capabilities
kaohlive Apr 3, 2025
6b09709
Login error fix
kaohlive Apr 20, 2025
9886e55
Bump version to v2.6.1
kaohlive Apr 20, 2025
a36f675
Bump version to v2.6.2
kaohlive Apr 20, 2025
fe3bee9
Login error fix
kaohlive Apr 20, 2025
9dc2f02
Refactor for new car telematics data model
kaohlive May 25, 2025
8aa5842
Bump version to v2.7.1
kaohlive Jun 1, 2025
d0e3408
Added support for new ev charging states
kaohlive Jun 1, 2025
2d563c4
Bump version to v2.7.2
kaohlive Jun 12, 2025
a6f5cba
Fixed CSV receiver driver
kaohlive Jun 12, 2025
40e2340
Bump version to v2.7.3
kaohlive Aug 31, 2025
5d35cc9
Added upgrade path for existing cars for homey energy
kaohlive Aug 31, 2025
67add9b
Bump version to v2.7.4
kaohlive Sep 1, 2025
599f8eb
More rebost energy upgrade detection
kaohlive Sep 1, 2025
940753a
added testing scripts to find more details from the api, no new field…
kaohlive Oct 26, 2025
a64988b
Bump version to v2.7.5
kaohlive Oct 26, 2025
d77aecb
Changed api, no linger supports images
kaohlive Oct 26, 2025
9751318
Bump version to v2.7.6
kaohlive Oct 30, 2025
570d2ee
Bump version to v2.7.7
kaohlive Jan 18, 2026
47a9cbe
Added support to switch to miles
kaohlive Jan 18, 2026
ee8e640
Bump version to v2.7.8
kaohlive Jan 19, 2026
7b89b8c
Rounding and stability improvements
kaohlive Jan 19, 2026
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
9 changes: 9 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"permissions": {
"allow": [
"Bash(node -e:*)"
],
"deny": [],
"ask": []
}
}
367 changes: 367 additions & 0 deletions .claude/skills/homey-widget-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,367 @@
# Homey Widget/Dashboard API Guide

This skill documents how to work with the built-in Homey API from dashboard widgets in this project.

## Overview

The Homey framework provides an internal message-based API system for communication between HTML widgets and the Homey app. This is NOT a traditional REST server - it's Homey's built-in widget API framework.

## Architecture

```
Widget HTML (index.html)
├─► Homey.api('GET', '/endpoint') [Request]
Widget API Handler (api.js)
├─► Access device capabilities
Response returned to Widget
Widget renders the data
```

## File Structure

```
widgets/<widget-name>/
├── public/
│ └── index.html # Widget HTML with JavaScript
├── api.js # Backend API handler functions
└── widget.compose.json # Widget configuration & API definition
```

## 1. Defining API Endpoints

API endpoints are defined in `widget.compose.json`:

```json
{
"name": { "en": "Widget Name" },
"height": 188,
"transparent": true,
"settings": [
{
"id": "device",
"type": "autocomplete",
"title": { "en": "Vehicle" }
}
],
"api": {
"getVehicles": {
"method": "GET",
"path": "/"
},
"getVehicleStatus": {
"method": "GET",
"path": "/status"
}
}
}
```

The `api` object maps function names to HTTP-like endpoints:
- Keys (e.g., `getVehicleStatus`) must match exported function names in `api.js`
- `method`: HTTP method (`GET`, `POST`, etc.)
- `path`: Endpoint path (relative to widget)

## 2. Implementing API Handlers

Create `api.js` to implement the endpoint handlers:

```javascript
'use strict';

module.exports = {
// Handler for GET /status
async getVehicleStatus({ homey, query }) {
const { registration } = query; // Access query parameters

// Get driver and find device
const driver = await homey.drivers.getDriver('vehicle');
const vehicle = driver.getDevices().find(
device => device.getData().registration === registration
);

if (!vehicle) {
throw new Error('Vehicle Not Found');
}

// Return capability values
return {
battery: vehicle.getCapabilityValue('measure_polestarBattery'),
connected: vehicle.getCapabilityValue('measure_vehicleConnected'),
charging: vehicle.getCapabilityValue('measure_vehicleChargeState'),
current: vehicle.getCapabilityValue('measure_current'),
power: vehicle.getCapabilityValue('measure_power'),
time_remaining: vehicle.getCapabilityValue('measure_vehicleChargeTimeRemaining'),
odometer: vehicle.getCapabilityValue('measure_vehicleOdometer'),
range: vehicle.getCapabilityValue('measure_vehicleRange'),
service: vehicle.getCapabilityValue('alarm_generic'),
};
},

// Handler for GET /
async getVehicles({ homey, body }) {
const driver = await homey.drivers.getDriver('vehicle');
return driver.getDevices();
}
};
```

### Handler Function Parameters

| Parameter | Description |
|-----------|-------------|
| `homey` | The Homey instance for accessing drivers, settings, etc. |
| `query` | Query string parameters (for GET requests) |
| `body` | Request body (for POST requests) |

## 3. Calling the API from Widget HTML

### Basic API Call

```javascript
Homey.api('GET', '/status?registration=ABC123')
.then(response => {
console.log(response);
})
.catch(err => {
console.error(err);
});
```

### Full Widget Example

```html
<script type="text/javascript">
let status;

// Called when Homey is ready
function onHomeyReady(Homey) {
Homey.ready(); // Signal widget is ready
syncStatus(); // Initial data fetch

// Listen for real-time updates
Homey.on('updatevehicle', () => {
syncStatus();
});
}

function syncStatus() {
// Get selected device from widget settings
const { device } = Homey.getSettings();
if (!device) {
showError('Please select a device');
return;
}

// Call the API
Homey.api('GET', `/status?registration=${device.registration}`)
.then(response => {
status = response;
renderStatus();
})
.catch(err => {
showError(err.message);
});
}

function renderStatus() {
document.getElementById('battery').innerText = status.battery + '%';
document.getElementById('range').innerText = status.range + ' km';
}
</script>
```

## 4. Homey API Methods Reference

### `Homey.api(method, path, [body])`
Make an API call to the widget backend.

```javascript
// GET request with query params
Homey.api('GET', '/status?id=123')

// POST request with body
Homey.api('POST', '/action', { command: 'start' })
```

### `Homey.ready()`
Signal that the widget is ready to receive data. **Must be called** in `onHomeyReady`.

```javascript
function onHomeyReady(Homey) {
Homey.ready();
}
```

### `Homey.getSettings()`
Get widget settings configured by the user.

```javascript
const { device } = Homey.getSettings();
```

### `Homey.on(event, callback)`
Listen for real-time events from the app.

```javascript
Homey.on('updatevehicle', () => {
syncStatus();
});
```

### `Homey.emit(event, data)` (for pair/repair pages)
Emit events to the driver. Used in pairing flows.

```javascript
Homey.emit('testlogin', { username, password })
.then(result => {
// Handle success
});
```

## 5. Real-Time Updates

### Broadcasting from Device/App

From `device.js` or `app.js`, broadcast updates to widgets:

```javascript
// In device.js
this.homey.api.realtime('updatevehicle');

// In app.js
this.homey.api.realtime('debugLog', { message: 'Something happened' });
```

### Listening in Widget

```javascript
Homey.on('updatevehicle', () => {
// Refresh widget data
syncStatus();
});
```

## 6. Widget Settings Autocomplete

Register autocomplete handlers in `app.js`:

```javascript
class MyApp extends Homey.App {
async onInit() {
this.homey.dashboards
.getWidget('dashboard')
.registerSettingAutocompleteListener('device', async (query, settings) => {
const driver = await this.homey.drivers.getDriver('vehicle');
const devices = await driver.getDevices();

return devices
.map(device => ({
name: device.getName(),
registration: device.getData().registration,
}))
.filter(v => v.name.toLowerCase().includes(query.toLowerCase()));
});
}
}
```

## 7. Available Device Capabilities

Access these via `vehicle.getCapabilityValue()`:

| Capability | Type | Description |
|-----------|------|-------------|
| `measure_polestarBattery` | number (0-100) | Battery percentage |
| `measure_vehicleConnected` | boolean | Charger connected |
| `measure_vehicleChargeState` | boolean | Currently charging |
| `measure_current` | number | Charging current (A) |
| `measure_power` | number | Charging power (W) |
| `measure_vehicleChargeTimeRemaining` | number | Minutes to full |
| `measure_vehicleOdometer` | number | Odometer (km) |
| `measure_vehicleRange` | number | Estimated range (km) |
| `alarm_generic` | boolean | Service warning |

## 8. Error Handling

Always handle errors in API calls:

```javascript
Homey.api('GET', '/status?registration=ABC')
.then(status => {
renderStatus(status);
})
.catch(err => {
// Show user-friendly error
document.getElementById('error').innerText = err.message;
});
```

In API handlers, throw errors to return them to the widget:

```javascript
async getVehicleStatus({ homey, query }) {
if (!query.registration) {
throw new Error('Missing registration parameter');
}
// ...
}
```

## 9. Complete Example: Adding a New Endpoint

### Step 1: Define in widget.compose.json

```json
{
"api": {
"setChargeLimit": {
"method": "POST",
"path": "/charge-limit"
}
}
}
```

### Step 2: Implement in api.js

```javascript
module.exports = {
async setChargeLimit({ homey, body }) {
const { registration, limit } = body;
const vehicle = await getVehicle({ homey, registration });

// Perform action
await vehicle.setCapabilityValue('target_charge_level', limit);

return { success: true, newLimit: limit };
}
};
```

### Step 3: Call from widget HTML

```javascript
Homey.api('POST', '/charge-limit', {
registration: device.registration,
limit: 80
})
.then(result => {
console.log('Charge limit set to', result.newLimit);
});
```

## Key Files in This Project

- [widgets/dashboard/widget.compose.json](widgets/dashboard/widget.compose.json) - Widget configuration
- [widgets/dashboard/api.js](widgets/dashboard/api.js) - API handlers
- [widgets/dashboard/public/index.html](widgets/dashboard/public/index.html) - Widget HTML
- [app.js](app.js) - App initialization & autocomplete registration
- [drivers/vehicle/device.js](drivers/vehicle/device.js) - Device capabilities & realtime broadcasts
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
drivers/polestar-2/*
drivers/polestar-2-beta/*
.homeyignore
/env.json
/env_secret.json
tmpclaude-7720-cwd
Loading