server: graceful Ctrl-C shutdown; HendiCtrl closes connection cleanly
On KeyboardInterrupt, brewpi.py cancels all asyncio tasks (letting HeaterTask's `with device.open()` finally block run), then calls heater.close() as belt-and-suspenders before closing the event loop. On shutdown HeaterHendi.activate(False) now sets the switch to 0 instead of disabling remote control, so the Hendi stays in remote mode at 0 W rather than dropping back to its local panel state. HendiCtrl.close() does the same (setSwitch(0)) then closes the serial port. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,7 @@ class HeaterHendi(AHeater):
|
|||||||
if enable:
|
if enable:
|
||||||
self.hendi.remoteEnable(1)
|
self.hendi.remoteEnable(1)
|
||||||
else:
|
else:
|
||||||
self.hendi.remoteEnable(0)
|
self.hendi.setSwitch(0)
|
||||||
|
|
||||||
def is_activated(self):
|
def is_activated(self):
|
||||||
s = self.hendi.isRemoteEnable()
|
s = self.hendi.isRemoteEnable()
|
||||||
@@ -44,3 +44,6 @@ class HeaterHendi(AHeater):
|
|||||||
|
|
||||||
def get_power(self):
|
def get_power(self):
|
||||||
return self.power_eff
|
return self.power_eff
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.hendi.close()
|
||||||
|
|||||||
@@ -183,6 +183,13 @@ class HendiCtrl:
|
|||||||
def getPowerWatts(self):
|
def getPowerWatts(self):
|
||||||
return int(self.toWatts(self.getPowerDigits()) + 0.5)
|
return int(self.toWatts(self.getPowerDigits()) + 0.5)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
try:
|
||||||
|
self.setSwitch(0)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.ser.close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ class AHeater(AttributeChange):
|
|||||||
def get_powers(self):
|
def get_powers(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
pass
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def open(self):
|
def open(self):
|
||||||
try:
|
try:
|
||||||
|
|||||||
+19
-1
@@ -190,4 +190,22 @@ if __name__ == '__main__':
|
|||||||
threading.Thread(target=http_server.serve_forever, daemon=True).start()
|
threading.Thread(target=http_server.serve_forever, daemon=True).start()
|
||||||
print("Serving {} on http://0.0.0.0:{}".format(web_dir, args.http_port))
|
print("Serving {} on http://0.0.0.0:{}".format(web_dir, args.http_port))
|
||||||
|
|
||||||
server.run_forever()
|
loop = asyncio.get_event_loop()
|
||||||
|
try:
|
||||||
|
loop.run_forever()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nShutting down...")
|
||||||
|
finally:
|
||||||
|
# Cancel all tasks so their finally blocks (e.g. HeaterTask's
|
||||||
|
# `with device.open()`) get a chance to run before we close the port.
|
||||||
|
pending = asyncio.all_tasks(loop)
|
||||||
|
for task in pending:
|
||||||
|
task.cancel()
|
||||||
|
if pending:
|
||||||
|
loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True))
|
||||||
|
# Belt-and-suspenders: explicitly close the heater connection even if
|
||||||
|
# the task cleanup above failed to reach HeaterHendi.activate(False).
|
||||||
|
heater.close()
|
||||||
|
http_server.shutdown()
|
||||||
|
loop.close()
|
||||||
|
print("Server stopped.")
|
||||||
|
|||||||
Reference in New Issue
Block a user