<!doctype html> <html> <head> <meta charset="utf-8" /> <title>Tesla Charge Control</title> <link id="favicon" rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⏳</text></svg>"> <script type="text/javascript"> const api_url = window.location.protocol + "//" + window.location.hostname + ":" + window.location.port; refresh_interval = register(); refresh(); document.addEventListener("visibilitychange", () => { if (document.hidden) { clearInterval(refresh_interval); } else { refresh(); refresh_interval = register(); } }); function register() { return setInterval(refresh, 10000); } function flash() { fetch(api_url + "/flash", { method: "POST" }) .then((response) => console.log(response)); } function refresh() { let favicon = document.getElementById("favicon"); favicon.setAttribute("href", "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>" + "⏳" + "</text></svg>"); fetch(api_url + "/charge-state") .then((response) => response.json()) .then((json) => update_charge_state(json)); fetch(api_url + "/home").then((response) => response.json()).then((response) => update_home(response)); } function update_charge_state(charge_state) { let favicon = document.getElementById("favicon"); favicon.setAttribute("href", "data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>" + get_emoji(charge_state) + "</text></svg>"); var info_div = document.getElementById("info"); while (info_div.childElementCount > 0) { info_div.removeChild(info_div.firstChild) } var arr = ["Battery " + charge_state.battery_level + "%", "Range: " + (charge_state.battery_range * 1.60934).toFixed(1) + "km", "Charging at " + charge_state.charge_rate.toFixed(1) + " amps", "Charging until battery at " + charge_state.charge_limit_soc + "%", ]; for (line in arr) { el = document.createElement('p'); el.appendChild(document.createTextNode(arr[line])); info_div.appendChild(el) } el = document.createElement('p'); el.appendChild(document.createTextNode("Full charge state:")); state_json = document.createElement('pre'); state_json.appendChild(document.createTextNode(JSON.stringify(charge_state, null, '\t'))); el.appendChild(state_json); info_div.appendChild(el); } function update_home(response) { var info_div = document.getElementById("info"); el = document.createElement('p'); if (response) { el.appendChild(document.createTextNode("At home")); } else { el.appendChild(document.createTextNode("Not home")); } info_div.appendChild(el); } function get_emoji(charge_state) { if (charge_state.charge_rate > 0) { return "🔌"; } else if (charge_state.battery_level < 60) { return "🪫" } else return "🔋"; } </script> </head> <body></body> <div> <h2> <a href="/grafana">Grafana</a> </h2> </div> <button onclick="flash()">flash</button> <div id="info"></div> </html>