Add connection and battery status
All checks were successful
docker-image / docker (push) Successful in 1m17s
All checks were successful
docker-image / docker (push) Successful in 1m17s
This commit is contained in:
parent
3a2d1869c0
commit
c05e5786de
6 changed files with 101 additions and 165 deletions
|
@ -1,6 +1,5 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import ssl
|
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
@ -17,11 +16,22 @@ class CCUJackHmIPDLD:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.id = id
|
self.id = id
|
||||||
self.value_list = self.get_value_list(id)
|
self.value_list = self.get_value_list(id)
|
||||||
|
self.ops = {
|
||||||
|
'low_battery': True,
|
||||||
|
'unreachable': True,
|
||||||
|
'voltage': -99,
|
||||||
|
}
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
r = self.ccu.get_json(f"/device/{self.id}/1/LOCK_STATE/~pv")
|
r = self.ccu.get_json(f"/device/{self.id}/1/LOCK_STATE/~pv")
|
||||||
return self.value_list[r["v"]]
|
return self.value_list[r["v"]]
|
||||||
|
|
||||||
|
def get_ops(self):
|
||||||
|
self.ops['low_battery'] = self.ccu.get_value(f"/device/{self.id}/0/LOW_BAT/~pv")
|
||||||
|
self.ops['unreachable'] = self.ccu.get_value(f"/device/{self.id}/0/UNREACH/~pv")
|
||||||
|
self.ops['voltage'] = self.ccu.get_value(f"/device/{self.id}/0/OPERATING_VOLTAGE/~pv")
|
||||||
|
return self.ops
|
||||||
|
|
||||||
def get_value_list(self, id) -> List[str]:
|
def get_value_list(self, id) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Uses the fist lock to obtain the valueList property that maps the enum values to strings
|
Uses the fist lock to obtain the valueList property that maps the enum values to strings
|
||||||
|
@ -47,7 +57,7 @@ class CCUJack:
|
||||||
self.kvargs['verify'] = certpath
|
self.kvargs['verify'] = certpath
|
||||||
if certpath is True:
|
if certpath is True:
|
||||||
urllib3.disable_warnings()
|
urllib3.disable_warnings()
|
||||||
self.locks : Dict[str, CCUJackHmIPDLD] = {}
|
self.locks: Dict[str, CCUJackHmIPDLD] = {}
|
||||||
self.get_all_locks()
|
self.get_all_locks()
|
||||||
|
|
||||||
def get_json(self, url: str):
|
def get_json(self, url: str):
|
||||||
|
@ -61,6 +71,9 @@ class CCUJack:
|
||||||
pass
|
pass
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
def get_value(self, url: str):
|
||||||
|
return self.get_json(url)["v"]
|
||||||
|
|
||||||
def put_json(self, url: str, data: dict):
|
def put_json(self, url: str, data: dict):
|
||||||
url = self.url + url
|
url = self.url + url
|
||||||
r = requests.put(url, json=data, **self.kvargs)
|
r = requests.put(url, json=data, **self.kvargs)
|
||||||
|
@ -86,11 +99,12 @@ class CCUJack:
|
||||||
s[lock.id] = {
|
s[lock.id] = {
|
||||||
"name": lock.name,
|
"name": lock.name,
|
||||||
"id": lock.id,
|
"id": lock.id,
|
||||||
"status": lock.status()
|
"status": lock.status(),
|
||||||
|
'ops': lock.get_ops(),
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def lock_unlock(self, lock_id, locked_state = None):
|
def lock_unlock(self, lock_id, locked_state=None):
|
||||||
lock = self.locks.get(lock_id)
|
lock = self.locks.get(lock_id)
|
||||||
s = lock.status()
|
s = lock.status()
|
||||||
if locked_state is None:
|
if locked_state is None:
|
||||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 5.1 KiB |
|
@ -6,6 +6,12 @@ body {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes blink-animation {
|
||||||
|
to {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#locks {
|
#locks {
|
||||||
width: 40em;
|
width: 40em;
|
||||||
}
|
}
|
||||||
|
@ -30,11 +36,16 @@ body {
|
||||||
margin: 1em 0 0 0;
|
margin: 1em 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.lock__line .lock__state-bat {
|
||||||
|
color: red;
|
||||||
|
animation: blink-animation 1s steps(5, start) infinite;
|
||||||
|
}
|
||||||
|
|
||||||
.lock__line button {
|
.lock__line button {
|
||||||
min-width: 10em;
|
min-width: 10em;
|
||||||
margin: 0.1em 0.5em;
|
margin: 0.1em 0.5em;
|
||||||
padding: 0.1em 0.5em;
|
padding: 0.1em 0.5em;
|
||||||
border-radius: 1em;
|
border-radius: 2em;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
color: black;
|
color: black;
|
||||||
}
|
}
|
||||||
|
@ -64,4 +75,18 @@ svg.icon {
|
||||||
font-size: 0.7em;
|
font-size: 0.7em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend {
|
||||||
|
width: 40em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend__icons {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: calc(32px + 0.3em);
|
||||||
|
text-indent: calc(-32px - 0.3em);
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend__icons .icon {
|
||||||
|
color: black;
|
||||||
}
|
}
|
|
@ -1,16 +1,17 @@
|
||||||
(function () {
|
(function () {
|
||||||
let update_button = function (lock) {
|
let update_button = function (lock) {
|
||||||
let state_icon = document.getElementById(`lock__state-icon__${lock.id}`);
|
let state_icon = document.querySelector(`#lock__line__${lock.id} .lock__state-icon`);
|
||||||
let state_label = document.getElementById(`lock__state-label__${lock.id}`);
|
let state_label = document.querySelector(`#lock__line__${lock.id} .lock__state-label`);
|
||||||
let button_lock = document.getElementById(`lock__lock__${lock.id}`);
|
let state_bat = document.querySelector(`#lock__line__${lock.id} .lock__state-bat`);
|
||||||
let button_unlock = document.getElementById(`lock__unlock__${lock.id}`);
|
let button_lock = document.querySelector(`#lock__line__${lock.id} .lock__button__lock`);
|
||||||
|
let button_unlock = document.querySelector(`#lock__line__${lock.id} .lock__button__unlock`);
|
||||||
if (lock.status === "LOCKED") {
|
if (lock.status === "LOCKED") {
|
||||||
state_icon.innerHTML = '<svg class="icon"><use href="static/icon-lock-alt-svgrepo-com"/></svg>';
|
state_icon.innerHTML = '<svg class="icon"><use href="static/icons.svg#icon-lock-alt-svgrepo-com"/></svg>';
|
||||||
state_label.innerText = 'locked';
|
state_label.innerText = 'locked';
|
||||||
button_lock.disabled = true;
|
button_lock.disabled = true;
|
||||||
button_unlock.disabled = false;
|
button_unlock.disabled = false;
|
||||||
} else if (lock.status === "UNLOCKED") {
|
} else if (lock.status === "UNLOCKED") {
|
||||||
state_icon.innerHTML = '<svg class="icon"><use href="static/icon-unlock-alt-svgrepo-com"/></svg>';
|
state_icon.innerHTML = '<svg class="icon"><use href="static/icons.svg#icon-unlock-alt-svgrepo-com"/></svg>';
|
||||||
state_label.innerText = 'unlocked';
|
state_label.innerText = 'unlocked';
|
||||||
button_lock.disabled = false;
|
button_lock.disabled = false;
|
||||||
button_unlock.disabled = true;
|
button_unlock.disabled = true;
|
||||||
|
@ -20,6 +21,13 @@
|
||||||
button_lock.disabled = true;
|
button_lock.disabled = true;
|
||||||
button_unlock.disabled = true;
|
button_unlock.disabled = true;
|
||||||
}
|
}
|
||||||
|
state_bat.innerHTML = '';
|
||||||
|
if (lock.ops.low_battery) {
|
||||||
|
state_bat.innerHTML = state_bat.innerHTML + '<svg class="icon"><use href="static/icons.svg#icon-mobile-bolt-svgrepo-com"/></svg>';
|
||||||
|
}
|
||||||
|
if (lock.ops.low_battery) {
|
||||||
|
state_bat.innerHTML = state_bat.innerHTML + '<svg class="icon"><use href="static/icons.svg#icon-broken-link-svgrepo-com"/></svg>';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let lock_button_add_event_handler = function (e, id, locking) {
|
let lock_button_add_event_handler = function (e, id, locking) {
|
||||||
|
@ -68,20 +76,24 @@
|
||||||
let lock_line = document.createElement("div");
|
let lock_line = document.createElement("div");
|
||||||
lock_line.id = `lock__line__${lock.id}`;
|
lock_line.id = `lock__line__${lock.id}`;
|
||||||
lock_line.classList.add("lock__line");
|
lock_line.classList.add("lock__line");
|
||||||
lock_line.innerHTML = `<div class="lock__state-and-label"><span id="lock__state-icon__${lock.id}" class="lock__state-icon"></span><span class="lock__name">${lock.name}: </span><span id="lock__state-label__${lock.id}" class="lock__state-label"></span></div>`;
|
let lock_line_inner = `<span class="lock__state-icon"></span>`
|
||||||
|
lock_line_inner += `<span class="lock__name">${lock.name}: </span>`
|
||||||
|
lock_line_inner += `<span class="lock__state-label"></span>`
|
||||||
|
lock_line_inner += `<span class="lock__state-bat"></span>`
|
||||||
|
lock_line.innerHTML = `<div class="lock__state-and-label">${lock_line_inner}</div>`;
|
||||||
locks.appendChild(lock_line);
|
locks.appendChild(lock_line);
|
||||||
|
|
||||||
let lock_button = document.createElement("button");
|
let lock_button = document.createElement("button");
|
||||||
|
lock_button.classList.add("lock__button__lock");
|
||||||
lock_button.name = lock.id;
|
lock_button.name = lock.id;
|
||||||
lock_button.id = `lock__lock__${lock.id}`;
|
|
||||||
lock_button.disabled = true;
|
lock_button.disabled = true;
|
||||||
lock_button.innerText = "Lock";
|
lock_button.innerText = "Lock";
|
||||||
lock_button_add_event_handler(lock_button, lock.id, true);
|
lock_button_add_event_handler(lock_button, lock.id, true);
|
||||||
lock_line.appendChild(lock_button);
|
lock_line.appendChild(lock_button);
|
||||||
|
|
||||||
lock_button = document.createElement("button");
|
lock_button = document.createElement("button");
|
||||||
|
lock_button.classList.add("lock__button__unlock");
|
||||||
lock_button.name = lock.id;
|
lock_button.name = lock.id;
|
||||||
lock_button.id = `lock__unlock__${lock.id}`;
|
|
||||||
lock_button.disabled = true;
|
lock_button.disabled = true;
|
||||||
lock_button.innerText = "Unlock";
|
lock_button.innerText = "Unlock";
|
||||||
lock_button_add_event_handler(lock_button, lock.id, false);
|
lock_button_add_event_handler(lock_button, lock.id, false);
|
||||||
|
|
|
@ -1,147 +0,0 @@
|
||||||
/* Generated using nucleoapp.com */
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
General
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--icon-color-primary: inherit;
|
|
||||||
--icon-color-secondary: currentColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon {
|
|
||||||
display: inline-block;
|
|
||||||
color: var(--icon-color-primary); /* icon primary color */
|
|
||||||
height: 1em;
|
|
||||||
width: 1em;
|
|
||||||
line-height: 1;
|
|
||||||
flex-shrink: 0;
|
|
||||||
max-width: initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon use {
|
|
||||||
/* icon secondary color */
|
|
||||||
fill: var(--icon-color-secondary);
|
|
||||||
stroke: var(--icon-color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
Themes
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
.icon-theme-1 {
|
|
||||||
--icon-color-primary: #212121;
|
|
||||||
--icon-color-secondary: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
Sizes
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
:root {
|
|
||||||
--icon-sm: 0.8em;
|
|
||||||
--icon-lg: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* relative units */
|
|
||||||
.icon-sm {
|
|
||||||
font-size: var(--icon-sm);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-lg {
|
|
||||||
font-size: var(--icon-lg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* absolute units */
|
|
||||||
.icon-16 {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-32 {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
Stroke
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
.stroke-1 {
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-2 {
|
|
||||||
stroke-width: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-3 {
|
|
||||||
stroke-width: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-4 {
|
|
||||||
stroke-width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
Caps/Corners
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
.icon use {
|
|
||||||
--icon-stroke-linecap-butt: butt;
|
|
||||||
stroke-miterlimit: 10;
|
|
||||||
stroke-linecap: square;
|
|
||||||
stroke-linejoin: miter;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stroke-round use {
|
|
||||||
--icon-stroke-linecap-butt: round;
|
|
||||||
stroke-linecap: round;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------
|
|
||||||
|
|
||||||
Transformations/Animations
|
|
||||||
|
|
||||||
-------------------------------- */
|
|
||||||
|
|
||||||
.icon-rotate-90 {
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-rotate-180 {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-rotate-270 {
|
|
||||||
transform: rotate(270deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-flip-y {
|
|
||||||
transform: scaleY(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-flip-x {
|
|
||||||
transform: scaleX(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-is-spinning {
|
|
||||||
animation: icon-spin 1s infinite linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes icon-spin {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,40 @@
|
||||||
{% block page_title %}CCCHH Dooris{% endblock %}
|
{% block page_title %}CCCHH Dooris{% endblock %}
|
||||||
{% block page_body %}
|
{% block page_body %}
|
||||||
<div id="locks"></div>
|
<div id="locks"></div>
|
||||||
<div>
|
<div class="legend">
|
||||||
<p>Click the respective buttons to lock or unlock a door. If the status of a door is ”unknown”, you will need to
|
<p>Click the respective buttons to lock or unlock a door.</p>
|
||||||
run the lock manually by pressing the lock or unlock button on the door lock.</p>
|
<ul class="legend__icons">
|
||||||
|
<li>
|
||||||
|
<svg class="icon">
|
||||||
|
<use href="static/icons.svg#icon-lock-alt-svgrepo-com"/>
|
||||||
|
</svg>
|
||||||
|
The door is locked.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<svg class="icon">
|
||||||
|
<use href="static/icons.svg#icon-unlock-alt-svgrepo-com"/>
|
||||||
|
</svg>
|
||||||
|
The door is unlocked.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<svg class="icon">
|
||||||
|
<use href="static/icons.svg#icon-arrow-spin-svgrepo-com"/>
|
||||||
|
</svg>
|
||||||
|
The lock status is moving or unknown. If the status does not change within 30 seconds, you will need to
|
||||||
|
run the lock manually by pressing the lock or unlock button on the door lock.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<svg class="icon">
|
||||||
|
<use href="static/icons.svg#icon-mobile-bolt-svgrepo-com"/>
|
||||||
|
</svg>
|
||||||
|
The battery is getting low. Please open the door motor and swap out the batteries.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<svg class="icon">
|
||||||
|
<use href="static/icons.svg#icon-broken-link-svgrepo-com"/>
|
||||||
|
</svg>
|
||||||
|
The lock is offline. Verify the lock batteries and the CCU radio configuration.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue