From c05e5786de2e7602b3d7ebe8c0b863fae7682806 Mon Sep 17 00:00:00 2001 From: Stefan Bethke Date: Fri, 30 May 2025 14:19:17 +0200 Subject: [PATCH] Add connection and battery status --- hmdooris/ccujack.py | 22 ++++- hmdooris/static/icons.svg | 2 +- hmdooris/static/main.css | 27 +++++- hmdooris/static/main.js | 30 ++++-- hmdooris/static/style.css | 147 ----------------------------- hmdooris/templates/operate.html.j2 | 38 +++++++- 6 files changed, 101 insertions(+), 165 deletions(-) delete mode 100644 hmdooris/static/style.css diff --git a/hmdooris/ccujack.py b/hmdooris/ccujack.py index a1be509..7b2f125 100644 --- a/hmdooris/ccujack.py +++ b/hmdooris/ccujack.py @@ -1,6 +1,5 @@ import json import logging -import ssl from typing import List, Dict import requests @@ -17,11 +16,22 @@ class CCUJackHmIPDLD: self.name = name self.id = id self.value_list = self.get_value_list(id) + self.ops = { + 'low_battery': True, + 'unreachable': True, + 'voltage': -99, + } def status(self): r = self.ccu.get_json(f"/device/{self.id}/1/LOCK_STATE/~pv") 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]: """ 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 if certpath is True: urllib3.disable_warnings() - self.locks : Dict[str, CCUJackHmIPDLD] = {} + self.locks: Dict[str, CCUJackHmIPDLD] = {} self.get_all_locks() def get_json(self, url: str): @@ -61,6 +71,9 @@ class CCUJack: pass return {} + def get_value(self, url: str): + return self.get_json(url)["v"] + def put_json(self, url: str, data: dict): url = self.url + url r = requests.put(url, json=data, **self.kvargs) @@ -86,11 +99,12 @@ class CCUJack: s[lock.id] = { "name": lock.name, "id": lock.id, - "status": lock.status() + "status": lock.status(), + 'ops': lock.get_ops(), } 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) s = lock.status() if locked_state is None: diff --git a/hmdooris/static/icons.svg b/hmdooris/static/icons.svg index 82f472d..c50c94c 100644 --- a/hmdooris/static/icons.svg +++ b/hmdooris/static/icons.svg @@ -1 +1 @@ -arrow spin svgrepo commobile bolt svgrepo comunlock alt svgrepo comlock alt svgrepo com \ No newline at end of file +broken link svgrepo comarrow spin svgrepo commobile bolt svgrepo comunlock alt svgrepo comlock alt svgrepo com \ No newline at end of file diff --git a/hmdooris/static/main.css b/hmdooris/static/main.css index b7c98e1..f369439 100644 --- a/hmdooris/static/main.css +++ b/hmdooris/static/main.css @@ -6,6 +6,12 @@ body { font-family: Arial, Helvetica, sans-serif; } +@keyframes blink-animation { + to { + visibility: hidden; + } +} + #locks { width: 40em; } @@ -30,11 +36,16 @@ body { margin: 1em 0 0 0; } +.lock__line .lock__state-bat { + color: red; + animation: blink-animation 1s steps(5, start) infinite; +} + .lock__line button { min-width: 10em; margin: 0.1em 0.5em; padding: 0.1em 0.5em; - border-radius: 1em; + border-radius: 2em; background-color: white; color: black; } @@ -64,4 +75,18 @@ svg.icon { font-size: 0.7em; position: absolute; 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; } \ No newline at end of file diff --git a/hmdooris/static/main.js b/hmdooris/static/main.js index fd21872..b6b014c 100644 --- a/hmdooris/static/main.js +++ b/hmdooris/static/main.js @@ -1,16 +1,17 @@ (function () { let update_button = function (lock) { - let state_icon = document.getElementById(`lock__state-icon__${lock.id}`); - let state_label = document.getElementById(`lock__state-label__${lock.id}`); - let button_lock = document.getElementById(`lock__lock__${lock.id}`); - let button_unlock = document.getElementById(`lock__unlock__${lock.id}`); + let state_icon = document.querySelector(`#lock__line__${lock.id} .lock__state-icon`); + let state_label = document.querySelector(`#lock__line__${lock.id} .lock__state-label`); + let state_bat = document.querySelector(`#lock__line__${lock.id} .lock__state-bat`); + 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") { - state_icon.innerHTML = ''; + state_icon.innerHTML = ''; state_label.innerText = 'locked'; button_lock.disabled = true; button_unlock.disabled = false; } else if (lock.status === "UNLOCKED") { - state_icon.innerHTML = ''; + state_icon.innerHTML = ''; state_label.innerText = 'unlocked'; button_lock.disabled = false; button_unlock.disabled = true; @@ -20,6 +21,13 @@ button_lock.disabled = true; button_unlock.disabled = true; } + state_bat.innerHTML = ''; + if (lock.ops.low_battery) { + state_bat.innerHTML = state_bat.innerHTML + ''; + } + if (lock.ops.low_battery) { + state_bat.innerHTML = state_bat.innerHTML + ''; + } } let lock_button_add_event_handler = function (e, id, locking) { @@ -68,20 +76,24 @@ let lock_line = document.createElement("div"); lock_line.id = `lock__line__${lock.id}`; lock_line.classList.add("lock__line"); - lock_line.innerHTML = `
${lock.name}: 
`; + let lock_line_inner = `` + lock_line_inner += `${lock.name}: ` + lock_line_inner += `` + lock_line_inner += `` + lock_line.innerHTML = `
${lock_line_inner}
`; locks.appendChild(lock_line); let lock_button = document.createElement("button"); + lock_button.classList.add("lock__button__lock"); lock_button.name = lock.id; - lock_button.id = `lock__lock__${lock.id}`; lock_button.disabled = true; lock_button.innerText = "Lock"; lock_button_add_event_handler(lock_button, lock.id, true); lock_line.appendChild(lock_button); lock_button = document.createElement("button"); + lock_button.classList.add("lock__button__unlock"); lock_button.name = lock.id; - lock_button.id = `lock__unlock__${lock.id}`; lock_button.disabled = true; lock_button.innerText = "Unlock"; lock_button_add_event_handler(lock_button, lock.id, false); diff --git a/hmdooris/static/style.css b/hmdooris/static/style.css deleted file mode 100644 index 22f7088..0000000 --- a/hmdooris/static/style.css +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/hmdooris/templates/operate.html.j2 b/hmdooris/templates/operate.html.j2 index 4d3354d..31905c6 100644 --- a/hmdooris/templates/operate.html.j2 +++ b/hmdooris/templates/operate.html.j2 @@ -2,8 +2,40 @@ {% block page_title %}CCCHH Dooris{% endblock %} {% block page_body %}
-
-

Click the respective buttons to lock or unlock a door. If the status of a door is ”unknown”, you will need to - run the lock manually by pressing the lock or unlock button on the door lock.

+
+

Click the respective buttons to lock or unlock a door.

+
    +
  • + + + + The door is locked. +
  • +
  • + + + + The door is unlocked. +
  • +
  • + + + + 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. +
  • +
  • + + + + The battery is getting low. Please open the door motor and swap out the batteries. +
  • +
  • + + + + The lock is offline. Verify the lock batteries and the CCU radio configuration. +
  • +
{% endblock %}