From 44e75f4accc2ce04d1ae6fa466346ff60e74be59 Mon Sep 17 00:00:00 2001 From: Yuma Mihira Date: Fri, 27 Dec 2019 07:30:10 +0000 Subject: [PATCH 1/8] Port from Python 2 to Python 3 --- package.xml | 7 ++++--- scripts/mqtt_bridge_node.py | 2 +- src/mqtt_bridge/app.py | 10 +++++----- src/mqtt_bridge/bridge.py | 25 ++++++++++++------------- src/mqtt_bridge/mqtt_client.py | 2 +- src/mqtt_bridge/util.py | 6 ++---- 6 files changed, 25 insertions(+), 27 deletions(-) diff --git a/package.xml b/package.xml index 3b9a20b..6cedf22 100644 --- a/package.xml +++ b/package.xml @@ -18,9 +18,10 @@ rospy rosbridge_library std_msgs - - - + python3-msgpack + python3-paho-mqtt + python3-bson + diff --git a/scripts/mqtt_bridge_node.py b/scripts/mqtt_bridge_node.py index e829784..2e549fb 100755 --- a/scripts/mqtt_bridge_node.py +++ b/scripts/mqtt_bridge_node.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- import rospy diff --git a/src/mqtt_bridge/app.py b/src/mqtt_bridge/app.py index ec92338..7260af5 100644 --- a/src/mqtt_bridge/app.py +++ b/src/mqtt_bridge/app.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import + import inject import paho.mqtt.client as mqtt @@ -11,9 +11,9 @@ def create_config(mqtt_client, serializer, deserializer, mqtt_private_path): - if isinstance(serializer, basestring): + if isinstance(serializer, str): serializer = lookup_object(serializer) - if isinstance(deserializer, basestring): + if isinstance(deserializer, str): deserializer = lookup_object(deserializer) private_path_extractor = create_private_path_extractor(mqtt_private_path) def config(binder): @@ -42,8 +42,8 @@ def mqtt_bridge_node(): mqtt_client = mqtt_client_factory(mqtt_params) # load serializer and deserializer - serializer = params.get('serializer', 'json:dumps') - deserializer = params.get('deserializer', 'json:loads') + serializer = params.get('serializer', 'msgpack:dumps') + deserializer = params.get('deserializer', 'msgpack:loads') # dependency injection config = create_config( diff --git a/src/mqtt_bridge/bridge.py b/src/mqtt_bridge/bridge.py index bb94ef5..0f659c5 100644 --- a/src/mqtt_bridge/bridge.py +++ b/src/mqtt_bridge/bridge.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import + from abc import ABCMeta, abstractmethod @@ -11,7 +11,7 @@ def create_bridge(factory, msg_type, topic_from, topic_to, **kwargs): - u""" bridge generator function + """ bridge generator function :param (str|class) factory: Bridge class :param (str|class) msg_type: ROS message type @@ -20,11 +20,11 @@ def create_bridge(factory, msg_type, topic_from, topic_to, **kwargs): :param (float|None) frequency: publish frequency :return Bridge: bridge object """ - if isinstance(factory, basestring): + if isinstance(factory, str): factory = lookup_object(factory) if not issubclass(factory, Bridge): raise ValueError("factory should be Bridge subclass") - if isinstance(msg_type, basestring): + if isinstance(msg_type, str): msg_type = lookup_object(msg_type) if not issubclass(msg_type, rospy.Message): raise TypeError( @@ -34,14 +34,13 @@ def create_bridge(factory, msg_type, topic_from, topic_to, **kwargs): topic_from=topic_from, topic_to=topic_to, msg_type=msg_type, **kwargs) -class Bridge(object): - u""" Bridge base class +class Bridge(object, metaclass=ABCMeta): + """ Bridge base class :param mqtt.Client _mqtt_client: MQTT client :param _serialize: message serialize callable :param _deserialize: message deserialize callable """ - __metaclass__ = ABCMeta _mqtt_client = inject.attr(mqtt.Client) _serialize = inject.attr('serializer') @@ -50,7 +49,7 @@ class Bridge(object): class RosToMqttBridge(Bridge): - u""" Bridge from ROS topic to MQTT + """ Bridge from ROS topic to MQTT :param str topic_from: incoming ROS topic path :param str topic_to: outgoing MQTT topic path @@ -73,12 +72,12 @@ def _callback_ros(self, msg): self._last_published = now def _publish(self, msg): - payload = bytearray(self._serialize(extract_values(msg))) + payload = self._serialize(extract_values(msg)) self._mqtt_client.publish(topic=self._topic_to, payload=payload) class MqttToRosBridge(Bridge): - u""" Bridge from MQTT to ROS topic + """ Bridge from MQTT to ROS topic :param str topic_from: incoming MQTT topic path :param str topic_to: outgoing ROS topic path @@ -102,7 +101,7 @@ def __init__(self, topic_from, topic_to, msg_type, frequency=None, self._topic_to, self._msg_type, queue_size=self._queue_size) def _callback_mqtt(self, client, userdata, mqtt_msg): - u""" callback from MQTT + """ callback from MQTT :param mqtt.Client client: MQTT client used in connection :param userdata: user defined data @@ -120,12 +119,12 @@ def _callback_mqtt(self, client, userdata, mqtt_msg): rospy.logerr(e) def _create_ros_message(self, mqtt_msg): - u""" create ROS message from MQTT payload + """ create ROS message from MQTT payload :param mqtt.Message mqtt_msg: MQTT Message :return rospy.Message: ROS Message """ - msg_dict = self._deserialize(mqtt_msg.payload) + msg_dict = self._deserialize(mqtt_msg.payload, raw=False) return populate_instance(msg_dict, self._msg_type()) diff --git a/src/mqtt_bridge/mqtt_client.py b/src/mqtt_bridge/mqtt_client.py index de1fee3..3e175da 100644 --- a/src/mqtt_bridge/mqtt_client.py +++ b/src/mqtt_bridge/mqtt_client.py @@ -3,7 +3,7 @@ def default_mqtt_client_factory(params): - u""" MQTT Client factory + """ MQTT Client factory :param dict param: configuration parameters :return mqtt.Client: MQTT Client diff --git a/src/mqtt_bridge/util.py b/src/mqtt_bridge/util.py index 05080fc..424afb4 100644 --- a/src/mqtt_bridge/util.py +++ b/src/mqtt_bridge/util.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import absolute_import + from importlib import import_module from rosbridge_library.internal import message_conversion @@ -14,7 +14,7 @@ def lookup_object(object_path, package='mqtt_bridge'): def monkey_patch_message_conversion(): - u""" modify _to_primitive_inst to distinct unicode and str conversion """ + """ modify _to_primitive_inst to distinct unicode and str conversion """ from rosbridge_library.internal.message_conversion import ( type_map, primitive_types, string_types, FieldTypeMismatchException, ) @@ -23,8 +23,6 @@ def _to_primitive_inst(msg, rostype, roottype, stack): msgtype = type(msg) if msgtype in primitive_types and rostype in type_map[msgtype.__name__]: return msg - elif msgtype is unicode and rostype in type_map[msgtype.__name__]: - return msg.encode("utf-8", "ignore") elif msgtype is str and rostype in type_map[msgtype.__name__]: return msg.decode("utf-8").encode("utf-8", "ignore") raise FieldTypeMismatchException(roottype, stack, rostype, msgtype) From 977455294c4b46c5aaa10eec24396ff4f04f2b2b Mon Sep 17 00:00:00 2001 From: Yuma Mihira Date: Fri, 27 Dec 2019 07:51:25 +0000 Subject: [PATCH 2/8] Install python dependencies --- CMakeLists.txt | 2 +- package.xml | 4 ++-- requirements.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba5dab5..41aa565 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,4 +19,4 @@ install(DIRECTORY config DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/config ) -add_custom_target(install_depends ALL COMMAND "pip" "install" "--user" "-r" "${PROJECT_SOURCE_DIR}/requirements.txt") +add_custom_target(install_depends ALL COMMAND "pip3" "install" "--user" "-r" "${PROJECT_SOURCE_DIR}/requirements.txt") diff --git a/package.xml b/package.xml index 6cedf22..2753657 100644 --- a/package.xml +++ b/package.xml @@ -14,13 +14,13 @@ catkin python-setuptools - python-pip + python3-pip rospy rosbridge_library std_msgs python3-msgpack python3-paho-mqtt - python3-bson + python3-pymongo diff --git a/requirements.txt b/requirements.txt index 14de31f..b94438c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -inject>=3.3.1,<4.0 +inject>=4.0 msgpack-python>=0.4.8 paho-mqtt>=1.2 pymongo From 5e0b1c37dc19d72e48a31ea6048fc07052c65745 Mon Sep 17 00:00:00 2001 From: Christopher Mayershofer Date: Sat, 7 Nov 2020 13:26:11 +0100 Subject: [PATCH 3/8] Fix python3 compatibility issues for json and msgpack deserialization --- README.md | 14 ++++++++------ config/demo_params.yaml | 4 ++-- src/mqtt_bridge/bridge.py | 6 +++++- src/mqtt_bridge/util.py | 8 ++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2168e36..f33aa18 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,18 @@ This limitation can be overcome by defining custom bridge class, though. ## Demo -### prepare MQTT broker and client +### Prerequisites ``` -$ sudo apt-get install mosquitto mosquitto-clients +$ sudo apt install python3-pip +$ sudo apt install ros-noetic-rosbridge-library +$ sudo apt install mosquitto mosquitto-clients ``` ### Install python modules ```bash -$ pip install -r requirements.txt +$ pip3 install -r requirements.txt ``` ### launch node @@ -126,11 +128,11 @@ If `mqtt/private_path` parameter is set, leading `~/` in MQTT topic path will be ### serializer and deserializer -`mqtt_bridge` uses `json` as a serializer in default. But you can also configure other serializers. For example, if you want to use messagepack for serialization, add following configuration. +`mqtt_bridge` uses `msgpack` as a serializer by default. But you can also configure other serializers. For example, if you want to use json for serialization, add following configuration. ``` yaml -serializer: msgpack:dumps -deserializer: msgpack:loads +serializer: json:dumps +deserializer: json:loads ``` ### bridges diff --git a/config/demo_params.yaml b/config/demo_params.yaml index bf9943a..4d3afb2 100644 --- a/config/demo_params.yaml +++ b/config/demo_params.yaml @@ -6,8 +6,8 @@ mqtt: port: 1883 keepalive: 60 private_path: device/001 -serializer: msgpack:dumps -deserializer: msgpack:loads +#serializer: json:dumps +#deserializer: json:loads bridge: # ping pong - factory: mqtt_bridge.bridge:RosToMqttBridge diff --git a/src/mqtt_bridge/bridge.py b/src/mqtt_bridge/bridge.py index 0f659c5..bb074f1 100644 --- a/src/mqtt_bridge/bridge.py +++ b/src/mqtt_bridge/bridge.py @@ -124,7 +124,11 @@ def _create_ros_message(self, mqtt_msg): :param mqtt.Message mqtt_msg: MQTT Message :return rospy.Message: ROS Message """ - msg_dict = self._deserialize(mqtt_msg.payload, raw=False) + # Hack to enable both, messagepack and json deserialization. + if self._serialize.__name__ == "packb": + msg_dict = self._deserialize(mqtt_msg.payload, raw=False) + else: + msg_dict = self._deserialize(mqtt_msg.payload) return populate_instance(msg_dict, self._msg_type()) diff --git a/src/mqtt_bridge/util.py b/src/mqtt_bridge/util.py index 424afb4..b7cb883 100644 --- a/src/mqtt_bridge/util.py +++ b/src/mqtt_bridge/util.py @@ -12,7 +12,7 @@ def lookup_object(object_path, package='mqtt_bridge'): obj = getattr(module, obj_name) return obj - +""" def monkey_patch_message_conversion(): """ modify _to_primitive_inst to distinct unicode and str conversion """ from rosbridge_library.internal.message_conversion import ( @@ -27,9 +27,9 @@ def _to_primitive_inst(msg, rostype, roottype, stack): return msg.decode("utf-8").encode("utf-8", "ignore") raise FieldTypeMismatchException(roottype, stack, rostype, msgtype) message_conversion._to_primitive_inst = _to_primitive_inst - - -monkey_patch_message_conversion() +""" +# Seems like Python3 can work without this patch. +#monkey_patch_message_conversion() extract_values = message_conversion.extract_values populate_instance = message_conversion.populate_instance From 5a6f2951a7425ba48431a9730f34e2b414885ecd Mon Sep 17 00:00:00 2001 From: Christopher Mayershofer Date: Sat, 7 Nov 2020 13:26:11 +0100 Subject: [PATCH 4/8] Fix python3 compatibility issues for json and msgpack deserialization --- src/mqtt_bridge/util.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/mqtt_bridge/util.py b/src/mqtt_bridge/util.py index b7cb883..4e6a3fc 100644 --- a/src/mqtt_bridge/util.py +++ b/src/mqtt_bridge/util.py @@ -12,24 +12,6 @@ def lookup_object(object_path, package='mqtt_bridge'): obj = getattr(module, obj_name) return obj -""" -def monkey_patch_message_conversion(): - """ modify _to_primitive_inst to distinct unicode and str conversion """ - from rosbridge_library.internal.message_conversion import ( - type_map, primitive_types, string_types, FieldTypeMismatchException, - ) - def _to_primitive_inst(msg, rostype, roottype, stack): - # Typecheck the msg - msgtype = type(msg) - if msgtype in primitive_types and rostype in type_map[msgtype.__name__]: - return msg - elif msgtype is str and rostype in type_map[msgtype.__name__]: - return msg.decode("utf-8").encode("utf-8", "ignore") - raise FieldTypeMismatchException(roottype, stack, rostype, msgtype) - message_conversion._to_primitive_inst = _to_primitive_inst -""" -# Seems like Python3 can work without this patch. -#monkey_patch_message_conversion() extract_values = message_conversion.extract_values populate_instance = message_conversion.populate_instance From 0237ddd25124675c3894a4efbad58b691954d5b6 Mon Sep 17 00:00:00 2001 From: Junya Hayashi Date: Wed, 16 Dec 2020 15:16:14 +0900 Subject: [PATCH 5/8] fix codes for python3 --- .circleci/config.yml | 2 +- dev-requirements.txt | 2 +- test/conftest.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 62b7d89..d30336b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 executors: python: docker: - - image: cimg/python:2.7 + - image: cimg/python:3.7 auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_PASSWORD diff --git a/dev-requirements.txt b/dev-requirements.txt index 617c421..5cab397 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -3,7 +3,7 @@ --extra-index-url https://rospypi.github.io/simple/ catkin-pkg geometry-msgs -inject>=3.3.1,<4.0 +inject>=4.0 mock msgpack-python>=0.4.8 paho-mqtt>=1.2 diff --git a/test/conftest.py b/test/conftest.py index c95d75e..336c7e7 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,5 +1,5 @@ import threading -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler +from http.server import HTTPServer, BaseHTTPRequestHandler import pytest From 8fb9bc7417efcdf057995322967a7d82bab54823 Mon Sep 17 00:00:00 2001 From: Junya Hayashi Date: Wed, 16 Dec 2020 15:18:14 +0900 Subject: [PATCH 6/8] remove encoding header --- scripts/mqtt_bridge_node.py | 1 - setup.py | 2 -- src/mqtt_bridge/app.py | 3 --- src/mqtt_bridge/bridge.py | 3 --- src/mqtt_bridge/mqtt_client.py | 1 - src/mqtt_bridge/util.py | 2 -- 6 files changed, 12 deletions(-) diff --git a/scripts/mqtt_bridge_node.py b/scripts/mqtt_bridge_node.py index 2e549fb..b14725e 100755 --- a/scripts/mqtt_bridge_node.py +++ b/scripts/mqtt_bridge_node.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- import rospy from mqtt_bridge.app import mqtt_bridge_node diff --git a/setup.py b/setup.py index 1f31710..6e97bce 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from catkin_pkg.python_setup import generate_distutils_setup from setuptools import setup diff --git a/src/mqtt_bridge/app.py b/src/mqtt_bridge/app.py index 7260af5..47f4149 100644 --- a/src/mqtt_bridge/app.py +++ b/src/mqtt_bridge/app.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - import inject import paho.mqtt.client as mqtt import rospy diff --git a/src/mqtt_bridge/bridge.py b/src/mqtt_bridge/bridge.py index bb074f1..4518d12 100644 --- a/src/mqtt_bridge/bridge.py +++ b/src/mqtt_bridge/bridge.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - from abc import ABCMeta, abstractmethod import inject diff --git a/src/mqtt_bridge/mqtt_client.py b/src/mqtt_bridge/mqtt_client.py index 3e175da..4536dd5 100644 --- a/src/mqtt_bridge/mqtt_client.py +++ b/src/mqtt_bridge/mqtt_client.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import paho.mqtt.client as mqtt diff --git a/src/mqtt_bridge/util.py b/src/mqtt_bridge/util.py index 4e6a3fc..f646759 100644 --- a/src/mqtt_bridge/util.py +++ b/src/mqtt_bridge/util.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from importlib import import_module from rosbridge_library.internal import message_conversion From 76be1637764699a92f740e8f979372fb4b1d78a2 Mon Sep 17 00:00:00 2001 From: Junya Hayashi Date: Wed, 16 Dec 2020 15:51:10 +0900 Subject: [PATCH 7/8] use type hinting --- src/mqtt_bridge/bridge.py | 64 ++++++++++------------------------ src/mqtt_bridge/mqtt_client.py | 12 +++---- src/mqtt_bridge/util.py | 10 +++--- 3 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/mqtt_bridge/bridge.py b/src/mqtt_bridge/bridge.py index 4518d12..08080ef 100644 --- a/src/mqtt_bridge/bridge.py +++ b/src/mqtt_bridge/bridge.py @@ -1,4 +1,5 @@ -from abc import ABCMeta, abstractmethod +from abc import ABCMeta +from typing import Optional, Type, Dict, Union import inject import paho.mqtt.client as mqtt @@ -7,15 +8,10 @@ from .util import lookup_object, extract_values, populate_instance -def create_bridge(factory, msg_type, topic_from, topic_to, **kwargs): - """ bridge generator function - - :param (str|class) factory: Bridge class - :param (str|class) msg_type: ROS message type - :param str topic_from: incoming topic path - :param str topic_to: outgoing topic path - :param (float|None) frequency: publish frequency - :return Bridge: bridge object +def create_bridge(factory: Union[str, "Bridge"], msg_type: Union[str, Type[rospy.Message]], topic_from: str, + topic_to: str, frequency: Optional[float] = None, **kwargs) -> "Bridge": + """ generate bridge instance using factory callable and arguments. if `factory` or `meg_type` is provided as string, + this function will convert it to a corresponding object. """ if isinstance(factory, str): factory = lookup_object(factory) @@ -28,17 +24,11 @@ def create_bridge(factory, msg_type, topic_from, topic_to, **kwargs): "msg_type should be rospy.Message instance or its string" "reprensentation") return factory( - topic_from=topic_from, topic_to=topic_to, msg_type=msg_type, **kwargs) + topic_from=topic_from, topic_to=topic_to, msg_type=msg_type, frequency=frequency, **kwargs) class Bridge(object, metaclass=ABCMeta): - """ Bridge base class - - :param mqtt.Client _mqtt_client: MQTT client - :param _serialize: message serialize callable - :param _deserialize: message deserialize callable - """ - + """ Bridge base class """ _mqtt_client = inject.attr(mqtt.Client) _serialize = inject.attr('serializer') _deserialize = inject.attr('deserializer') @@ -48,27 +38,24 @@ class Bridge(object, metaclass=ABCMeta): class RosToMqttBridge(Bridge): """ Bridge from ROS topic to MQTT - :param str topic_from: incoming ROS topic path - :param str topic_to: outgoing MQTT topic path - :param class msg_type: subclass of ROS Message - :param (float|None) frequency: publish frequency + bridge ROS messages on `topic_from` to MQTT topic `topic_to`. expect `msg_type` ROS message type. """ - def __init__(self, topic_from, topic_to, msg_type, frequency=None): + def __init__(self, topic_from: str, topic_to: str, msg_type: rospy.Message, frequency: Optional[float] = None): self._topic_from = topic_from 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) - def _callback_ros(self, msg): + def _callback_ros(self, msg: rospy.Message): rospy.logdebug("ROS received from {}".format(self._topic_from)) now = rospy.get_time() if now - self._last_published >= self._interval: self._publish(msg) self._last_published = now - def _publish(self, msg): + def _publish(self, msg: rospy.Message): payload = self._serialize(extract_values(msg)) self._mqtt_client.publish(topic=self._topic_to, payload=payload) @@ -76,15 +63,11 @@ def _publish(self, msg): class MqttToRosBridge(Bridge): """ Bridge from MQTT to ROS topic - :param str topic_from: incoming MQTT topic path - :param str topic_to: outgoing ROS topic path - :param class msg_type: subclass of ROS Message - :param (float|None) frequency: publish frequency - :param int queue_size: ROS publisher's queue size + bridge MQTT messages on `topic_from` to ROS topic `topic_to`. MQTT messages will be converted to `msg_type`. """ - def __init__(self, topic_from, topic_to, msg_type, frequency=None, - queue_size=10): + def __init__(self, topic_from: str, topic_to: str, msg_type: Type[rospy.Message], + frequency: Optional[float] = None, queue_size: int = 10): self._topic_from = self._extract_private_path(topic_from) self._topic_to = topic_to self._msg_type = msg_type @@ -97,13 +80,8 @@ def __init__(self, topic_from, topic_to, msg_type, frequency=None, self._publisher = rospy.Publisher( self._topic_to, self._msg_type, queue_size=self._queue_size) - def _callback_mqtt(self, client, userdata, mqtt_msg): - """ callback from MQTT - - :param mqtt.Client client: MQTT client used in connection - :param userdata: user defined data - :param mqtt.MQTTMessage mqtt_msg: MQTT message - """ + def _callback_mqtt(self, client: mqtt.Client, userdata: Dict, mqtt_msg: mqtt.MQTTMessage): + """ callback from MQTT """ rospy.logdebug("MQTT received from {}".format(mqtt_msg.topic)) now = rospy.get_time() @@ -115,12 +93,8 @@ def _callback_mqtt(self, client, userdata, mqtt_msg): except Exception as e: rospy.logerr(e) - def _create_ros_message(self, mqtt_msg): - """ create ROS message from MQTT payload - - :param mqtt.Message mqtt_msg: MQTT Message - :return rospy.Message: ROS Message - """ + def _create_ros_message(self, mqtt_msg: mqtt.MQTTMessage) -> rospy.Message: + """ create ROS message from MQTT payload """ # Hack to enable both, messagepack and json deserialization. if self._serialize.__name__ == "packb": msg_dict = self._deserialize(mqtt_msg.payload, raw=False) diff --git a/src/mqtt_bridge/mqtt_client.py b/src/mqtt_bridge/mqtt_client.py index 4536dd5..d30bd8e 100644 --- a/src/mqtt_bridge/mqtt_client.py +++ b/src/mqtt_bridge/mqtt_client.py @@ -1,12 +1,10 @@ -import paho.mqtt.client as mqtt +from typing import Dict, Callable +import paho.mqtt.client as mqtt -def default_mqtt_client_factory(params): - """ MQTT Client factory - :param dict param: configuration parameters - :return mqtt.Client: MQTT Client - """ +def default_mqtt_client_factory(params: Dict) -> mqtt.Client: + """ MQTT Client factory """ # create client client_params = params.get('client', {}) client = mqtt.Client(**client_params) @@ -49,7 +47,7 @@ def default_mqtt_client_factory(params): return client -def create_private_path_extractor(mqtt_private_path): +def create_private_path_extractor(mqtt_private_path: str) -> Callable[[str], str]: def extractor(topic_path): if topic_path.startswith('~/'): return '{}/{}'.format(mqtt_private_path, topic_path[2:]) diff --git a/src/mqtt_bridge/util.py b/src/mqtt_bridge/util.py index f646759..ada8d4a 100644 --- a/src/mqtt_bridge/util.py +++ b/src/mqtt_bridge/util.py @@ -1,17 +1,19 @@ from importlib import import_module +from typing import Any, Callable, Dict +import rospy from rosbridge_library.internal import message_conversion - -def lookup_object(object_path, package='mqtt_bridge'): +def lookup_object(object_path: str, package: str='mqtt_bridge') -> Any: """ lookup object from a some.module:object_name specification. """ module_name, obj_name = object_path.split(":") module = import_module(module_name, package) obj = getattr(module, obj_name) return obj -extract_values = message_conversion.extract_values -populate_instance = message_conversion.populate_instance + +extract_values = message_conversion.extract_values # type: Callable[[rospy.Message], Dict] +populate_instance = message_conversion.populate_instance # type: Callable[[Dict, rospy.Message], rospy.Message] __all__ = ['lookup_object', 'extract_values', 'populate_instance'] From bd0ddeee744b400456b9bcd9f99850d8ee37397b Mon Sep 17 00:00:00 2001 From: Junya Hayashi Date: Thu, 31 Dec 2020 23:42:04 +0900 Subject: [PATCH 8/8] use noetic for rostest --- .circleci/config.yml | 8 ++++---- package.xml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d30336b..592dc72 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,7 +9,7 @@ executors: password: $DOCKERHUB_PASSWORD ros: docker: - - image: ros:melodic + - image: ros:noetic auth: username: $DOCKERHUB_USERNAME password: $DOCKERHUB_PASSWORD @@ -37,7 +37,7 @@ jobs: mkdir -p ~/catkin_ws/src cd ~/catkin_ws ln -s /root/project src/mqtt_bridge - source /opt/ros/melodic/setup.bash + source /opt/ros/noetic/setup.bash apt update rosdep update rosdep install --from-paths src --ignore-src -r -y @@ -47,9 +47,9 @@ jobs: name: run rostest command: | cd ~/catkin_ws - source /opt/ros/melodic/setup.bash + source /opt/ros/noetic/setup.bash source devel/setup.bash - pip install mock + pip3 install mock rostest mqtt_bridge demo.test workflows: diff --git a/package.xml b/package.xml index 2753657..f907ba9 100644 --- a/package.xml +++ b/package.xml @@ -19,7 +19,7 @@ rosbridge_library std_msgs python3-msgpack - python3-paho-mqtt + python3-pymongo