From 3fbdb4cfa9f79757f3662b6a18ce48c420780578 Mon Sep 17 00:00:00 2001 From: Junya Hayashi <junya.hayashi@groove-x.com> Date: Mon, 21 Nov 2016 00:00:42 +0900 Subject: [PATCH] Implement mqtt_private_path feature --- README.md | 4 ++++ config/demo_params.yaml | 10 ++++++++++ src/mqtt_bridge/app.py | 9 +++++++-- src/mqtt_bridge/bridge.py | 5 +++-- src/mqtt_bridge/mqtt_client.py | 10 +++++++++- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 318b3c0..1bb1c2e 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,10 @@ Parameters under `mqtt` section are used for creating paho's `mqtt.Client` and i See `mqtt_bridge.mqtt_client` for detail. +### mqtt private path + +If `mqtt/private_path` parameter is set, leading `~/` in MQTT topic path will be replaced by this value. For example, if `mqtt/pivate_path` is set as "device/001", MQTT path "~/value" will be converted to "device/001/value". + ### selializer and deselializer `mqtt_bridge` uses `json` as a selializer in default. But you can also configure other selializers. For example, if you want to use messagepack for selialization, add following configuration. diff --git a/config/demo_params.yaml b/config/demo_params.yaml index e6fa3de..6ac90ef 100644 --- a/config/demo_params.yaml +++ b/config/demo_params.yaml @@ -5,6 +5,7 @@ mqtt: host: localhost port: 1883 keepalive: 60 + private_path: device/001 selializer: msgpack:dumps deselializer: msgpack:loads bridge: @@ -26,3 +27,12 @@ bridge: msg_type: std_msgs.msg:String topic_from: echo topic_to: /back + # private path + - factory: mqtt_bridge.bridge:RosToMqttBridge + msg_type: std_msgs.msg:String + topic_from: /private/echo + topic_to: ~/echo + - factory: mqtt_bridge.bridge:MqttToRosBridge + msg_type: std_msgs.msg:String + topic_from: ~/echo + topic_to: /private/back diff --git a/src/mqtt_bridge/app.py b/src/mqtt_bridge/app.py index ad627a2..7f5a1df 100644 --- a/src/mqtt_bridge/app.py +++ b/src/mqtt_bridge/app.py @@ -6,18 +6,21 @@ import paho.mqtt.client as mqtt import rospy from .bridge import create_bridge +from .mqtt_client import create_private_path_extractor from .util import lookup_object -def create_config(mqtt_client, selializer, deselializer): +def create_config(mqtt_client, selializer, deselializer, mqtt_private_path): if isinstance(selializer, basestring): selializer = lookup_object(selializer) if isinstance(deselializer, basestring): deselializer = lookup_object(deselializer) + private_path_extractor = create_private_path_extractor(mqtt_private_path) def config(binder): binder.bind('selializer', selializer) binder.bind('deselializer', deselializer) binder.bind(mqtt.Client, mqtt_client) + binder.bind('mqtt_private_path_extractor', private_path_extractor) return config @@ -29,6 +32,7 @@ def mqtt_bridge_node(): params = rospy.get_param("~", {}) mqtt_params = params.pop("mqtt", {}) conn_params = mqtt_params.pop("connection") + mqtt_private_path = mqtt_params.pop("private_path", "") bridge_params = params.get("bridge", []) # create mqtt client @@ -42,7 +46,8 @@ def mqtt_bridge_node(): deselializer = params.get('deselializer', 'json:loads') # dependency injection - config = create_config(mqtt_client, selializer, deselializer) + config = create_config( + mqtt_client, selializer, deselializer, mqtt_private_path) inject.configure(config) # configure and connect to MQTT broker diff --git a/src/mqtt_bridge/bridge.py b/src/mqtt_bridge/bridge.py index e87f254..2aa22d9 100644 --- a/src/mqtt_bridge/bridge.py +++ b/src/mqtt_bridge/bridge.py @@ -46,6 +46,7 @@ class Bridge(object): _mqtt_client = inject.attr(mqtt.Client) _selialize = inject.attr('selializer') _deselialize = inject.attr('deselializer') + _extract_private_path = inject.attr('mqtt_private_path_extractor') class RosToMqttBridge(Bridge): @@ -59,7 +60,7 @@ class RosToMqttBridge(Bridge): def __init__(self, topic_from, topic_to, msg_type, frequency=None): self._topic_from = topic_from - self._topic_to = topic_to + self._topic_to = self._extract_private_path(topic_to) self._last_published = rospy.get_time() self._interval = 0 if frequency is None else 1.0 / frequency rospy.Subscriber(topic_from, msg_type, self._callback_ros) @@ -88,7 +89,7 @@ class MqttToRosBridge(Bridge): def __init__(self, topic_from, topic_to, msg_type, frequency=None, queue_size=10): - self._topic_from = topic_from + self._topic_from = self._extract_private_path(topic_from) self._topic_to = topic_to self._msg_type = msg_type self._queue_size = queue_size diff --git a/src/mqtt_bridge/mqtt_client.py b/src/mqtt_bridge/mqtt_client.py index 3093c0e..bf4498a 100644 --- a/src/mqtt_bridge/mqtt_client.py +++ b/src/mqtt_bridge/mqtt_client.py @@ -53,4 +53,12 @@ def default_mqtt_client_factory(params): return client -__all__ = ["default_mqtt_client_factory"] +def create_private_path_extractor(mqtt_private_path): + def extractor(topic_path): + if topic_path.startswith('~/'): + return '{}/{}'.format(mqtt_private_path, topic_path[2:]) + return topic_path + return extractor + + +__all__ = ['default_mqtt_client_factory', 'create_private_path_extractor'] -- GitLab