Skip to content

Commit 34ba93f

Browse files
authored
Smarter shutters detection (#297)
1 parent 99d8390 commit 34ba93f

File tree

13 files changed

+112
-32
lines changed

13 files changed

+112
-32
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ celerybeat-schedule
100100
.idea/
101101

102102
tdm.cfg
103+
tdm.ini
103104
devices.cfg
105+
devices.ini
104106
tdm*.log
105107
__version__.py

tdmgr/GUI/console.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,9 @@ def __init__(self, devices):
250250
self.lwCommands = QListWidget()
251251

252252
vl.addElements(
253-
gbxDevice, self.lwCommands, QLabel("Double-click a command to use it, ESC to close.")
253+
gbxDevice,
254+
self.lwCommands,
255+
QLabel("Double-click a command to use it, ESC to close."),
254256
)
255257
self.setLayout(vl)
256258

tdmgr/GUI/delegates/devices.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,12 @@ def sizeHint(self, option, index):
296296
return QStyledItemDelegate().sizeHint(option, index)
297297

298298
def get_used_width(self, option, index) -> int:
299-
return sum([self.get_devicename_width(option, index), self.get_alerts_width(option, index)])
299+
return sum(
300+
[
301+
self.get_devicename_width(option, index),
302+
self.get_alerts_width(option, index),
303+
]
304+
)
300305

301306
@staticmethod
302307
def get_devicename_width(option, index) -> int:
@@ -356,7 +361,10 @@ def paint(self, p: QPainter, option: QStyleOptionViewItem, index):
356361
alerts_width = self.get_alerts_width(option, index)
357362

358363
exc_rect = QRect(
359-
self.get_devicename_width(option, index), y, alerts_width, RECT_SIZE.height()
364+
self.get_devicename_width(option, index),
365+
y,
366+
alerts_width,
367+
RECT_SIZE.height(),
360368
)
361369

362370
if selected:

tdmgr/GUI/devices.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,10 @@ def create_actions(self):
176176
self.ctx_menu.addAction(QIcon(":/delete.png"), "Delete", self.ctx_menu_delete_device)
177177

178178
self.agAllPower = QActionGroup(self)
179-
for label, shortcut, fill in [("ON", "Ctrl+F1", True), ("OFF", "Ctrl+F2", False)]:
179+
for label, shortcut, fill in [
180+
("ON", "Ctrl+F1", True),
181+
("OFF", "Ctrl+F2", False),
182+
]:
180183
px = make_relay_pixmap(label, filled=fill)
181184
act = self.agAllPower.addAction(QIcon(px), f"All relays {label}")
182185
act.setShortcut(shortcut)
@@ -278,7 +281,11 @@ def ctx_menu_restart(self):
278281
def ctx_menu_reset(self):
279282
if self.device:
280283
reset, ok = QInputDialog.getItem(
281-
self, "Reset device and restart", "Select reset mode", resets, editable=False
284+
self,
285+
"Reset device and restart",
286+
"Select reset mode",
287+
resets,
288+
editable=False,
282289
)
283290
if ok:
284291
self.mqtt.publish(self.device.cmnd_topic("reset"), payload=reset.split(":")[0])
@@ -366,7 +373,7 @@ def select_device(self, idx):
366373
self.actColor.setEnabled(False)
367374
self.actChannels.setEnabled(False)
368375
if color := self.device.color():
369-
self.actColor.setEnabled(bool(color.hsbcolor and color.SO68 == 1))
376+
self.actColor.setEnabled(bool(color.hsbcolor) and color.SO68 == 0)
370377
self.actChannels.setEnabled(True)
371378

372379
self.actChannels.menu().clear()

tdmgr/GUI/dialogs/main.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import logging
33
import re
44

5+
from paho.mqtt import MQTTException
56
from PyQt5.QtCore import QDir, QFileInfo, QSettings, QSize, Qt, QTimer, QUrl, pyqtSlot
67
from PyQt5.QtGui import QDesktopServices, QFont, QIcon
78
from PyQt5.QtWidgets import (
@@ -15,7 +16,6 @@
1516
QPushButton,
1617
QStatusBar,
1718
)
18-
from paho.mqtt import MQTTException
1919

2020
from tdmgr.GUI.console import ConsoleWidget
2121
from tdmgr.GUI.devices import DevicesListWidget
@@ -63,9 +63,13 @@ def __init__(
6363

6464
self.menuBar().setNativeMenuBar(False)
6565

66+
self.mqtt = None
67+
self.setup_mqtt()
68+
6669
self.unknown = []
6770
self.custom_patterns = []
6871
self.env = TasmotaEnvironment()
72+
self.env.mqtt = self.mqtt
6973
self.device = None
7074

7175
self.topics = []
@@ -88,8 +92,7 @@ def __init__(
8892
)
8993
device.debug = self.devices.value("debug", False, bool)
9094
device.p["Mac"] = mac.replace("-", ":")
91-
device.env = self.env
92-
self.env.devices.append(device)
95+
self.env.add_device(device)
9396

9497
# load device command history
9598
self.devices.beginGroup("history")
@@ -101,7 +104,6 @@ def __init__(
101104

102105
self.device_model = TasmotaDevicesModel(self.settings, self.devices, self.env)
103106

104-
self.setup_mqtt()
105107
self.setup_main_layout()
106108
self.add_devices_tab()
107109
self.build_mainmenu()
@@ -186,7 +188,9 @@ def build_mainmenu(self):
186188

187189
def build_toolbars(self):
188190
main_toolbar = Toolbar(
189-
orientation=Qt.Horizontal, iconsize=24, label_position=Qt.ToolButtonTextBesideIcon
191+
orientation=Qt.Horizontal,
192+
iconsize=24,
193+
label_position=Qt.ToolButtonTextBesideIcon,
190194
)
191195
main_toolbar.setObjectName("main_toolbar")
192196

@@ -304,7 +308,8 @@ def mqtt_subscribe(self):
304308
# the custom patterns
305309
for custom_pattern in self.custom_patterns:
306310
custom_pattern_match = re.match(
307-
custom_pattern.replace("+", f"({MQTT_PATH_REGEX})"), d.p["FullTopic"]
311+
custom_pattern.replace("+", f"({MQTT_PATH_REGEX})"),
312+
d.p["FullTopic"],
308313
)
309314
if not d.is_default() and not custom_pattern_match:
310315
# if pattern is not found then add the device topics to subscription list.
@@ -428,7 +433,7 @@ def mqtt_message(self, msg: Message):
428433
elif msg.endpoint in ("RESULT", "FULLTOPIC"):
429434
# reply from an unknown device
430435
if d := lwt_discovery_stage2(self.env, msg):
431-
self.env.devices.append(d)
436+
self.env.add_device(d)
432437
self.device_model.addDevice(d)
433438
log.debug("DISCOVERY: Sending initial query to topic %s", d.p["Topic"])
434439
self.initial_query(d, True)
@@ -438,7 +443,10 @@ def mqtt_message(self, msg: Message):
438443

439444
def export(self):
440445
fname, _ = QFileDialog.getSaveFileName(
441-
self, "Export device list as...", directory=QDir.homePath(), filter="CSV files (*.csv)"
446+
self,
447+
"Export device list as...",
448+
directory=QDir.homePath(),
449+
filter="CSV files (*.csv)",
442450
)
443451
if fname:
444452
if not fname.endswith(".csv"):
@@ -564,7 +572,9 @@ def openTelemetry(self):
564572
self.mqtt_publish(self.device.cmnd_topic("STATUS"), "8")
565573
self.tele_docks.append(tele_widget)
566574
self.resizeDocks(
567-
self.tele_docks, [100 // len(self.tele_docks) for _ in self.tele_docks], Qt.Vertical
575+
self.tele_docks,
576+
[100 // len(self.tele_docks) for _ in self.tele_docks],
577+
Qt.Vertical,
568578
)
569579

570580
@pyqtSlot()
@@ -577,7 +587,9 @@ def openConsole(self):
577587
console_widget.command.setFocus()
578588
self.consoles.append(console_widget)
579589
self.resizeDocks(
580-
self.consoles, [100 // len(self.consoles) for _ in self.consoles], Qt.Horizontal
590+
self.consoles,
591+
[100 // len(self.consoles) for _ in self.consoles],
592+
Qt.Horizontal,
581593
)
582594

583595
@pyqtSlot()

tdmgr/GUI/dialogs/timers.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,12 @@ def __init__(self, device, *args, **kwargs):
103103
hl_tmr_time.addElements(self.cbxTimerPM, self.teTimerTime, lbWnd, self.cbxTimerWnd)
104104

105105
self.gbTimers.addElements(
106-
self.cbTimer, hl_tmr_arm_rpt, hl_tmr_out_act, gbTimerMode, hl_tmr_time, hl_tmr_days
106+
self.cbTimer,
107+
hl_tmr_arm_rpt,
108+
hl_tmr_out_act,
109+
gbTimerMode,
110+
hl_tmr_time,
111+
hl_tmr_days,
107112
)
108113

109114
btns = QDialogButtonBox(QDialogButtonBox.Save | QDialogButtonBox.Close)
@@ -159,7 +164,11 @@ def loadTimer(self, timer=""):
159164

160165
def describeTimer(self):
161166
if self.cbTimerArm.isChecked():
162-
desc = {"days": "", "repeat": "", "timer": self.cbTimer.currentText().upper()}
167+
desc = {
168+
"days": "",
169+
"repeat": "",
170+
"timer": self.cbTimer.currentText().upper(),
171+
}
163172
repeat = self.cbTimerRpt.isChecked()
164173
out = self.cbxTimerOut.currentText()
165174
act = self.cbxTimerAction.currentText()

tdmgr/GUI/rules.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,10 @@ def load_rule_from_file(self):
163163
def save_to_file(self):
164164
new_fname = f"{self.device.name} {self.cbRule.currentText()}.txt"
165165
file, ok = QFileDialog.getSaveFileName(
166-
self, "Save rule", os.path.join(QDir.homePath(), new_fname), "Text files | *.txt"
166+
self,
167+
"Save rule",
168+
os.path.join(QDir.homePath(), new_fname),
169+
"Text files | *.txt",
167170
)
168171
if ok:
169172
with open(file, "w") as f:
@@ -262,7 +265,11 @@ def display_rule(self, payload, rule):
262265
self.actStopOnError.setChecked(payload["StopOnError"] == "ON")
263266

264267
def unfold_rule(self, rules: str):
265-
for pat, repl in [(r" on ", "\non "), (r" do ", " do\n\t"), (r" endon", "\nendon ")]:
268+
for pat, repl in [
269+
(r" on ", "\non "),
270+
(r" do ", " do\n\t"),
271+
(r" endon", "\nendon "),
272+
]:
266273
rules = re.sub(pat, repl, rules, flags=re.IGNORECASE)
267274
return rules.rstrip(" ")
268275

tdmgr/GUI/widgets.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,12 @@ def addElements(self, *elements):
146146

147147
class GroupBoxV(GroupBoxBase):
148148
def __init__(
149-
self, title: str, margin: Union[int, List[int]] = 3, spacing: int = 3, *args, **kwargs
149+
self,
150+
title: str,
151+
margin: Union[int, List[int]] = 3,
152+
spacing: int = 3,
153+
*args,
154+
**kwargs,
150155
):
151156
super(GroupBoxV, self).__init__(title, *args, **kwargs)
152157

@@ -156,7 +161,12 @@ def __init__(
156161

157162
class GroupBoxH(GroupBoxBase):
158163
def __init__(
159-
self, title: str, margin: Union[int, List[int]] = 3, spacing: int = 3, *args, **kwargs
164+
self,
165+
title: str,
166+
margin: Union[int, List[int]] = 3,
167+
spacing: int = 3,
168+
*args,
169+
**kwargs,
160170
):
161171
super(GroupBoxH, self).__init__(title, *args, **kwargs)
162172

@@ -387,7 +397,8 @@ def __init__(self, command, meta, value=None, *args, **kwargs):
387397

388398
elif meta["type"] == "value":
389399
self.input = SpinBox(
390-
minimum=int(meta["parameters"]["min"]), maximum=int(meta["parameters"]["max"])
400+
minimum=int(meta["parameters"]["min"]),
401+
maximum=int(meta["parameters"]["max"]),
391402
)
392403
self.input.setMinimumWidth(75)
393404
if value:
@@ -538,7 +549,8 @@ def __init__(self, command: str, meta: dict, device: TasmotaDevice):
538549

539550
for idx, value in enumerate(values, start=1):
540551
sb = SpinBox(
541-
minimum=int(meta["parameters"]["min"]), maximum=int(meta["parameters"]["max"])
552+
minimum=int(meta["parameters"]["min"]),
553+
maximum=int(meta["parameters"]["max"]),
542554
)
543555
sb.setValue(value)
544556
hl_group = HLayout(0)

tdmgr/mqtt.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,6 @@ def initial_commands():
4040
commands = [(command, "") for command in commands]
4141
commands += [("status", "0"), ("gpios", "255")]
4242

43-
for sht in range(8):
44-
commands.append([f"shutterrelay{sht + 1}", ""])
45-
commands.append([f"shutterposition{sht + 1}", ""])
46-
4743
return commands
4844

4945

tdmgr/tasmota/commands.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@
5757
"0": {"description": "Keep relay(s) OFF after power up"},
5858
"1": {"description": "Turn relay(s) ON after power up"},
5959
"2": {"description": "Toggle relay(s) from last saved state"},
60-
"3": {"description": "Switch relay(s) to their last saved state", "default": "True"},
60+
"3": {
61+
"description": "Switch relay(s) to their last saved state",
62+
"default": "True",
63+
},
6164
"4": {"description": "Turn relay(s) ON and disable further relay control"},
6265
"5": {"description": "Turn relay(s) ON after a PulseTime period"},
6366
},

0 commit comments

Comments
 (0)