Skip to content

Instantly share code, notes, and snippets.

@pve84
Forked from bfritscher/sendToHA.js
Created October 5, 2022 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pve84/869685a4e52344d2e80ddb5d4421f52a to your computer and use it in GitHub Desktop.
Save pve84/869685a4e52344d2e80ddb5d4421f52a to your computer and use it in GitHub Desktop.
node.js script to upload external data to home assistant via the websocket api
const W3CWebSocket = require("websocket").w3cwebsocket; // npm install websocket
const host = "127.0.0.1";
const port = 8123;
const protocol = "ws"; // ws or wss if ssl
// long lived access token from profile > Create Token
const access_token ="";
const entityName = "Energy Consumption";
const entityId = "energy_consumption_kwh";
// datetime must be in ISO 8601 format with timezone
// stats = [{start: '2022-01-01T00:00:00z', sum: 0},...]
// start_search_time = datetime from which to search for old total
function sendToHA(stats, start_search_time) {
const client = new W3CWebSocket(
`${protocol}://${host}:${port}/api/websocket`
);
let id = 1;
const awaiting = new Set();
client.onerror = function (e) {
console.log("Connection Error", e);
};
client.onopen = function () {
console.log("WebSocket Client Connected");
};
client.onclose = function () {
console.log("WebSocket Client Closed");
};
client.onmessage = function (e) {
try {
const data = JSON.parse(e.data);
if (data.type === "auth_required") {
client.send(
JSON.stringify({
type: "auth",
access_token,
})
);
}
if (data.type === "auth_ok") {
// get the last state sum
const payload = {
id,
type: "history/statistics_during_period",
start_time: start_search_time,
end_time: stats[0].start,
statistic_ids: [`external:${entityId}`],
period: "hour",
};
console.log("request last stats");
awaiting.add(id);
client.send(JSON.stringify(payload));
id++;
}
if (data.type === "auth_invalid") {
console.log("Auth invalid", data);
client.close();
}
if (data.type === "result") {
awaiting.delete(data.id);
if (!data.success) {
console.log("Error", data.error);
} else {
console.log("Success", data.id);
// collect answer and insert updated stats
if (data.id === 1) {
const results = data.result[`external:${entityId}`];
if (results && results.length > 0) {
const lastStat = results[results.length - 1];
const sum = lastStat.sum;
console.log("Last stat", lastStat);
// shift all data fo a unique grand total, since last_rest does not work
stats.forEach((stat) => {
stat.sum += sum;
});
} else {
console.log("No last stats");
}
const payload = {
id,
type: "recorder/import_statistics",
metadata: {
has_mean: false,
has_sum: true,
name: entityName,
source: "external",
statistic_id: `external:${entityId}`,
unit_of_measurement: "kWh",
},
stats,
};
console.log("sending stats");
awaiting.add(id);
client.send(JSON.stringify(payload));
id++;
}
}
if (awaiting.size === 0) {
client.close();
}
}
} catch (e) {
console.log(e);
}
};
}
module.exports = sendToHA;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment