mqtt: add option to publish states to individual mqtt topics

This change allows the user to choose the strategy for publishing
klipper states to MQTT.  The original strategy where all state
updates are published to a common topic is still the default, but
can be turned off using the "publish_combined_status" config option.

The newly added strategy is publishing individual state updates to
separate mqtt topics.  It is disabled by default, and can be enabled
with the "publish_split_status" config option.

Signed-off-by: Matt White <m.w.white@gmail.com>
This commit is contained in:
Matt White 2022-12-30 05:13:25 -06:00 committed by GitHub
parent 358aee956b
commit e3bcfb5ea0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 4 deletions

View File

@ -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.

View File

@ -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,9 +729,20 @@ class MQTTClient(APITransport, Subscribable):
) -> None:
if not status or not self.is_connected():
return
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