diff options
-rw-r--r-- | kvmd/apps/kvmd/ugpio.py | 60 | ||||
-rw-r--r-- | testenv/v2-hdmi-rpi4.override.yaml | 4 | ||||
-rw-r--r-- | web/share/js/kvm/gpio.js | 40 |
3 files changed, 75 insertions, 29 deletions
diff --git a/kvmd/apps/kvmd/ugpio.py b/kvmd/apps/kvmd/ugpio.py index cb328115..d4e9d0af 100644 --- a/kvmd/apps/kvmd/ugpio.py +++ b/kvmd/apps/kvmd/ugpio.py @@ -322,29 +322,51 @@ class UserGpio: items: List[Dict] = [] for item in map(str.strip, row): if item.startswith("#") or len(item) == 0: - items.append({ - "type": "label", - "text": item[1:].strip(), - }) + items.append(self.__make_view_label(item)) else: - parts = list(map(str.strip, item.split("|", 1))) + parts = list(map(str.strip, item.split("|", 2))) if parts: - channel: str = parts[0] - param: Optional[str] = (parts[1] if len(parts) > 1 else None) - if channel in self.__inputs: - items.append({ - "type": UserGpioModes.INPUT, - "channel": channel, - "color": (param if param in ["green", "yellow", "red"] else "green"), - }) - elif channel in self.__outputs: - items.append({ - "type": UserGpioModes.OUTPUT, - "channel": parts[0], - "text": (param if param is not None else "Click"), - }) + if parts[0] in self.__inputs: + items.append(self.__make_view_input(parts)) + elif parts[0] in self.__outputs: + items.append(self.__make_view_output(parts)) table.append(items) + return { "header": self.__view["header"], "table": table, } + + def __make_view_label(self, item: str) -> Dict: + assert item.startswith("#") + return { + "type": "label", + "text": item[1:].strip(), + } + + def __make_view_input(self, parts: List[str]) -> Dict: + assert len(parts) >= 1 + color = (parts[1] if len(parts) > 1 else None) + if color not in ["green", "yellow", "red"]: + color = "green" + return { + "type": UserGpioModes.INPUT, + "channel": parts[0], + "color": color, + } + + def __make_view_output(self, parts: List[str]) -> Dict: + assert len(parts) >= 1 + confirm = False + text = "Click" + if len(parts) == 2: + text = parts[1] + elif len(parts) == 3: + confirm = (parts[1] == "confirm") + text = parts[2] + return { + "type": UserGpioModes.OUTPUT, + "channel": parts[0], + "confirm": confirm, + "text": text, + } diff --git a/testenv/v2-hdmi-rpi4.override.yaml b/testenv/v2-hdmi-rpi4.override.yaml index a8f361b3..2d2bf678 100644 --- a/testenv/v2-hdmi-rpi4.override.yaml +++ b/testenv/v2-hdmi-rpi4.override.yaml @@ -84,11 +84,11 @@ kvmd: - ["#Generic GPIO leds"] - [] - ["#Test 1:", led1, button1] - - ["#Test 2:", led2, button2] + - ["#Test 2:", led2, button2|confirm|Click] - [] - ["#HID Relays /dev/hidraw0"] - [] - - ["#Relay #1:", "relay1|Boop 0.1"] + - ["#Relay #1:", "relay1|confirm|Boop 0.1"] - ["#Relay #2:", "relay2|Boop 2.0"] vnc: diff --git a/web/share/js/kvm/gpio.js b/web/share/js/kvm/gpio.js index e7b3c9e1..a67224b7 100644 --- a/web/share/js/kvm/gpio.js +++ b/web/share/js/kvm/gpio.js @@ -96,11 +96,11 @@ export function Gpio() { for (let channel in model.scheme.outputs) { let el = $(`gpio-switch-${channel}`); if (el) { - tools.setOnClick(el, () => __switchChannel(channel)); + tools.setOnClick(el, () => __switchChannel(el)); } el = $(`gpio-button-${channel}`); if (el) { - tools.setOnClick(el, () => __pulseChannel(channel)); + tools.setOnClick(el, () => __pulseChannel(el)); } } @@ -120,7 +120,8 @@ export function Gpio() { if (item.scheme["switch"]) { controls.push(` <td><div class="switch-box"> - <input disabled type="checkbox" id="gpio-switch-${item.channel}" class="gpio-switch" /> + <input disabled type="checkbox" id="gpio-switch-${item.channel}" class="gpio-switch" + data-channel="${item.channel}" data-confirm="${Number(item.confirm)}" /> <label for="gpio-switch-${item.channel}"> <span class="switch-inner"></span> <span class="switch"></span> @@ -129,7 +130,10 @@ export function Gpio() { `); } if (item.scheme.pulse.delay) { - controls.push(`<td><button disabled id="gpio-button-${item.channel}" class="gpio-button">${item.text}</button></td>`); + controls.push(` + <td><button disabled id="gpio-button-${item.channel}" class="gpio-button" + data-channel="${item.channel}" data-confirm="${Number(item.confirm)}">${item.text}</button></td> + `); } return `<table><tr>${controls.join("<td> </td>")}</tr></table>`; } else { @@ -148,13 +152,33 @@ export function Gpio() { } }; - var __switchChannel = function(channel) { + var __switchChannel = function(el) { + let channel = el.getAttribute("data-channel"); + let confirm = parseInt(el.getAttribute("data-confirm")); let to = ($(`gpio-switch-${channel}`).checked ? "1" : "0"); - __sendPost(`/api/gpio/switch?channel=${channel}&state=${to}`); + let act = () => __sendPost(`/api/gpio/switch?channel=${channel}&state=${to}`); + if (confirm) { + wm.confirm("Are you sure to act this switch?").then(function(ok) { + if (ok) { + act(); + } else { + self.setState(__state); // Switch back + } + }); + } else { + act(); + } }; - var __pulseChannel = function(channel) { - __sendPost(`/api/gpio/pulse?channel=${channel}`); + var __pulseChannel = function(el) { + let channel = el.getAttribute("data-channel"); + let confirm = parseInt(el.getAttribute("data-confirm")); + let act = () => __sendPost(`/api/gpio/pulse?channel=${channel}`); + if (confirm) { + wm.confirm("Are you sure to click this button?").then(function(ok) { if (ok) act(); }); + } else { + act(); + } }; var __sendPost = function(url) { |