48
48
# This will be populated if we have the config file
49
49
# url format: mqtt[s]://[<username>[:<password>]@]<host>[:<port>]/<topic_root>
50
50
MQTT_URL = None
51
+ MQTT_TOPIC_ROOT = ''
52
+ MQTT_CLIENT = None
51
53
MQTT_CONFIG_FILE = '/etc/sbot/mqtt.conf'
52
54
53
55
@@ -216,6 +218,14 @@ def __init__(self, mountpoint_path: str) -> None:
216
218
self ._setup_logging (mountpoint_path )
217
219
LED_CONTROLLER .set_code (True )
218
220
LED_CONTROLLER .set_status (LedStatus .Running )
221
+ if MQTT_CLIENT is not None :
222
+ MQTT_CLIENT .publish (
223
+ f'{ MQTT_TOPIC_ROOT } /state' ,
224
+ '{"state": "running"}' ,
225
+ qos = 1 ,
226
+ retain = True ,
227
+ )
228
+
219
229
env = dict (os .environ )
220
230
env ["SBOT_METADATA_PATH" ] = MOUNTPOINT_DIR
221
231
if MQTT_URL is not None :
@@ -256,6 +266,14 @@ def close(self) -> None:
256
266
LED_CONTROLLER .set_code (False )
257
267
USERCODE_LOGGER .removeHandler (self .handler )
258
268
269
+ if MQTT_CLIENT is not None :
270
+ MQTT_CLIENT .publish (
271
+ f'{ MQTT_TOPIC_ROOT } /state' ,
272
+ '{"state": "no USB"}' ,
273
+ qos = 1 ,
274
+ retain = True ,
275
+ )
276
+
259
277
def _send_signal (self , sig : int ) -> None :
260
278
if self .process .poll () is not None :
261
279
# Process has already exited, so the kill() call would fail.
@@ -267,8 +285,18 @@ def _watch_process(self) -> None:
267
285
self .process .wait ()
268
286
if self .process .returncode != 0 :
269
287
USERCODE_LOGGER .warning (f"Process exited with code { self .process .returncode } " )
288
+ new_state = 'crashed'
270
289
else :
271
290
USERCODE_LOGGER .info ("Your code finished successfully." )
291
+ new_state = 'finished'
292
+
293
+ if MQTT_CLIENT is not None :
294
+ MQTT_CLIENT .publish (
295
+ f'{ MQTT_TOPIC_ROOT } /state' ,
296
+ json .dumps ({"state" : new_state }),
297
+ qos = 1 ,
298
+ retain = True ,
299
+ )
272
300
273
301
process_lifetime = time .time () - self .process_start_time
274
302
@@ -438,7 +466,7 @@ def read_mqtt_config_file() -> MQTTVariables | None:
438
466
439
467
440
468
def setup_usercode_logging () -> None :
441
- global REL_TIME_FILTER
469
+ global REL_TIME_FILTER , MQTT_CLIENT , MQTT_TOPIC_ROOT
442
470
REL_TIME_FILTER = RelativeTimeFilter ()
443
471
USERCODE_LOGGER .addFilter (REL_TIME_FILTER )
444
472
USERCODE_LOGGER .setLevel (logging .DEBUG )
@@ -459,6 +487,8 @@ def setup_usercode_logging() -> None:
459
487
connected_callback = lambda : LED_CONTROLLER .set_wifi (True ),
460
488
disconnected_callback = lambda : LED_CONTROLLER .set_wifi (False ),
461
489
)
490
+ MQTT_CLIENT = handler .mqtt
491
+ MQTT_TOPIC_ROOT = mqtt_config .topic_prefix
462
492
463
493
handler .setLevel (logging .INFO )
464
494
handler .setFormatter (TieredFormatter (
@@ -479,6 +509,15 @@ def main():
479
509
registry = AutorunProcessRegistry ()
480
510
481
511
LED_CONTROLLER .mark_start ()
512
+
513
+ if MQTT_CLIENT is not None :
514
+ MQTT_CLIENT .publish (
515
+ f'{ MQTT_TOPIC_ROOT } /state' ,
516
+ '{"state": "no USB"}' ,
517
+ qos = 1 ,
518
+ retain = True ,
519
+ )
520
+
482
521
# Initial pass (in case an autorun FS is already mounted)
483
522
registry .update_filesystems (fstab_reader .read ())
484
523
0 commit comments