solar-assistant
v0.1.0
Published
Node.js client for the Solar Assistant cloud and local device APIs
Downloads
151
Maintainers
Readme
solar-assistant
Node.js client for the Solar Assistant cloud and local device APIs.
Supports both real-time metric streaming (WebSocket) and REST snapshots — works with the cloud API or direct local connections.
Installation
npm install solar-assistantRequires Node.js 18+.
Quick start
import { SolarAssistantClient, connect } from 'solar-assistant';
// 1. Create a cloud client (get your API key at solar-assistant.io/user/edit#api)
const client = new SolarAssistantClient({ apiKey: process.env.SA_API_KEY! });
// 2. List your sites
const sites = await client.listSites();
console.log(sites[0].name, sites[0].inverter);
// 3. Authorize a WebSocket connection
const auth = await client.authorizeSite(sites[0].id);
// 4. Connect and stream metrics
const socket = await connect({
host: auth.host,
token: auth.token,
siteId: auth.site_id,
siteKey: auth.site_key,
// Optional: try local IP first, fall back to cloud
localIp: auth.local_ip,
});
socket.subscribeMetrics((metric) => {
console.log(`${metric.device}/${metric.name} = ${metric.value} ${metric.unit}`);
});
await socket.listen(); // blocks until disconnectedAPI
SolarAssistantClient
const client = new SolarAssistantClient({
apiKey: 'your-api-key',
baseUrl?: 'https://solar-assistant.io', // optional override
verbose?: false,
});
// List sites with optional filters
const sites = await client.listSites({
inverter?: 'srne',
battery?: 'daly',
last_seen_after?: '2026-01-01',
limit?: 10,
offset?: 0,
});
// Get WebSocket credentials for a site
const auth = await client.authorizeSite(siteId);
// auth.host, auth.token, auth.site_id, auth.site_key, auth.local_ipconnect(options)
Establishes a WebSocket connection. If localIp is provided, attempts a direct local connection first (500ms timeout) before falling back to the cloud proxy.
const socket = await connect({
host: 'eu1.solar-assistant.io', // cloud proxy host from authorizeSite
token: '...', // JWT from authorizeSite
siteId: 12345,
siteKey: '...',
// — OR — local direct connection (no cloud account needed):
host: '192.168.1.100',
password: 'your-web-password',
// — OR — hybrid (try local first, fall back to cloud):
host: auth.host,
token: auth.token,
siteId: auth.site_id,
siteKey: auth.site_key,
localIp: auth.local_ip, // tries this first
verbose?: false, // log WebSocket frames to stderr
});socket.subscribeMetrics(handler, filters?)
Receive real-time metric updates. Optionally filter by topic glob and throttle frequency:
// All default metrics (battery, inverter, totals)
socket.subscribeMetrics((m) => console.log(m.topic, m.value, m.unit));
// Specific topics with throttling
socket.subscribeMetrics(
(m) => console.log(m),
[
{ topic: 'battery*' },
{ topic: 'total/pv_power', max_frequency_s: 10 },
]
);Each Metric contains:
| Field | Type | Description |
|----------|----------|--------------------------------------|
| topic | string | e.g. "battery_1/state_of_charge" |
| device | string | e.g. "Battery 1" |
| number | number | Device index |
| group | string | Metric group |
| name | string | e.g. "State of charge" |
| value | unknown| Numeric, string, or boolean |
| unit | string | e.g. "%", "W", "V" |
socket.subscribe(topic, event, handler)
Low-level access to raw Phoenix Channel messages. Use "*" as a wildcard:
socket.subscribe('*', '*', (msg) => console.log(msg.topic, msg.event, msg.payload));socket.listen()
Starts the heartbeat and reads messages in a loop. Returns a Promise<void> that resolves when the connection closes.
socket.close()
Closes the WebSocket connection.
getMetrics(options)
Fetch a REST snapshot of current metric values (no streaming):
import { getMetrics } from 'solar-assistant';
// Via cloud
const metrics = await getMetrics({
host: auth.host,
token: auth.token,
siteId: auth.site_id,
siteKey: auth.site_key,
topic: 'battery*', // optional glob filter
});
// Via local device
const metrics = await getMetrics({
host: '192.168.1.100',
password: 'your-web-password',
});
// metrics[0] = { topic, group, name, value, unit }Default metric topics
When subscribeMetrics is called with no filters, the server sends:
total/*
battery_*/voltage
battery_*/state_of_charge
battery_*/power
battery_*/temperature
inverter_*/pv_power
inverter_*/load_power
inverter_*/grid_power
inverter_*/device_mode
inverter_*/temperatureLicense
MIT
