rawhide kobayashi f548353fa6
some power control buttons implemented
seven-segment post codes added to webui
other optimizations
2025-03-04 15:58:47 -06:00

473 lines
8.3 KiB
Python

from enum import IntEnum
from os import name
import serial
from ipkvm import profile
import threading
from queue import Queue
import json
import time
from ipkvm import ui
from collections.abc import Mapping
# python can't use NUMBERS as enum keys?!
POSTHex7Segment = {
0: "00",
1: "01",
2: "02",
3: "03",
4: "04",
5: "05",
6: "06",
7: "07",
8: "08",
9: "09",
10: "0A",
11: "0b",
12: "0C",
13: "0d",
14: "0E",
15: "0F",
16: "10",
17: "11",
18: "12",
19: "13",
20: "14",
21: "15",
22: "16",
23: "17",
24: "18",
25: "19",
26: "1A",
27: "1b",
28: "1C",
29: "1d",
30: "1E",
31: "1F",
32: "20",
33: "21",
34: "22",
35: "23",
36: "24",
37: "25",
38: "26",
39: "27",
40: "28",
41: "29",
42: "2A",
43: "2b",
44: "2C",
45: "2d",
46: "2E",
47: "2F",
48: "30",
49: "31",
50: "32",
51: "33",
52: "34",
53: "35",
54: "36",
55: "37",
56: "38",
57: "39",
58: "3A",
59: "3b",
60: "3C",
61: "3d",
62: "3E",
63: "3F",
64: "40",
65: "41",
66: "42",
67: "43",
68: "44",
69: "45",
70: "46",
71: "47",
72: "48",
73: "49",
74: "4A",
75: "4b",
76: "4C",
77: "4d",
78: "4E",
79: "4F",
80: "50",
81: "51",
82: "52",
83: "53",
84: "54",
85: "55",
86: "56",
87: "57",
88: "58",
89: "59",
90: "5A",
91: "5b",
92: "5C",
93: "5d",
94: "5E",
95: "5F",
96: "60",
97: "61",
98: "62",
99: "63",
100: "64",
101: "65",
102: "66",
103: "67",
104: "68",
105: "69",
106: "6A",
107: "6b",
108: "6C",
109: "6d",
110: "6E",
111: "6F",
112: "70",
113: "71",
114: "72",
115: "73",
116: "74",
117: "75",
118: "76",
119: "77",
120: "78",
121: "79",
122: "7A",
123: "7b",
124: "7C",
125: "7d",
126: "7E",
127: "7F",
128: "80",
129: "81",
130: "82",
131: "83",
132: "84",
133: "85",
134: "86",
135: "87",
136: "88",
137: "89",
138: "8A",
139: "8b",
140: "8C",
141: "8d",
142: "8E",
143: "8F",
144: "90",
145: "91",
146: "92",
147: "93",
148: "94",
149: "95",
150: "96",
151: "97",
152: "98",
153: "99",
154: "9A",
155: "9b",
156: "9C",
157: "9d",
158: "9E",
159: "9F",
160: "A0",
161: "A1",
162: "A2",
163: "A3",
164: "A4",
165: "A5",
166: "A6",
167: "A7",
168: "A8",
169: "A9",
170: "AA",
171: "Ab",
172: "AC",
173: "Ad",
174: "AE",
175: "AF",
176: "b0",
177: "b1",
178: "b2",
179: "b3",
180: "b4",
181: "b5",
182: "b6",
183: "b7",
184: "b8",
185: "b9",
186: "bA",
187: "bb",
188: "bC",
189: "bd",
190: "bE",
191: "bF",
192: "C0",
193: "C1",
194: "C2",
195: "C3",
196: "C4",
197: "C5",
198: "C6",
199: "C7",
200: "C8",
201: "C9",
202: "CA",
203: "Cb",
204: "CC",
205: "Cd",
206: "CE",
207: "CF",
208: "d0",
209: "d1",
210: "d2",
211: "d3",
212: "d4",
213: "d5",
214: "d6",
215: "d7",
216: "d8",
217: "d9",
218: "dA",
219: "db",
220: "dC",
221: "dd",
222: "dE",
223: "dF",
224: "E0",
225: "E1",
226: "E2",
227: "E3",
228: "E4",
229: "E5",
230: "E6",
231: "E7",
232: "E8",
233: "E9",
234: "EA",
235: "Eb",
236: "EC",
237: "Ed",
238: "EE",
239: "EF",
240: "F0",
241: "F1",
242: "F2",
243: "F3",
244: "F4",
245: "F5",
246: "F6",
247: "F7",
248: "F8",
249: "F9",
250: "FA",
251: "Fb",
252: "FC",
253: "Fd",
254: "FE",
255: "FF"
}
HIDMouseScanCodes = {
0: 1,
2: 2,
1: 4,
3: 8,
4: 16
}
class GPIO(IntEnum):
LOW = 0
HIGH = 1
# God Bless CHADGPT
class HIDKeyCode(IntEnum):
"""
Enum that translates modern JS key.code andvalues to HID scancodes.
"""
# Letter keys (A-Z)
KeyA = 4
KeyB = 5
KeyC = 6
KeyD = 7
KeyE = 8
KeyF = 9
KeyG = 10
KeyH = 11
KeyI = 12
KeyJ = 13
KeyK = 14
KeyL = 15
KeyM = 16
KeyN = 17
KeyO = 18
KeyP = 19
KeyQ = 20
KeyR = 21
KeyS = 22
KeyT = 23
KeyU = 24
KeyV = 25
KeyW = 26
KeyX = 27
KeyY = 28
KeyZ = 29
# Number keys (top row)
Digit1 = 30
Digit2 = 31
Digit3 = 32
Digit4 = 33
Digit5 = 34
Digit6 = 35
Digit7 = 36
Digit8 = 37
Digit9 = 38
Digit0 = 39
# Control keys
Enter = 40
Escape = 41
Backspace = 42
Tab = 43
Space = 44
Minus = 45
Equal = 46
BracketLeft = 47
BracketRight = 48
Backslash = 49
# Punctuation keys
Semicolon = 51
Quote = 52
Backquote = 53
Comma = 54
Period = 55
Slash = 56
CapsLock = 57
# Function keys (F1-F12)
F1 = 58
F2 = 59
F3 = 60
F4 = 61
F5 = 62
F6 = 63
F7 = 64
F8 = 65
F9 = 66
F10 = 67
F11 = 68
F12 = 69
PrintScreen = 70
ScrollLock = 71
Pause = 72
Insert = 73
Home = 74
PageUp = 75
Delete = 76
End = 77
PageDown = 78
ArrowRight = 79
ArrowLeft = 80
ArrowDown = 81
ArrowUp = 82
# Numpad keys
NumLock = 83
NumpadDivide = 84
NumpadMultiply = 85
NumpadSubtract = 86
NumpadAdd = 87
NumpadEnter = 88
Numpad1 = 89
Numpad2 = 90
Numpad3 = 91
Numpad4 = 92
Numpad5 = 93
Numpad6 = 94
Numpad7 = 95
Numpad8 = 96
Numpad9 = 97
Numpad0 = 98
NumpadDecimal = 99
# Additional keys
IntlBackslash = 100
ContextMenu = 101
Power = 102
# Modifier keys
ControlLeft = 224
ShiftLeft = 225
AltLeft = 226
MetaLeft = 227 # Windows / Command key (left)
ControlRight = 228
ShiftRight = 229
AltRight = 230
MetaRight = 231 # Windows / Command key (right)
class Esp32Serial(threading.Thread):
def __init__(self):
super().__init__()
self.post_code_queue: Queue[str] = Queue()
self.mkb_queue: Queue[Mapping[str, int | str | Mapping[str, int]]] = Queue()
self.change_serial_device = threading.Event()
self.device = self.get_device()
self.bios_timer = time.time()
self.power_status = None
self.start()
def run(self):
with self.device as ser:
while True:
# if self.change_serial_device.is_set():
# self.change_serial_device.clear()
# self.device = self.get_device()
while not self.mkb_queue.empty():
msg = self.mkb_queue.get()
ser.write(json.dumps(msg).encode())
while ser.in_waiting > 0:
try:
line = json.loads(ser.readline().decode().strip())
if "pwr" in line:
self.power_status = line["pwr"]
elif "post_code" in line:
# This code is what presents when you are in BIOS, but also... Other times.
# In another part of the script, we'll check to see if it's hung around for a few
# seconds. If so, we are in BIOS.
if POSTHex7Segment[line["post_code"]] != "Ab":
self.bios_timer = time.time()
ui.emit("update_seven_segment", POSTHex7Segment[line["post_code"]])
except json.JSONDecodeError:
continue
except UnicodeDecodeError:
continue
# self.post_code_queue.put(ser.read().hex())
time.sleep(0.01)
def get_device(self):
if name == "posix":
return serial.Serial(f"/dev/serial/by-id/{profile["esp32_serial"]}", 115200, bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE)
else:
raise RuntimeError("Your OS is unsupported!")