diff --git a/docs/configuration.md b/docs/configuration.md index 35c5ff7..ea8904f 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1567,8 +1567,10 @@ instance_name: # The default is the machine's hostname. status_objects: # A newline separated list of Klipper objects whose state will be -# published in the payload of the following topic: -# {instance_name}/klipper/status +# published. There are two different ways to publish the states - you +# can use either or both depending on your need. See the +# "publish_split_status" options for details. +# # For example, this option could be set as follows: # # status_objects: @@ -1589,6 +1591,23 @@ status_objects: # # If not configured then no objects will be tracked and published to # the klipper/status topic. +publish_split_status: False +# Configures how to publish status updates to MQTT. +# +# When set to False (default), all Klipper object state updates will be +# published to a single mqtt state with the following topic: +# {instance_name}/klipper/status +# +# When set to True, all Klipper object state updates will be published to +# separate mqtt topics derived from the object and item in the following +# format: +# {instance_name}/klipper/state/{objectname}/{statename} +# +# The actual value of the state is published as "value" to the topic above. +# For example, if the heater_bed temperature was 24.0, this is the payload: +# {"eventtime": {timestamp}, "value": 24.0} +# It would be published to this topic: +# {instance_name}/klipper/state/heater_bed/temperature default_qos: 0 # The default QOS level used when publishing or subscribing to topics. # Must be an integer value from 0 to 2. The default is 0. diff --git a/moonraker/components/mqtt.py b/moonraker/components/mqtt.py index efd593a..92af788 100644 --- a/moonraker/components/mqtt.py +++ b/moonraker/components/mqtt.py @@ -280,6 +280,8 @@ class MQTTClient(APITransport, Subscribable): raise config.error( "Option 'default_qos' in section [mqtt] must be " "between 0 and 2") + self.publish_split_status = \ + config.getboolean("publish_split_status", False) self.client = ExtPahoClient(protocol=self.protocol) self.client.on_connect = self._on_connect self.client.on_message = self._on_message @@ -308,6 +310,7 @@ class MQTTClient(APITransport, Subscribable): self.api_request_topic = f"{self.instance_name}/moonraker/api/request" self.api_resp_topic = f"{self.instance_name}/moonraker/api/response" self.klipper_status_topic = f"{self.instance_name}/klipper/status" + self.klipper_state_prefix = f"{self.instance_name}/klipper/state" self.moonraker_status_topic = f"{self.instance_name}/moonraker/status" status_cfg: Dict[str, Any] = config.getdict("status_objects", {}, allow_empty_fields=True) @@ -726,8 +729,19 @@ class MQTTClient(APITransport, Subscribable): ) -> None: if not status or not self.is_connected(): return - payload = {'eventtime': eventtime, 'status': status} - self.publish_topic(self.klipper_status_topic, payload) + if self.publish_split_status: + for objkey in status: + objval = status[objkey] + for statekey in objval: + payload = {'eventtime': eventtime, + 'value': objval[statekey]} + self.publish_topic( + f"{self.klipper_state_prefix}/{objkey}/{statekey}", + payload, retain=True) + else: + payload = {'eventtime': eventtime, 'status': status} + self.publish_topic(self.klipper_status_topic, payload) + def get_instance_name(self) -> str: return self.instance_name