Skip to content

Instantly share code, notes, and snippets.

@JerryWorkman
Last active March 2, 2018 02:38
Show Gist options
  • Save JerryWorkman/31987605cd4958864dd5f159e26c0408 to your computer and use it in GitHub Desktop.
Save JerryWorkman/31987605cd4958864dd5f159e26c0408 to your computer and use it in GitHub Desktop.
html / css / javascript code
<!DOCTYPE html>
<html lang="en">
<head>
<title>Home Assistant Google Guages using WebSockets</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<meta name="description" content="A web interface for Home Assistant with WebSocket and Google Guages">
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js'></script>
<script src='https://unpkg.com/home-assistant-js-websocket@0.4.1/dist/haws.umd.js'></script>
<style>
.flex-container {
padding: 0;
margin: 0;
list-style: none;
-ms-box-orient: horizontal;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
}
.wrap {
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
}
.flex-item {
padding: 0px;
width: 150px;
height: 150px;
margin: 5px;
line-height: 150px;
color: white;
font-weight: bold;
font-size: 2em;
text-align: center;
}
</style>
<script type="text/javascript">
///// Modify to suit your configeration /////
var URL = 'ws://' + window.location.hostname + ':8123/api/websocket';
var PASSWORD = 'XXXXXX'; //Only used if ther server requires authentication
function make_options(max) {
return {
width: 150, height: 150,
yellowFrom: 0.5*max, yellowTo: 0.75*max,
redFrom: 0.75*max, redTo: max,
minorTicks: 5,
max: max
};
}
var guages = {
"sensor.daily_power_cost":
{label: "$/Day", div: "guage0_div", max: 20},
"sensor.meter_avg_for_last_hour":
{label: "Avg/hr", div: "guage1_div", max: 12000},
"sensor.power_meter":
{label: "Meter", div: "guage2_div", max: 12000},
"sensor.humidifier":
{label: "Humidifier", div: "guage3_div", max: 3000},
"sensor.up_heat_pump":
{label: "Up HP", div: "guage4_div", max: 2000},
"sensor.down_air_handler":
{label: "Dn AH", div: "guage5_div", max: 260},
"sensor.down_heat_pump":
{label: "Dn HP", div: "guage6_div", max: 2700},
"sensor.line_voltage":
{label: "Volts", div: "guage7_div", max: 250},
"sensor.out_temperature":
{label: "Outside", div: "guage8_div", max: 140},
"sensor.up_temperature":
{label: "Up", div: "guage9_div", max: 140},
"sensor.fr_temperature":
{label: "FR", div: "guage10_div", max: 140},
"sensor.garage_temperature":
{label: "Garage", div: "guage11_div", max: 140},
"sensor.out_temperature_humidity":
{label: "Outside", div: "guage12_div", max: 100},
"sensor.up_temperature_humidity":
{label: "Up", div: "guage13_div", max: 100},
"sensor.fr_temperature_humidity":
{label: "FR", div: "guage14_div", max: 100},
"sensor.garage_temperature_humidity":
{label: "Garage", div: "guage15_div", max: 100}
};
function init() {
const status = document.getElementById('status');
google.charts.load('current', {'packages':['gauge']});
google.charts.setOnLoadCallback(drawChart);
function render(entities) {
//HAWS.getGroupEntities(entities, "group.Power" => console.log('Power Entities!', entities));
//HAWS.splitByGroups(entities => console.log('Group Entities!', entities));
var error = false;
_.forEach(guages, function(guage, key) {
try {
var svalue = entities[key].state;
if( svalue < 0 ) { svalue = 0; }
guage["data"].setValue(0, 1, svalue);
//guage["chart"].draw(guage["data"], guage["options"]);
guage["chart"].draw(guage["data"], make_options(guage["max"]));
} catch(e) {
// Uncomment to see all state read failures in console
// console.log("Error reading state for key: " + key);
status.innerHTML = "Error reading state for key: " + key;
error = true;
}
if(!error) status.innerHTML = "Updated: " + (new Date()).toLocaleString();
});
}
function getConfig(config) {
console.log(config);
}
function GetErrorCode(err) {
if(err == 1) return 'ERR_CANNOT_CONNECT';
if(err == 2) return 'ERR_INVALID_AUTH';
return 'UNKNOWN_ERROR';
}
function drawChart() {
_.forEach(guages, function(guage) {
guage.data = google.visualization.arrayToDataTable([['Label', 'Value'], [guage.label, -1]]);
guage.chart = new google.visualization.Gauge(document.getElementById(guage.div));
guage.chart.draw(guage.data, guage.options);
});
//add authentation with options parameter
var options = {authToken: PASSWORD};
HAWS.createConnection(URL, options).then(conn => {
status.innerHTML = 'Connected';
HAWS.subscribeConfig(conn, config => console.log('New config!', config));
HAWS.subscribeEntities(conn, render);
}, err => { status.innerHTML = "Connection error: " + GetErrorCode(err); });
}
}
</script>
</head>
<body onload="init();">
<h4><span id='status'>Connecting...</span></h4>
<h1>Power (watts)</h1>
<ul class="flex-container wrap">
<li class="flex-item" id='guage0_div'></li>
<li class="flex-item" id='guage1_div'></li>
<li class="flex-item" id='guage2_div'></li>
<li class="flex-item" id='guage3_div'></li>
<li class="flex-item" id='guage4_div'></li>
<li class="flex-item" id='guage5_div'></li>
<li class="flex-item" id='guage6_div'></li>
<li class="flex-item" id='guage7_div'></li>
</ul>
<h1>Temperature (&deg;F)</h1>
<ul class="flex-container wrap">
<li class="flex-item" id='guage8_div'></li>
<li class="flex-item" id='guage9_div'></li>
<li class="flex-item" id='guage10_div'></li>
<li class="flex-item" id='guage11_div'></li>
</ul>
<h1>Humidity(%)</h1>
<ul class="flex-container wrap">
<li class="flex-item" id='guage12_div'></li>
<li class="flex-item" id='guage13_div'></li>
<li class="flex-item" id='guage14_div'></li>
<li class="flex-item" id='guage15_div'></li>
<li class="flex-item" id='guage16_div'></li>
</ul>
</body>
</html>
@JerryWorkman
Copy link
Author

Add authentication, error messages, general code cleanup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment