sensor: Use pipe to interrupt loop
The `time.sleep` function cannot be stopped prematurely. This means that when the program receives a signal indicating it should stop, it will not be able to do so until the running `sleep` completes. This means it could take up to 10 seconds for the process to stop. A better way to handle the shutdown signal is to use a pipe. When the signal is received, the write end of the pipe is closed. The event loop will detect this immediately, as `select.select` returns as soon as any event occurs on any of the polled file descriptors, or the timeout expires.master
parent
9503e87b4b
commit
205989aefd
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "thermostat"
|
name = "thermostat"
|
||||||
version = "0.2.0"
|
version = "0.3.0dev1"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["Dustin C. Hatch <dustin@hatch.name>"]
|
authors = ["Dustin C. Hatch <dustin@hatch.name>"]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import select
|
||||||
import signal
|
import signal
|
||||||
import time
|
import time
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
@ -52,12 +53,12 @@ SENSOR_CONFIG = {
|
||||||
|
|
||||||
class Daemon:
|
class Daemon:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.running = True
|
self.quitpipe = os.pipe()
|
||||||
|
|
||||||
def on_signal(self, signum: int, frame: FrameType) -> None:
|
def on_signal(self, signum: int, frame: FrameType) -> None:
|
||||||
log.debug("Got signal %d at %s", signum, frame)
|
log.debug("Got signal %d at %s", signum, frame)
|
||||||
log.info("Stopping")
|
log.info("Stopping")
|
||||||
self.running = False
|
os.close(self.quitpipe[1])
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
signal.signal(signal.SIGINT, self.on_signal)
|
signal.signal(signal.SIGINT, self.on_signal)
|
||||||
|
@ -73,7 +74,7 @@ class Daemon:
|
||||||
client.loop_start()
|
client.loop_start()
|
||||||
with closing(smbus2.SMBus(I2CPORT)) as bus:
|
with closing(smbus2.SMBus(I2CPORT)) as bus:
|
||||||
params = bme280.load_calibration_params(bus, SENSOR_ADDR)
|
params = bme280.load_calibration_params(bus, SENSOR_ADDR)
|
||||||
while self.running:
|
while 1:
|
||||||
data = bme280.sample(bus, SENSOR_ADDR, params)
|
data = bme280.sample(bus, SENSOR_ADDR, params)
|
||||||
values = {
|
values = {
|
||||||
"temperature": int(data.temperature),
|
"temperature": int(data.temperature),
|
||||||
|
@ -81,7 +82,10 @@ class Daemon:
|
||||||
"humidity": int(data.humidity),
|
"humidity": int(data.humidity),
|
||||||
}
|
}
|
||||||
client.publish(TOPIC, json.dumps(values))
|
client.publish(TOPIC, json.dumps(values))
|
||||||
time.sleep(10)
|
ready = select.select((self.quitpipe[0],), (), (), 10)[0]
|
||||||
|
if self.quitpipe[0] in ready:
|
||||||
|
os.close(self.quitpipe[0])
|
||||||
|
break
|
||||||
client.disconnect()
|
client.disconnect()
|
||||||
client.loop_stop()
|
client.loop_stop()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue