diff --git a/.gitignore b/.gitignore index b79728e..3004e1a 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,9 @@ ENV/ # mypy .mypy_cache/ +/.project +/.pydevproject +/bit/bit.c +/bit/bit.h +/bit/helloworld.c +/bit/helloworld.h diff --git a/.travis.yml b/.travis.yml index 5a5a64b..9c8621c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,12 @@ before_install: - - sudo apt install -y python3-pip build-essential cmake + - sudo apt install -y python3-pip build-essential cmake default-jdk maven - git clone https://github.com/eclipse-cyclonedds/cyclonedds /tmp/cyclonedds - - cd /tmp/cyclonedds && mkdir build && cd cmake --build . --target install + - cd /tmp/cyclonedds && mkdir build && cd build && cmake .. && make && sudo make install && cd $TRAVIS_BUILD_DIR addons: apt: update: true -language: python3 +language: python python: - "3.5" - "3.6" @@ -16,10 +16,13 @@ python: install: - travis_retry pip3 install tox - pip install codecov jsonpickle idl_parser + - ./configure + - cp tests/example.idl /tmp/example.idl + - cp tests/helloworld.idl /tmp/helloworld.idl script: - tox cache: directories: - $HOME/.cache/pip after_success: -- codecov \ No newline at end of file +- codecov diff --git a/bit/CMakeLists.txt b/bit/CMakeLists.txt index beefbb3..70ebd63 100644 --- a/bit/CMakeLists.txt +++ b/bit/CMakeLists.txt @@ -1,7 +1,44 @@ cmake_minimum_required(VERSION 3.7) +project(dds-python) find_package(CycloneDDS) -idlc_generate(ddsbit bit.idl) -add_library(ddstubs SHARED dds_stubs.c) -target_link_libraries(ddstubs ddsbit CycloneDDS::ddsc) +#idlc_generate(ddsbit bit.idl) +SET(outsources) + +SET(outsources bit) + +list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +message(" CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") +include(idlc_generate_macro) + +# find_program(idcl_generate dds_idlc /home/firas/cyclone/cyclonedds/bld/src/idlc) +# +# if(NOT idcl_generate) +# message(FATAL_ERROR "Failed to find idlc code generator ") +# else() +# message("Find idlc code generator") +# endif() + +# message (${idcl_generate}) +message (" outsources = ${outsources}") + +message ("${idcl_generate} -d ${CMAKE_CURRENT_SOURCE_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/${outsources}.idl") + + +# ADD_CUSTOM_COMMAND ( +# OUTPUT ${outsource}.c ${outsources}.h +# COMMAND ${idcl_generate} ARGS -d ${CMAKE_CURRENT_SOURCE_DIR} -verbose ${CMAKE_CURRENT_BINARY_DIR}/bit.idl +# COMMENT "Generating files in ${CMAKE_CURRENT_SOURCE_DIR} " +# ) +idlc_generate_func(${CMAKE_CURRENT_SOURCE_DIR}/bit.idl) +idlc_generate_func(${CMAKE_CURRENT_SOURCE_DIR}/../tests/helloworld.idl) + +add_library(ddstubs SHARED ${CMAKE_CURRENT_SOURCE_DIR}/dds_stubs.c) +add_library(ddsbit SHARED ${CMAKE_CURRENT_SOURCE_DIR}/bit.c ${CMAKE_CURRENT_SOURCE_DIR}/bit.h ) +add_library(ddshelloworld SHARED ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.c ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.h ) + +message("CMAKE_CURRENT_BINARY_DIR ==== ${CMAKE_CURRENT_BINARY_DIR} ") +message("CMAKE_CURRENT_SOURCE_DIR ==== ${CMAKE_CURRENT_SOURCE_DIR} ") + +target_link_libraries(ddstubs ddsbit ddshelloworld CycloneDDS::ddsc) \ No newline at end of file diff --git a/bit/cmake/idlc_generate_macro.cmake b/bit/cmake/idlc_generate_macro.cmake new file mode 100644 index 0000000..800c5ce --- /dev/null +++ b/bit/cmake/idlc_generate_macro.cmake @@ -0,0 +1,81 @@ +# +# Copyright(c) 2006 to 2018 ADLINK Technology Limited and others +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +# v. 1.0 which is available at +# http://www.eclipse.org/org/documents/edl-v10.php. +# +# SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause +# + + + +#set(IDLC_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "") +#set(IDLC "dds_idlc${EXTENSION}" CACHE STRING "") +#mark_as_advanced(IDLC_DIR IDLC) + +#set(IDLC_SCRIPT_IN "${CMAKE_CURRENT_LIST_DIR}/dds_idlc${EXTENSION}.in") + +#configure_file( +# "${IDLC_SCRIPT_IN}" "${IDLC}" +# @ONLY +# NEWLINE_STYLE ${LINE_ENDINGS}) +# +#if(NOT ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")) +# execute_process(COMMAND chmod +x "${IDLC_DIR}/${IDLC}") +#endif() + +#add_custom_target(idlc ALL DEPENDS "${IDLC_JAR}") + +MACRO (idlc_generate_func idl_file) + message("idl_file: ${idl_file} ") + + if(idl_file STREQUAL "") + message(FATAL_ERROR "idlc_generate called without any idl files") + endif() + + if (NOT IDLC_ARGS) + set(IDLC_ARGS) + endif() + + set(_dir "${CMAKE_CURRENT_BINARY_DIR}") + set(_sources) + set(_headers) + + find_program(idcl_generate_full_path + dds_idlc + PATHS /tmp/cyclonedds/build/src/idlc) + + if( idcl_generate_full_path STREQUAL "") + message(FATAL_ERROR "Failed to find idlc code generator ") + else() + message("${idcl_generate_full_path}: Found idlc code generator") + endif() + + foreach(FIL ${idl_file}) + message("file to parse ${FIL} ") + get_filename_component(ABS_FIL ${FIL} ABSOLUTE) + get_filename_component(FIL_WE ${FIL} NAME_WE) + + set(_source "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.c") + set(_header "${CMAKE_CURRENT_SOURCE_DIR}/${FIL_WE}.h") + + list(APPEND _sources "${_source}") + list(APPEND _headers "${_header}") + + add_custom_command( + OUTPUT "${_source}" "${_header}" + COMMAND "${idcl_generate_full_path}" + ARGS -d ${CMAKE_CURRENT_SOURCE_DIR} ${ABS_FIL} + COMMENT "Running idlc on ${FIL}" + VERBATIM) + endforeach() + + message("sources ${_sources}" ) + message("headers ${_headers}" ) + + set_source_files_properties(${_sources} ${_headers} PROPERTIES GENERATED TRUE) + +endmacro() diff --git a/cdds/__init__.py b/cdds/__init__.py index c3bc686..b6d729d 100644 --- a/cdds/__init__.py +++ b/cdds/__init__.py @@ -1,10 +1,18 @@ __author__ = 'Angelo Corsaro' from .runtime import Runtime +from .policy import * +from .entity import * +from .waitset import * from .participant import * from .topic import * +from .flexy_topic import * from .sub import * from .pub import * from .reader import * +from .flexy_reader import * from .writer import * -from .policy import * +from .readcondition import * +from .querycondition import * +from .gaurdcondition import * +from .flexy_writer import * diff --git a/cdds/dds_binding.py b/cdds/dds_binding.py index de7f522..7e78bde 100644 --- a/cdds/dds_binding.py +++ b/cdds/dds_binding.py @@ -2,7 +2,6 @@ import os from ctypes import * - def get_lib_ext(): system = platform.system() if system == 'Linux': @@ -12,7 +11,30 @@ def get_lib_ext(): else: return '.dll' + +# def get_user_lib_path(): +# system = platform.system() +# if system == 'Linux': +# return '/usr/local/lib' +# elif system == 'Darwin': +# return '/usr/local/lib' +# elif system in ['windows', 'Windows', 'win32']: +# return os.environ['CDDS_HOME'] +# else: +# return '/usr/local/lib' + def get_user_lib_path(): + system = platform.system() + if system == 'Linux': + return '/usr/local/lib' + elif system == 'Darwin': + return '/usr/local/lib' + elif system in ['windows', 'Windows', 'win32']: + return os.environ['CDDS_HOME'] + else: + return '/usr/local/lib' + +def get_user_bit_lib_path(): system = platform.system() if system == 'Linux': return '/usr/local/lib' @@ -23,21 +45,35 @@ def get_user_lib_path(): else: return '/usr/local/lib' +# system = platform.system() +# if system in ['windows', 'Windows', 'win32']: +# cham_lib = 'ddsc' + get_lib_ext() +# bit_lib = 'ddstubs' + get_lib_ext() +# cham_lib_path = get_user_bit_lib_path() + os.sep + cham_lib +# bit_lib_path = get_user_bit_lib_path() + os.sep + bit_lib +# else: +# cham_lib = 'libddsbit' + get_lib_ext() +# bit_lib = 'libddstubs' + get_lib_ext() +# cham_lib_path = get_user_bit_lib_path() + os.sep + cham_lib +# bit_lib_path = get_user_bit_lib_path() + os.sep + bit_lib + system = platform.system() if system in ['windows', 'Windows', 'win32']: - cham_lib = 'ddsc' + get_lib_ext() - bit_lib = 'ddstubs' + get_lib_ext() - cham_lib_path = get_user_lib_path() + os.sep + cham_lib - bit_lib_path = get_user_lib_path() + os.sep + bit_lib + cham_lib = 'ddsc' + get_lib_ext() + bit_lib = 'ddstubs' + get_lib_ext() + cham_lib_path = get_user_lib_path() + os.sep + cham_lib + bit_lib_path = get_user_bit_lib_path() + os.sep + bit_lib else: cham_lib = 'libddsc' + get_lib_ext() bit_lib = 'libddstubs' + get_lib_ext() + helloworld_lib = 'libddshelloworld' + get_lib_ext() cham_lib_path = get_user_lib_path() + os.sep + cham_lib - bit_lib_path = get_user_lib_path() + os.sep + bit_lib + bit_lib_path = get_user_bit_lib_path() + os.sep + bit_lib + helloworld_lib_path = get_user_bit_lib_path() + os.sep + helloworld_lib # Limits and Constants -MAX_SAMPLES = 256 +MAX_SAMPLES = 100 # @@ -53,6 +89,7 @@ def get_user_lib_path(): DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE = 32 DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE = 64 DDS_ANY_INSTANCE_STATE = DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE +DDS_ANY_INSTANCE_STATE = DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE DDS_ANY_STATE = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE @@ -119,19 +156,28 @@ def get_user_lib_path(): DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP = 0 DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP = 1 +LENGTH_UNLIMITED = -1 + + +def dds_infinity(): + return 1e20 + + def dds_secs(n): - return n*1000000000 + return n * 1000000000 + def dds_millis(n): - return n*1000000 + return n * 1000000 + def dds_micros(n): - return n*1000 + return n * 1000 + def dds_nanos(n): return n - # # DDS Sample Info # @@ -171,7 +217,7 @@ def is_not_alive_instance(self): dds_entity_t = c_int32 dds_time_t = c_int64 dds_duration_t = c_int64 -dds_instance_handle_t = c_int64 +dds_instance_handle_t = c_uint64 dds_domainid_t = c_uint32 dds_sample_state_t = c_int dds_view_state_t = c_int @@ -191,8 +237,6 @@ def is_not_alive_instance(self): SAMPLE_LOST_PROTO = CFUNCTYPE(None, c_void_p, c_void_p, c_void_p) - - # There are actually used to check the the listener are actually working... def trivial_on_requested_deadline_missed(r, s): @@ -210,8 +254,6 @@ def trivial_on_sample_rejected(r, s): logger.debug('DefaultListener', '>> Sample Rejected') - - class DDSValue(Structure): _fields_ = [('value', c_char_p)] @@ -233,6 +275,8 @@ class DDSSequence(Structure): # # Built-in key-value type # + + class DDSKeyBValue(Structure): _fields_ = [('key', c_char_p), ('value', DDSSequence)] diff --git a/cdds/entity.py b/cdds/entity.py new file mode 100644 index 0000000..10ccc65 --- /dev/null +++ b/cdds/entity.py @@ -0,0 +1,96 @@ +from .runtime import Runtime +from ctypes import * +from cdds import * + + +class Entity(object): + def __init__(self): + self.rt = Runtime.get_runtime() + self._handle = None + self._parent = None + self._qos = None + self._listener = None + + self._participant = None + self.enabled = True + + def enable(self): + self.enabled = True + rc = self.rt.ddslib.dds_enable(self.handle) + return rc + + def delete(self): + rc = self.rt.ddslib.dds_delete() + return rc + + def get_participant(self): + participant = None + if(self._handle is not None): + participant = self.rt.ddslib.dds_get_participant(self.handle) + return participant + + def get_children(self, size=0): + rc = 0 + childern = {} + rc = self.rt.ddslib.dds_get_children(self.handle, childeren, size) + + if rc > 0: + return childern + return rc + + def set_qos(self, qos=[]): + rc = 0 + rc = self.rt.ddslib.dds_set_qos(self.handle, self.qos) + return rc + + def get_qos(self): + rc = 0 + qos_policies = [] + rc = self.rt.ddslib.dds_get_qos(self.handle, qos_policies) + + if(rc == 0): + return qos_policies + else: + return rc + + @property + def parent(self): + return self._parent + + @parent.setter + def parent(self, parent_entity): + self._parent = parent_entity + + @property + def participant(self): + return self._participant + + @participant.setter + def participant(self, entity): + if (entity is not None): + self._participant = entity + + @property + def qos(self): + return self._qos + + @qos.setter + def qos(self, qos): + rc = qos + return rc + + @property + def handle(self): + return self._handle + + @handle.setter + def handle(self, entity): + self._handle = entity + + @handle.deleter + def handle(self): + self.rt.ddslib.dds_delete(self._handle) + + def _check_handle(self): + if self.handle is None: + raise Exception('Entity is already closed') diff --git a/cdds/error.py b/cdds/error.py index 6e61799..0074a1b 100644 --- a/cdds/error.py +++ b/cdds/error.py @@ -1,4 +1,3 @@ class Error(Exception): pass - diff --git a/cdds/flexy_reader.py b/cdds/flexy_reader.py new file mode 100644 index 0000000..91a7959 --- /dev/null +++ b/cdds/flexy_reader.py @@ -0,0 +1,181 @@ +from .dds_binding import * +import jsonpickle +from .runtime import Runtime + +from cdds import * + +from collections import namedtuple + + +@LIVELINESS_CHANGED_PROTO +def trampoline_on_liveliness_changed(r, s, a): + # print("[python-cdds]:>> Dispatching Liveliness change") + Runtime.dispatch_liveliness_changed_listener(r, s) + + +@DATA_AVAILABLE_PROTO +def trampoline_on_data_available(r, a): + # print("[python-cdds]:>> Dispatching Data Available ") + Runtime.dispatch_data_listener(r) + + +@SUBSCRIPTION_MATCHED_PROTO +def trampoline_on_subscription_matched(e, s, a): + # print("[python-cdds]:>> Dispatching Subscription Match") + Runtime.dispatch_subscription_matched_listener(e, s) + + +@SAMPLE_LOST_PROTO +def trampoline_on_sample_lost(e, s, a): + # print("[python-cdds]:>> Dispatching Sample Lost") + global logger + logger.debug('DefaultListener', '>> Sample Lost') + + +def do_nothing(a): + return a + + +def read_samples(): + return c_uint(DDS_READ_SAMPLE_STATE | DDS_ALIVE_INSTANCE_STATE | DDS_ANY_VIEW_STATE) + + +def new_samples(): + return c_uint(DDS_NOT_READ_SAMPLE_STATE | DDS_ALIVE_INSTANCE_STATE | DDS_ANY_VIEW_STATE) + + +def all_samples(): + return c_uint(DDS_ANY_STATE) + + +def new_instance_samples(): + return c_uint(DDS_NOT_READ_SAMPLE_STATE | DDS_ALIVE_INSTANCE_STATE | DDS_NEW_VIEW_STATE) + + +def not_alive_instance_samples(): + return c_uint(DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) + + +class FlexyReader: + def __init__(self, sub, flexy_topic, flexy_data_listener=None, ps=None): + self.rt = Runtime.get_runtime() + self.participant = sub.participant + self.sub = sub + self.flexy_topic = flexy_topic + if flexy_data_listener is None: + self.data_listener = do_nothing + else: + self.data_listener = flexy_data_listener + self.qos = self.rt.to_rw_qos(ps) + self.subsciption_listener = None + self._liveliness_listener = None + self.handle = c_void_p() + topic = self.flexy_topic.topic + self.listener_handle = self.rt.ddslib.dds_create_listener(None) + self.rt.ddslib.dds_lset_data_available(self.listener_handle, trampoline_on_data_available) + self.rt.ddslib.dds_lset_liveliness_changed(self.listener_handle, trampoline_on_liveliness_changed) + self.rt.ddslib.dds_lset_subscription_matched(self.listener_handle, trampoline_on_subscription_matched) + + self.handle = self.rt.ddslib.dds_create_reader(sub.handle, topic, self.qos, self.listener_handle) + assert (self.handle > 0) + self.rt.register_data_listener(self.handle, self.__handle_data) + + def on_data_available(self, fun): + self.data_listener = fun + + def on_subscription_matched(self, fun): + self.subsciption_listener = fun + self.rt.register_subscription_matched_listener(self.handle, self.__handle_sub_matched) + + def on_liveliness_changed(self, fun): + self._liveliness_listener = fun + self.rt.register_liveliness_changed_listener(self.handle, self.__handle_liveliness_change) + + def __handle_data(self, r): + self.data_listener(self) + + def __handle_sub_matched(self, r, s): + self.subsciption_listener(self, s) + + def __handle_liveliness_change(self, r, s): + self._liveliness_listener(self, s) + + def wait_for_data(self, selector, timeout): + condition = c_void_p(self.rt.ddslib.dds_create_readcondition(self.handle, selector)) + ws = WaitSet(self.dp, condition) + r = ws.wait(timeout) + ws.close() + return r + + # sread is the synchronous read, that means this blocks until some data is received + def sread(self, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.read(selector) + else: + return [] + + def read(self, selector): + return self.read_n(MAX_SAMPLES, selector) + + def sread_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.read_n(n, selector) + else: + return [] + + def read_n(self, n, sample_selector): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * n)() + nr = self.rt.ddslib.dds_read_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(self.flexy_topic.data_type)) + if infos[i].valid_data: + v = sp[0].value.decode(encoding='UTF-8') + data.append(jsonpickle.decode(v)) + else: + kh = jsonpickle.decode(sp[0].key.decode(encoding='UTF-8')) + data.append(kh) + self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + + return zip(data, infos) + + def stake(self, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take(selector) + else: + return [] + + def take(self, selector): + return self.take_n(MAX_SAMPLES, selector) + + def stake_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take_n(n, selector) + else: + return [] + + def take_n(self, n, sample_selector): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + + SampleVec_t = c_void_p * n + samples = SampleVec_t() + nr = self.rt.ddslib.dds_take_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(self.flexy_topic.data_type)) + if infos[i].valid_data: + v = sp[0].value.decode(encoding='UTF-8') + data.append(jsonpickle.decode(v)) + else: + kh = jsonpickle.decode(sp[0].key.decode(encoding='UTF-8')) + data.append(kh) + + self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + return zip(data, infos) + + def wait_history(self, timeout): + return self.rt.ddslib.dds_reader_wait_for_historical_data(self.handle, timeout) diff --git a/cdds/flexy_topic.py b/cdds/flexy_topic.py new file mode 100644 index 0000000..848b646 --- /dev/null +++ b/cdds/flexy_topic.py @@ -0,0 +1,38 @@ +from .runtime import Runtime +from .dds_binding import DDSKeyValue +from ctypes import * + +from cdds import * + +MAX_NAME_SIZE = 100 + + +class TopicType(object): + def gen_key(self): + pass + + +class FlexyTopic: + def __init__(self, dp, name, keygen=None, qos=None): + self.rt = Runtime.get_runtime() + if keygen is None: + self.keygen = lambda x: x.gen_key() + else: + self.keygen = keygen + + self.qos = self.rt.to_rw_qos(qos) + self.type_support = self.rt.get_key_value_type_support() + + self.topic = self.rt.ddslib.dds_create_topic(dp._handle, self.type_support, name.encode(), self.qos, None) + self.handle = self.topic + assert (self.topic > 0) + self.data_type = DDSKeyValue + self.dp = dp + + def gen_key(self, s): + return self.keygen(s) + + def get_name(self, topic_name): + rc = self.rt.ddslib.dds_get_name(self.handle, topic_name) + + return rc diff --git a/cdds/flexy_writer.py b/cdds/flexy_writer.py new file mode 100644 index 0000000..32a5eab --- /dev/null +++ b/cdds/flexy_writer.py @@ -0,0 +1,34 @@ +from .runtime import Runtime +from .dds_binding import * +import jsonpickle + + +class FlexyWriter: + def __init__(self, pub, flexy_topic, ps=None): + self.rt = Runtime.get_runtime() + self. prticipant = pub.participant + self.qos = self.rt.to_rw_qos(ps) + self.handle = self.rt.ddslib.dds_create_writer(pub.handle, flexy_topic.topic, self.qos, None) + + assert (self.handle > 0) + self.keygen = flexy_topic.gen_key + + def write(self, s): + gk = self.keygen(s) + kh = KeyHolder(gk) + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + sample = DDSKeyValue(key.encode(), value.encode()) + self.rt.ddslib.dds_write(self.handle, byref(sample)) + + def write_all(self, xs): + for x in xs: + self.write(x) + + def dispose_instance(self, s): + gk = self.keygen(s) + kh = KeyHolder(gk) + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + sample = DDSKeyValue(key.encode(), value.encode()) + self.rt.ddslib.dds_dispose(self.handle, byref(sample)) diff --git a/cdds/gaurdcondition.py b/cdds/gaurdcondition.py new file mode 100644 index 0000000..5e6e16f --- /dev/null +++ b/cdds/gaurdcondition.py @@ -0,0 +1,245 @@ +from .dds_binding import * +from .runtime import Runtime + +from cdds import * +from ctypes import c_bool + + +class GaurdCondition (Entity): + def __init__(self, entity): + self.rt = Runtime.get_runtime() + self.participant = entity.participant + self.parent = entity + + self.handle = self.rt.ddslib.dds_create_guardcondition(entity.handle) + + def set_guard_condition(self, triggerd=True): + ret = self.rt.ddslib.dds_set_guardcondition(self.handle, triggerd) + if ret != 0: + print("Error while executing set_gaurdcondition") + + return True + + def read_trigger(self): + triggered = POINTER(c_bool)() + ret = self.rt.ddslib.dds_read_guardcondition(self.handle, byref(triggered)) + + if ret == 0: + return triggered + + return None + + def take_trigger(self): + triggered = POINTER(c_bool)() + ret = self.rt.ddslib.dds_take_guardcondition(self.handle, byref(triggered)) + + if ret == 0: + return triggered + + return None + + def read(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def read_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data + + def read_n(self, n): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * n)() + + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, n, n) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def read_wl(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_wl(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise Exception("Read operation with loan failed, return code is {0}".format(nr)) + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def lookup_instance(self, s): + gk = self.keygen(s) + + kh = KeyHolder(gk) + + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + + sample = DDSKeyValue(key.encode(), value.encode()) + result = self.rt.ddslib.dds_lookup_instance(self.parent.handle, byref(sample)) + + return result + + def read_instance(self, instacne_handle): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_instance(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, c_uint64(instacne_handle)) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + return data + + def sread_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.read_n(n, selector) + else: + return [] + + def take(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def take_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise ("Error while trying to take samples with mask, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take_mask operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data + + def stake(self, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take(selector) + else: + return [] + + def stake_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take_n(n, selector) + else: + return [] + + def take_n(self, n, sample_selector): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + + SampleVec_t = c_void_p * n + samples = SampleVec_t() + nr = self.rt.ddslib.dds_take_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data diff --git a/cdds/logger.py b/cdds/logger.py index afa3db0..7661d7f 100644 --- a/cdds/logger.py +++ b/cdds/logger.py @@ -26,8 +26,6 @@ def __init__(self, file_name=None, debug_flag=False): handler.setFormatter(formatter) self.logger.addHandler(handler) - - def info(self, caller, message): self.logger.info(str('< %s > %s') % (caller, message)) @@ -72,4 +70,3 @@ def debug(self, caller, message): logger = DDSLogger() - diff --git a/cdds/participant.py b/cdds/participant.py index 45c1537..d86f06b 100644 --- a/cdds/participant.py +++ b/cdds/participant.py @@ -1,9 +1,63 @@ from .runtime import Runtime +from cdds import pub, topic, entity +from cdds.topic import * +from cdds.entity import * +from cdds.sub import * -class Participant: +# DomainParticipant Wrapper + + +class Participant(Entity): def __init__(self, did): self.rt = Runtime.get_runtime() self.did = did self.handle = self.rt.ddslib.dds_create_participant(did, None, None) - assert (self.handle > 0) - self.dp = self + + assert self.handle > 0, "Failed to create Domain participant" + + self._participant = self + self._parent = self + + self._topic_list = [] + self._publisher_list = [] + self._subscriber_list = [] + self._writer_list = [] + self._reader_list = [] + self._topic_list = [] + + def create_publisher(self, publisher_qos=None, publisher_listener=None): + publisher = pub.Publisher(self, publisher_qos, publisher_listener) + self._publisher_list.append(publisher) + + return publisher + + def create_subscriber(self, subsriber_qos=None, subscriber_listener=None): + subscriber = Subscriber(self, subsriber_qos, subscriber_listener) + self._subscriber_list.append(subscriber) + return subscriber + + def create_topic(self, topic_name, type_support=None, qos=None, topic_listener=None): + if(type_support is None): + type_support = self.rt.get_key_value_type_support() + t = Topic(self, topic_name, type_support, qos, topic_listener) + self._topic_list.append(topic) + return t + + def find_topic(self, topic_name): + topic_name_as_byte_array = topic_name.encode(encoding='utf_8', errors='strict') + foundTopic = self.rt.ddslib.dds_find_topic(self.handle, topic_name_as_byte_array) + + return foundTopic + + @property + def handle(self): + return super(Participant, self).handle + + @handle.setter + def handle(self, e): + super(Participant, self.__class__).handle.fset(self, e) + + def _check_handle(self): + if super().handle is None: + raise Exception('Entity is already closed') + return True diff --git a/cdds/policy.py b/cdds/policy.py index de6b0eb..2c18bab 100644 --- a/cdds/policy.py +++ b/cdds/policy.py @@ -1,10 +1,12 @@ from .dds_binding import * + class Policy: def __init__(self, id, kind): self.id = id self.kind = kind + class Partition(Policy): def __init__(self, ps): Policy.__init__(self, DDS_PARTITION_QOS_POLICY_ID, None) @@ -12,7 +14,7 @@ def __init__(self, ps): class Reliable(Policy): - def __init__(self, blocking_time = 0): + def __init__(self, blocking_time=0): Policy.__init__(self, DDS_RELIABILITY_QOS_POLICY_ID, DDS_RELIABILITY_RELIABLE) self.max_blocking_time = blocking_time @@ -47,7 +49,7 @@ def __init__(self): class Transient(Policy): def __init__(self): - Policy.__init__(self, DDS_DURABILITY_QOS_POLICY_ID, DDS_DURABILITY_TRANSIENT) + Policy.__init__(self, DDS_DURABILITY_QOS_POLICY_ID, DDS_DURABILITY_TRANSIENT) class Persistent(Policy): @@ -82,12 +84,12 @@ class ReceptionTimestampOrder(Policy): def __init__(self): Policy.__init__(self, DDS_DESTINATIONORDER_QOS_POLICY_ID, DDS_DESTINATIONORDER_BY_RECEPTION_TIMESTAMP) + class SourceTimestampOrder(Policy): def __init__(self): Policy.__init__(self, DDS_DESTINATIONORDER_QOS_POLICY_ID, DDS_DESTINATIONORDER_BY_SOURCE_TIMESTAMP) - DDS_V_State = [Reliable(), KeepLastHistory(1), Volatile(), ManualInstanceDispose(), SourceTimestampOrder()] DDS_TL_State = [Reliable(), KeepLastHistory(1), TransientLocal(), ManualInstanceDispose(), SourceTimestampOrder()] DDS_State = DDS_V_State diff --git a/cdds/pub.py b/cdds/pub.py index dabc7ac..e637a8a 100644 --- a/cdds/pub.py +++ b/cdds/pub.py @@ -1,7 +1,25 @@ from .runtime import Runtime from .policy import Partition -class Publisher: +from cdds import * + +from cdds.writer import * + + +class Publisher(Entity): + def __init__(self, dp, ps=None, listener=None): + self.rt = Runtime.get_runtime() + self.participant = dp + qos = None +# if ps is not None: +# qos = self.rt.to_ps_qos(ps) + qos = ps + + self.parent = dp + self._datawriter_list = [] + self.handle = self.rt.ddslib.dds_create_publisher(self.participant.handle, qos, listener) + assert (self.handle is not None and self.handle > 0) + @staticmethod def partitions(ps): return [Partition(ps)] @@ -10,12 +28,37 @@ def partitions(ps): def partition(p): return [Partition([p])] - def __init__(self, dp, ps = None): - self.rt = Runtime.get_runtime() - self.dp = dp - qos = None - if ps is not None: - qos = self.rt.to_ps_qos(ps) + @property + def handle(self): + return super(Publisher, self).handle + + @handle.setter + def handle(self, entity): + super(Publisher, self.__class__).handle.fset(self, entity) + + def _check_handle(self): + if super().handle is None: + raise Exception('Entity is already closed') + return True + + @property + def participant(self): + return super(Publisher, self).participant + + @participant.setter + def participant(self, entity): + super(Publisher, self.__class__).participant.fset(self, entity) + + def create_writer(self, topic, policy=None, dw_listener=None): + data_writer = Writer(self, topic, policy, dw_listener) + self._datawriter_list.append(data_writer) + return data_writer + + def suspend(self): + rc = self.rt.ddslib.dds_suspend(self.handle) + + return rc - self.handle = self.rt.ddslib.dds_create_publisher(self.dp.handle, qos, None) - assert (self.handle > 0) + def resume(self): + rc = self.rt.ddslib.dds_resume(self.handle) + return rc diff --git a/cdds/py_dds_utils.py b/cdds/py_dds_utils.py new file mode 100644 index 0000000..56dc717 --- /dev/null +++ b/cdds/py_dds_utils.py @@ -0,0 +1,209 @@ +import xml.etree.ElementTree as ET +import subprocess +import struct +import enum +import re +from collections import OrderedDict, namedtuple + +import os +import sys + +from cdds import * + +from idl_parser import parser + + +import inspect + + +# constants +_MODULE_TAG = 'module' +_TYPEDEF_TAG = 'yypeDef' +_STRUCT_TAG = 'struct' +_MEMBER_TAG = 'member' +_ARRAY_TAG = 'array' +_SEQUENCE_TAG = 'sequence' +_TYPE_TAG = 'type' +_STRING_TAG = 'string' +_CHAR_TAG = 'char' +_ENUM_TAG = 'enum' +_ELEMENT_TAG = 'element' + +_NAME_ATTRIBUTE = 'name' +_SIZE_ATTRIBUTE = 'size' +_VALUE_ATTRIBUTE = 'value' + +_MODULE_SEPARATOR = '::' + + +def _FoundTopic_Init(dp, topic_handle): + foundTopic = FoundTopic(dp) + foundTopic.handle = topic_handle + return foundTopic + + +def _get_field_default(ele): + if ele == _STRING_TAG: + return '' + elif ele == _SEQUENCE_TAG: + return [] + elif ele == _ARRAY_TAG: + array_size = int(ele.attrib[_SIZE_ATTRIBUTE]) + array_type = ele[0] + return [_get_field_default(array_type) for _ in range(array_size)] + elif ele == _TYPE_TAG: + typename = ele.attrib[_NAME_ATTRIBUTE] + actual_type = _get_actual_type(typename) + if isinstance(actual_type, enum.EnumMeta): + return actual_type(0) + elif isinstance(actual_type, type): + return actual_type() + else: + # it's a typedef, recurse... + return _get_field_default(actual_type) + elif ele == 'boolean': + return False + elif ele == 'char': + return '\x00' + elif ele in ('octet', 'short', 'long', 'longlong', 'ushort', 'ulong', 'ulonglong'): + return 0 + elif ele in ('float', 'double'): + return 0.0 + return None + + +class TopicDataClass(object): + ''' + Abstract topic data class. + Generated classes inherits this base class. + ''' + + def __init__(self, member_names=[]): + self._member_attributes = member_names + self._typesupport = None + self._nested_types = {} + pass + + def get_vars(self): + ''' + Return the dictionary of attribute and value pair for the topic data members. + ''' + result = OrderedDict() + return result + + def _format_list(self, list_val): + result = [] + return result + + +def _create_class(name, members): + ''' Create Python class based on an dictionary of members + + Args: + name: name of the class to be created + members (dict): name and type of properties + Returns: + dynamically created Python class + ''' + + def __init__(self, **kwargs): + setattr(self, '_members', members) + setattr(self, '_member_attributes', members.keys()) + member_names = [] + self._member_attributes = member_names + # self._typesupport = None + # _nested_types = {} + + # define variables with default value + for member in members.keys(): + setattr(self, member, _get_field_default(members[member])) + + # set values for variables passed in + for member_name, value in kwargs.items(): + setattr(self, member_name, value) + + for member in members.keys(): + self._member_attributes.append(member) + + def get_vars(self): + result = OrderedDict() + for member in self._member_attributes: + result[member] = getattr(self, member) + + return result + + def gen_key(self): + return self.userID + + def __eq__(self, other): + result = (isinstance(other, type(self))) + if result: + for member in self._members.keys(): + result = (getattr(self, member) == getattr(other, member)) + if not result: + break + + return result + + def _get_print_vars(self): + result = [] + for key, val in self.get_vars().items(): + if isinstance(val, list): + result.append("{}: [{}]".format(key, self._format_list(val))) + else: + result.append("{}: {}".format(key, val)) + return ', '.join(result) + + def __str__(self): + res = self._get_print_vars() + return res + + cls_name = name + cls_attrs = {"__init__": __init__, + "gen_key": gen_key, + "__eq__": __eq__, + "__str__": __str__, + "_get_print_vars": _get_print_vars, + "get_vars": get_vars + } + + # create topic data class + data_class = type(cls_name, (TopicDataClass,), cls_attrs) + return data_class + + +''' Create Python class based on a idl file + + Args: + name: name of the class to be created + idl_path: full path of the idl file + Returns: + dynamically created Python class + ''' + + +def create_class(class_name, idl_path): + + # print("Generate {} from idl file".format(class_name)) + parser_ = parser.IDLParser() + + with open(idl_path, 'r') as idlf: + contents = idlf.read() + global_module = parser_.load(contents) + + for module in global_module.modules: + + mod_struct = module.structs + for sub_str in mod_struct: + member_dict = {} + struct_complete_name = "{0}_{1}".format(module.name, sub_str.name) + + members = sub_str.members + + for member in members: + if(member.name not in member_dict): + member_dict[member.name] = _get_field_default(member.type.name) + + other_new_class = _create_class(struct_complete_name, member_dict) + + return other_new_class diff --git a/cdds/querycondition.py b/cdds/querycondition.py new file mode 100644 index 0000000..40a5a6d --- /dev/null +++ b/cdds/querycondition.py @@ -0,0 +1,241 @@ +from .dds_binding import * +import jsonpickle +from .runtime import Runtime + +from cdds import * + +from collections import namedtuple + +_Sample = namedtuple('_Sample', ['data', 'status']) + + +class QueryCondition (Entity): + def __init__(self, reader, mask=all_samples(), filter=None): + self.rt = Runtime.get_runtime() + self.participant = reader.participant + self.parent = reader + + self.handle = self.rt.ddslib.dds_create_querycondition(reader.handle, mask, filter) + + self.keygen = self.parent.topic.gen_key + + def get_mask(self): + outMask = c_uint32(int('0xFFFFFFFF', 16)) + retValue = self.rt.ddslib.dds_get_mask(self.handle, byref(outMask)) + if retValue != 0: + raise Exception("Get_mask operation failed") + return outMask + + def get_reader_handle(self): + entity = self.rt.ddslib.dds_get_datareader(self.handle) + + if (entity < 0): + raise Exception("readerCondition.get_reader operation failed") + + return entity + + def read(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def read_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data + + def read_n(self, n): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * n)() + + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, n, n) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def read_wl(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_wl(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise Exception("Read operation with loan failed, return code is {0}".format(nr)) + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def lookup_instance(self, s): + gk = self.keygen(s) + + kh = KeyHolder(gk) + + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + + sample = DDSKeyValue(key.encode(), value.encode()) + result = self.rt.ddslib.dds_lookup_instance(self.parent.handle, byref(sample)) + + return result + + def read_instance(self, instacne_handle): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_instance(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, c_uint64(instacne_handle)) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + return data + + def sread_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.read_n(n, selector) + else: + return [] + + def take(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + + return data + + def take_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise ("Error while trying to take samples with mask, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take_mask operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data + + def stake(self, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take(selector) + else: + return [] + + def stake_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take_n(n, selector) + else: + return [] + + def take_n(self, n, sample_selector): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + + SampleVec_t = c_void_p * n + samples = SampleVec_t() + nr = self.rt.ddslib.dds_take_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, return code = {}".format(rc)) + return data diff --git a/cdds/readcondition.py b/cdds/readcondition.py new file mode 100644 index 0000000..9081bd9 --- /dev/null +++ b/cdds/readcondition.py @@ -0,0 +1,251 @@ +from .dds_binding import * +import jsonpickle +from .runtime import Runtime + +from cdds import * + +from collections import namedtuple + +_Sample = namedtuple('_Sample', ['data', 'status']) + + +class ReadCondition (Entity): + def __init__(self, reader, mask=all_samples()): + self.rt = Runtime.get_runtime() + self.participant = reader.participant + self.parent = reader + + self.handle = self.rt.ddslib.dds_create_readcondition(reader.handle, mask) + + self.keygen = self.parent.topic.gen_key + + def get_mask(self): + outMask = c_uint32(int('0xFFFFFFFF', 16)) + retValue = self.rt.ddslib.dds_get_mask(self.handle, byref(outMask)) + if retValue != 0: + raise Exception("Get_mask operation failed") + return outMask + + def get_reader_handle(self): + entity = self.rt.ddslib.dds_get_datareader(self.handle) + + if (entity < 0): + raise Exception("readerCondition.get_reader operation failed") + + return entity + + def read(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def read_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def read_n(self, n): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * n)() + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, n, n) + + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def read_wl(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + nr = self.rt.ddslib.dds_read_wl(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + + if nr < 0: + raise Exception("Read operation with loan failed, return code is {0}".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return zip(data, infos) + + def lookup_instance(self, s): + gk = self.keygen(s) + + kh = KeyHolder(gk) + + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + + sample = DDSKeyValue(key.encode(), value.encode()) + result = self.rt.ddslib.dds_lookup_instance(self.parent.handle, byref(sample)) + + return result + + def read_instance(self, instacne_handle): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_instance(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, c_uint64(instacne_handle)) + + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + return data + + def sread_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.read_n(n, selector) + else: + return [] + + def take(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def take_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + data = [] + try: + + nr = self.rt.ddslib.dds_take_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise ("Error while trying to take samples with mask, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take_mask operation, return code = {0}".format(nr)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def stake(self, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take(selector) + else: + return [] + + def stake_n(self, n, selector, timeout): + if self.wait_for_data(selector, timeout): + return self.take_n(n, selector) + else: + return [] + + def take_n(self, n, sample_selector): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + + SampleVec_t = c_void_p * n + samples = SampleVec_t() + nr = self.rt.ddslib.dds_take_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(self.topic.data_type)) + if infos[i].valid_data: + v = sp[0].value.decode(encoding='UTF-8') + data.append(jsonpickle.decode(v)) +# else: +# kh = jsonpickle.decode(sp[0].key.decode(encoding='UTF-8')) +# data.append(kh) + + self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + return zip(data, infos) diff --git a/cdds/reader.py b/cdds/reader.py index 10241d0..1d31b41 100644 --- a/cdds/reader.py +++ b/cdds/reader.py @@ -2,21 +2,31 @@ import jsonpickle from .runtime import Runtime +from cdds import * + +from collections import namedtuple + +_Sample = namedtuple('_Sample', ['data', 'status']) + + @LIVELINESS_CHANGED_PROTO def trampoline_on_liveliness_changed(r, s, a): # print("[python-cdds]:>> Dispatching Liveliness change") Runtime.dispatch_liveliness_changed_listener(r, s) + @DATA_AVAILABLE_PROTO def trampoline_on_data_available(r, a): # print("[python-cdds]:>> Dispatching Data Available ") Runtime.dispatch_data_listener(r) + @SUBSCRIPTION_MATCHED_PROTO def trampoline_on_subscription_matched(e, s, a): # print("[python-cdds]:>> Dispatching Subscription Match") Runtime.dispatch_subscription_matched_listener(e, s) + @SAMPLE_LOST_PROTO def trampoline_on_sample_lost(e, s, a): # print("[python-cdds]:>> Dispatching Sample Lost") @@ -48,38 +58,55 @@ def not_alive_instance_samples(): return c_uint(DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_NO_WRITERS_INSTANCE_STATE) - - -class FlexyReader: - def __init__(self, sub, flexy_topic, flexy_data_listener=None, ps=None): +class Reader (Entity): + def __init__(self, sub, topic, ps=None, data_listener=None): self.rt = Runtime.get_runtime() - self.dp = sub.dp - self.sub = sub - self.flexy_topic = flexy_topic - if flexy_data_listener is None: - self.data_listener = do_nothing - else: - self.data_listener = flexy_data_listener + self.participant = sub.participant + self.parent = sub + self.topic = topic - self.qos = self.rt.to_rw_qos(ps) + self.keygen = self.topic.gen_key - self.subsciption_listener = None - self._liveliness_listener = None + qos = self.rt.to_rw_qos(ps) - self.handle = c_void_p() + self._qos = qos - topic = self.flexy_topic.topic + if data_listener is None: + self.data_listener = do_nothing + else: + self.data_listener = data_listener self.listener_handle = self.rt.ddslib.dds_create_listener(None) - self.rt.ddslib.dds_lset_data_available(self.listener_handle , trampoline_on_data_available) + self.rt.ddslib.dds_lset_data_available(self.listener_handle, trampoline_on_data_available) self.rt.ddslib.dds_lset_liveliness_changed(self.listener_handle, trampoline_on_liveliness_changed) self.rt.ddslib.dds_lset_subscription_matched(self.listener_handle, trampoline_on_subscription_matched) - - self.handle = self.rt.ddslib.dds_create_reader(sub.handle, topic, self.qos, self.listener_handle) + self.handle = self.rt.ddslib.dds_create_reader(sub.handle, self.topic.handle, self.qos, self.listener_handle) assert (self.handle > 0) - self.rt.register_data_listener(self.handle, self.__handle_data) +# self.rt.register_data_listener(self.handle, self.__handle_data) + + @property + def handle(self): + return super(Reader, self).handle + + @handle.setter + def handle(self, entity): + super(Reader, self.__class__).handle.fset(self, entity) + + @property + def participant(self): + return super(Reader, self).participant + @participant.setter + def participant(self, entity): + super(Reader, self.__class__).participant.fset(self, entity) + @property + def qos(self): + return super(Reader, self).qos + + @qos.setter + def qos(self, qos): + super(Reader, self.__class__).qos.fset(self, qos) def on_data_available(self, fun): self.data_listener = fun @@ -115,8 +142,130 @@ def sread(self, selector, timeout): else: return [] - def read(self, selector): - return self.read_n(MAX_SAMPLES, selector) + def read(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + + samples = (c_void_p * MAX_SAMPLES)() + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Read_instance exception whlie return loan rc = {0} operation failed".format(nr)) + return data + + def read_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Read_instance exception whlie return loan rc = {0} operation failed".format(nr)) + return data + + def read_n(self, n): + ivec = (SampleInfo * n)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * n)() + + nr = self.rt.ddslib.dds_read(self.handle, samples, infos, n, n) + + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + return data + + def read_wl(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + nr = self.rt.ddslib.dds_read_wl(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + + if nr < 0: + raise Exception("Read operation with loan failed, return code is {0}".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + + if rc != 0: + raise Exception("Error while return loan, retuen code = {}".format(rc)) + + return data + + def lookup_instance(self, s): + gk = self.keygen(s) + + kh = KeyHolder(gk) + + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + + sample = DDSKeyValue(key.encode(), value.encode()) + result = self.rt.ddslib.dds_lookup_instance(self.handle, byref(sample)) + + print("result ", result) + return result + + def read_instance(self, instacne_handle): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() + + nr = self.rt.ddslib.dds_read_instance(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, c_uint64(instacne_handle)) + + if nr < 0: + raise Exception("Read n = {0} operation failed".format(nr)) + + data = [] + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + + rc = self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + if rc != 0: + raise Exception("Read_instance exception whlie return loan rc = {0} operation failed".format(nr)) + + return data def sread_n(self, n, selector, timeout): if self.wait_for_data(selector, timeout): @@ -124,26 +273,89 @@ def sread_n(self, n, selector, timeout): else: return [] - def read_n(self, n, sample_selector): - ivec = (SampleInfo * n)() + def take(self): + ivec = (SampleInfo * MAX_SAMPLES)() infos = cast(ivec, POINTER(SampleInfo)) - samples = (c_void_p * n)() + samples = (c_void_p * MAX_SAMPLES)() - nr = self.rt.ddslib.dds_read_mask_wl(self.handle, samples, infos, n, sample_selector) + data = [] + try: + + nr = self.rt.ddslib.dds_take(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + return data + + def take_mask(self, mask): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() data = [] - for i in range(nr): - sp = cast(c_void_p(samples[i]), POINTER(self.flexy_topic.data_type)) - if infos[i].valid_data: - v = sp[0].value.decode(encoding='UTF-8') - data.append(jsonpickle.decode(v)) - else: - kh = jsonpickle.decode(sp[0].key.decode(encoding='UTF-8')) - data.append(kh) + try: + + nr = self.rt.ddslib.dds_take_mask(self.handle, samples, infos, MAX_SAMPLES, MAX_SAMPLES, mask) + if nr < 0: + raise ("Error while trying to take samples with mask, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take_mask operation, return code = {0}".format(nr)) + return data + + def take_next(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() - self.rt.ddslib.dds_return_loan(self.handle, samples, nr) + data = [] + try: + + nr = self.rt.ddslib.dds_take_next(self.handle, samples, infos) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + return data + + def read_next(self): + ivec = (SampleInfo * MAX_SAMPLES)() + infos = cast(ivec, POINTER(SampleInfo)) + samples = (c_void_p * MAX_SAMPLES)() - return zip(data, infos) + data = [] + try: + + nr = self.rt.ddslib.dds_read_next(self.handle, samples, infos) + if nr < 0: + raise ("Error while trying to take samples, return code = {0}".format(nr)) + + for i in range(nr): + sp = cast(c_void_p(samples[i]), POINTER(DDSKeyValue)) + if infos[i].valid_data: + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) + except: + raise Exception("Error in take operation, return code = {0}".format(nr)) + return data def stake(self, selector, timeout): if self.wait_for_data(selector, timeout): @@ -151,9 +363,6 @@ def stake(self, selector, timeout): else: return [] - def take(self, selector): - return self.take_n(MAX_SAMPLES, selector) - def stake_n(self, n, selector, timeout): if self.wait_for_data(selector, timeout): return self.take_n(n, selector) @@ -170,18 +379,13 @@ def take_n(self, n, sample_selector): data = [] for i in range(nr): - sp = cast(c_void_p(samples[i]), POINTER(self.flexy_topic.data_type)) + sp = cast(c_void_p(samples[i]), POINTER(self.topic.data_type)) if infos[i].valid_data: - v = sp[0].value.decode(encoding='UTF-8') - data.append(jsonpickle.decode(v)) - else: - kh = jsonpickle.decode(sp[0].key.decode(encoding='UTF-8')) - data.append(kh) + si = infos[i] + data.append(_Sample(jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')), si)) self.rt.ddslib.dds_return_loan(self.handle, samples, nr) - return zip(data, infos) + return data def wait_history(self, timeout): return self.rt.ddslib.dds_reader_wait_for_historical_data(self.handle, timeout) - - diff --git a/cdds/runtime.py b/cdds/runtime.py index b8621ca..39d07eb 100644 --- a/cdds/runtime.py +++ b/cdds/runtime.py @@ -2,6 +2,7 @@ from .dds_binding import * the_runtime = None + class Runtime: @staticmethod def get_runtime(): @@ -19,11 +20,16 @@ def __init__(self): self.ddslib = CDLL(cham_lib_path) self.stublib = CDLL(bit_lib_path) + self.helloworld_lib = CDLL(helloworld_lib_path) self.kv_topic = None self.v_topic = None + # -- Entity Operations -- + self.ddslib.dds_delete.restype = dds_return_t + self.ddslib.dds_delete.argtypes = [dds_entity_t] - + self.ddslib.dds_enable.restype = dds_return_t + self.ddslib.dds_enable.argtypes = [dds_entity_t] # -- Participant Operations -- self.ddslib.dds_create_participant.restype = dds_entity_t self.ddslib.dds_create_participant.argtypes = [dds_domainid_t, dds_qos_p_t, dds_listener_p_t] @@ -41,6 +47,8 @@ def __init__(self): self.ddslib.dds_find_topic.restype = dds_entity_t self.ddslib.dds_find_topic.argtypes = [dds_entity_t, c_char_p] + self.ddslib.dds_get_name.restype = dds_return_t + self.ddslib.dds_get_name.argtypes = [dds_entity_t, c_char_p, c_int] # -- Publisher / Subscriber Operations -- @@ -60,6 +68,9 @@ def __init__(self): self.ddslib.dds_create_reader.restype = dds_entity_t self.ddslib.dds_create_reader.argtypes = [dds_entity_t, dds_entity_t, dds_qos_p_t, dds_listener_p_t] + self.ddslib.dds_lookup_instance.restype = dds_instance_handle_t + self.ddslib.dds_lookup_instance.argtypes = [dds_entity_t, c_void_p] + self.ddslib.dds_reader_wait_for_historical_data.restype = dds_return_t self.ddslib.dds_reader_wait_for_historical_data.argtypes = [dds_entity_t, dds_duration_t] @@ -98,24 +109,43 @@ def __init__(self): self.ddslib.dds_qset_destination_order.argtypes = [dds_qos_p_t, c_uint32] # -- read / take -- + self.ddslib.dds_take.restype = c_int + self.ddslib.dds_take.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_size_t, c_uint32] + + self.ddslib.dds_read.restype = c_int + self.ddslib.dds_read.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_size_t, c_uint32] + self.ddslib.dds_read_mask.restype = c_int self.ddslib.dds_read_mask.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_size_t, c_uint32, c_uint32] self.ddslib.dds_take_mask.restype = c_int self.ddslib.dds_take_mask.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_size_t, c_uint32, c_uint32] - # -- read / take with loan-- + self.ddslib.dds_read_wl.restype = c_int + self.ddslib.dds_read_wl.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_uint32] + self.ddslib.dds_read_mask_wl.restype = c_int self.ddslib.dds_read_mask_wl.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_uint32, c_uint32] + self.ddslib.dds_read_instance.restype = c_int + self.ddslib.dds_read_instance.argstypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_uint32, c_uint32, dds_instance_handle_t] + self.ddslib.dds_take_mask_wl.restype = c_int self.ddslib.dds_take_mask_wl.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo), c_uint32, c_uint32] self.ddslib.dds_return_loan.restype = c_int self.ddslib.dds_return_loan.argtypes = [dds_entity_t, POINTER(c_void_p), c_size_t] + self.ddslib.dds_take_next.restype = c_int + self.ddslib.dds_take_next.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo)] + + self.ddslib.dds_read_next.restype = c_int + self.ddslib.dds_read_next.argtypes = [dds_entity_t, POINTER(c_void_p), POINTER(SampleInfo)] + # -- dispoase -- + self.ddslib.dds_dispose.restype = dds_return_t + self.ddslib.dds_dispose.argtypes = [dds_entity_t, c_void_p] self.ddslib.dds_dispose.restype = dds_return_t self.ddslib.dds_dispose.argtypes = [dds_entity_t, c_void_p] @@ -123,19 +153,15 @@ def __init__(self): self.ddslib.dds_write.restype = dds_return_t self.ddslib.dds_write.argtypes = [dds_entity_t, c_void_p] - # DDS Entity Delete - self.ddslib.dds_delete.restype = dds_return_t - self.ddslib.dds_delete.argtypes = [dds_entity_t] - # -- Waitset Operations -- # create self.ddslib.dds_create_waitset.restype = dds_entity_t self.ddslib.dds_create_waitset.argtypes = [dds_entity_t] - # attach / detach self.ddslib.dds_waitset_attach.restype = dds_return_t self.ddslib.dds_waitset_attach.argtypes = [dds_entity_t, dds_entity_t, dds_attach_t] + self.ddslib.dds_waitset_detach.restype = dds_return_t self.ddslib.dds_waitset_detach.argtypes = [dds_entity_t, dds_entity_t] @@ -147,6 +173,26 @@ def __init__(self): self.ddslib.dds_create_readcondition.restype = dds_entity_t self.ddslib.dds_create_readcondition.argtypes = [dds_entity_t, c_uint32] + self.ddslib.dds_create_querycondition.restype = dds_entity_t + self.ddslib.dds_create_querycondition.argtypes = [dds_entity_t, c_uint32, CFUNCTYPE(c_bool, c_void_p)] + + self.ddslib.dds_create_guardcondition.restype = dds_entity_t + self.ddslib.dds_create_guardcondition.argstypes = [dds_entity_t] + + self.ddslib.dds_get_mask.restype = dds_return_t + self.ddslib.dds_get_mask.argstypes = [dds_entity_t, c_void_p] + + self.ddslib.dds_get_datareader.restype = dds_entity_t + self.ddslib.dds_get_datareader.argstypes = [dds_entity_t] + self.ddslib.dds_set_guardcondition.restype = dds_return_t + self.ddslib.dds_set_guardcondition.argstypes = [dds_entity_t, c_bool] + + self.ddslib.dds_read_guardcondition.restype = dds_return_t + self.ddslib.dds_read_guardcondition.argstypes = [dds_entity_t, POINTER(c_bool)] + + self.ddslib.dds_take_guardcondition.restype = dds_return_t + self.ddslib.dds_take_guardcondition.argstypes = [dds_entity_t, POINTER(c_bool)] + # -- Listeners -- self.ddslib.dds_create_listener.restype = dds_listener_p_t self.ddslib.dds_create_listener.argtypes = [c_void_p] @@ -208,13 +254,18 @@ def dispatch_liveliness_changed_listener(handle, s): fun = the_runtime.livelinessChangeListenerMap[h] fun(handle, s) - def get_key_value_type_support(self): return self.stublib.dds_bit_SKeySValue_desc def get_simple_value_type_support(self): return self.stublib.dds_bit_SValue_desc + def get_hello_world_key_value_type_support(self): + return self.helloworld_lib.HelloWorldDataMsg_keys + + def get_hello_world_simple_value_type_support(self): + return self.helloworld_lib.HelloWorldData_Msg_desc + def to_rw_qos(self, ps): if ps is None: return None @@ -238,7 +289,6 @@ def to_rw_qos(self, ps): self.ddslib.dds_qset_destination_order(qos, p.kind) return qos - def to_ps_qos(self, ps): if ps is None: return None @@ -261,7 +311,6 @@ def create_dds_qos(self): def release_dds_qos(self, qos): self.ddslib.dds_delete_qos(qos) - def close(self): # Magic value is DDS_CYCLONEDDS_HANDLE, so this tears down # the entire Cyclone run-time in a supported way once that diff --git a/cdds/sub.py b/cdds/sub.py index 5080ac0..138e5de 100644 --- a/cdds/sub.py +++ b/cdds/sub.py @@ -1,7 +1,22 @@ from .runtime import Runtime -from .policy import Partition +from .policy import Partition +from cdds import * + +from cdds.reader import * + + +class Subscriber(Entity): + def __init__(self, dp, ps=None, listener=None): + self.rt = Runtime.get_runtime() + self.participant = dp + self.parent = dp + self.handle = self.rt.ddslib.dds_create_subscriber(dp.handle, ps, listener) + # qos = self.rt.ddslib.dds_set_qos(self.handle, self.qos) + self.qos = ps + self._datareader_list = [] + + assert (self.handle is not None and self.handle > 0) -class Subscriber: @staticmethod def partitions(ps): return [Partition(ps)] @@ -10,12 +25,27 @@ def partitions(ps): def partition(p): return [Partition([p])] - def __init__(self, dp, ps = None): - self.rt = Runtime.get_runtime() - self.dp = dp - qos = None - if ps is not None: - qos = self.rt.to_ps_qos(ps) + @property + def handle(self): + return super(Subscriber, self).handle + + @handle.setter + def handle(self, entity): + super(Subscriber, self.__class__).handle.fset(self, entity) + + @property + def participant(self): + return super(Subscriber, self).participant + + @participant.setter + def participant(self, entity): + super(Subscriber, self.__class__).participant.fset(self, entity) + + def create_reader(self, topic, policy=None, dr_listener=None): + data_reader = Reader(self, topic, policy, dr_listener) + self._datareader_list.append(data_reader) + return data_reader - self.handle = self.rt.ddslib.dds_create_subscriber(self.dp.handle, qos, None) - assert (self.handle > 0) + def _check_handle(self): + if super().handle is None: + raise Exception('Entity is already closed') diff --git a/cdds/topic.py b/cdds/topic.py index e6ac6c2..41de96b 100644 --- a/cdds/topic.py +++ b/cdds/topic.py @@ -1,38 +1,96 @@ from .runtime import Runtime from .dds_binding import DDSKeyValue +from ctypes import * + +from cdds import * +from cdds.entity import * + +MAX_NAME_SIZE = 100 + class TopicType(object): - def gen_key(self): None + def gen_key(self): + pass -class FlexyTopic: - def __init__(self, dp, name, keygen=None, qos=None): +class Topic(Entity): + def __init__(self, dp, topic_name, type_support, data_type=None, qos=None): self.rt = Runtime.get_runtime() + self._name = topic_name.encode() + self.type_support = type_support + + self._qos = self.rt.to_rw_qos(qos) + self.handle = self.rt.ddslib.dds_create_topic(dp.handle, type_support, topic_name.encode(), self.qos, None) + + self.parent = dp + self.participant = dp + + keygen = None + if keygen is None: self.keygen = lambda x: x.gen_key() else: self.keygen = keygen - self.qos = self.rt.to_rw_qos(qos) - self.type_support = self.rt.get_key_value_type_support() - self.topic = self.rt.ddslib.dds_create_topic(dp.handle, self.type_support , name.encode(), self.qos, None) - self.handle = self.topic - assert (self.topic > 0) - self.data_type = DDSKeyValue - self.dp = dp + self.data_type = self.type_name() + + assert (self.handle > 0) def gen_key(self, s): return self.keygen(s) + def get_name(self): + res = " " * MAX_NAME_SIZE + result = res.encode(encoding='utf_8', errors='strict') + rc = self.rt.ddslib.dds_get_name(self.handle, result, MAX_NAME_SIZE) + + if(rc >= 0): + return str(result.decode()).split('\x00', 1)[0] + else: + return "" + + @property + def name(self): + return self._name.decode() -class Topic: - def __init__(self, dp, topic_name, type_support, data_type, qos): + @name.setter + def name(self, topic_name_str): + self._name = topic_name_str + + @property + def qos(self): + return self._qos + + @qos.setter + def qos(self, other_qos): + self._qos = other_qos + + def type_name(self): + res = " " * MAX_NAME_SIZE + result = res.encode(encoding='utf_8', errors='strict') + rc = self.rt.ddslib.dds_get_type_name(self.handle, result, MAX_NAME_SIZE) + + if(rc >= 0): + return str(result.decode()).split('\x00', 1)[0] + else: + return "" + + @property + def handle(self): + return super(Topic, self).handle + + @handle.setter + def handle(self, entity): + super(Topic, self.__class__).handle.fset(self, entity) + + def _check_handle(self): + if super().handle is None: + raise Exception('Entity is already closed') + + +class FoundTopic (Topic): + def __init__(self, participant): self.rt = Runtime.get_runtime() - self.topic_name = topic_name - self.type_support = type_support - self.data_type = data_type - self.qos = self.rt.to_rw_qos(qos) - self.topic = self.rt.ddslib.dds_create_topic(dp.handle, type_support, topic_name.encode(), self.qos, None) - self.handle = self.topic - assert (self.handle > 0) + self.participant = participant + self.parent = participant diff --git a/cdds/waitset.py b/cdds/waitset.py index 1472645..0e829b2 100644 --- a/cdds/waitset.py +++ b/cdds/waitset.py @@ -1,25 +1,47 @@ +from cdds import * from ctypes import * from .runtime import Runtime -# The current waitset implementation has the limitation that can wait -# on a single condition. -class WaitSet(object): - def __init__(self, dp, condition): + +class WaitSet(Entity): + def __init__(self, dp, condition=None): self.rt = Runtime.get_runtime() - self.handle = c_void_p(self.rt.ddslib.dds_create_waitset(dp.handle)) - self.condition = condition - self.rt.ddslib.dds_waitset_attach(self.handle, self.condition, None) + self.handle = self.rt.ddslib.dds_create_waitset(dp.handle) + self.conditions = [] + if condition is not None: + self.conditions.append(condition) + self.attach(condition) def close(self): self.rt.ddslib.dds_waitset_detach(self.handle, self.condition) self.rt.ddslib.dds_delete(self.handle) - def wait(self, timeout): - # we only have one condition + def wait(self, timeout=dds_infinity()): cs = (c_void_p * 1)() pcs = cast(cs, c_void_p) - s = self.rt.ddslib.dds_waitset_wait(self.handle, byref(pcs), 1, timeout) - if s == 0: - return False - else: - return True \ No newline at end of file + s = self.rt.ddslib.dds_waitset_wait(self.handle, byref(pcs), 100, timeout) + + return s + + def attach(self, condition): + rc = self.rt.ddslib.dds_waitset_attach(self.handle, condition.handle, c_void_p(None)) + if rc != 0: + raise Exception("attach n = {0} operation failed".format(rc)) + + self.conditions.append(condition) + return True + + def detach(self, condition): + rc = self.rt.ddslib.dds_waitset_detach(self.handle, condition.handle) + if rc != 0: + raise Exception("detach n = {0} operation failed".format(rc)) + self.conditions.remove(condition) + return True + + @property + def conditions(self): + return self._conditions + + @conditions.setter + def conditions(self, condition_list): + self._conditions = condition_list diff --git a/cdds/writer.py b/cdds/writer.py index b6ccac5..5f55d20 100644 --- a/cdds/writer.py +++ b/cdds/writer.py @@ -2,15 +2,55 @@ from .dds_binding import * import jsonpickle -class FlexyWriter: - def __init__(self, pub, flexy_topic, ps = None): - self.rt = Runtime.get_runtime() - self.dp = pub.dp - self.qos = self.rt.to_rw_qos(ps) - self.handle = self.rt.ddslib.dds_create_writer(pub.handle, flexy_topic.topic, self.qos, None) +from cdds import * + +class Writer (Entity): + def __init__(self, pub, topic, ps=None, listener=None): + self.rt = Runtime.get_runtime() + self.participant = pub.participant + self.parent = pub + self.topic = topic + qos = self.rt.to_rw_qos(ps) + self.keygen = self.topic.gen_key + self._qos = qos + self.listener = listener + self.handle = self.rt.ddslib.dds_create_writer(pub.handle, topic.handle, self.qos, self.listener) assert (self.handle > 0) - self.keygen = flexy_topic.gen_key + + @property + def handle(self): + return super(Writer, self).handle + + @handle.setter + def handle(self, entity): + super(Writer, self.__class__).handle.fset(self, entity) + + @property + def participant(self): + return super(Writer, self).participant + + @participant.setter + def participant(self, entity): + super(Writer, self.__class__).participant.fset(self, entity) + + @property + def qos(self): + return super(Writer, self).qos + + @qos.setter + def qos(self, qos): + super(Writer, self.__class__).qos.fset(self, qos) + + def lookup_instance(self, s): + gk = self.keygen(s) + kh = KeyHolder(gk) + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + sample = DDSKeyValue(key.encode(), value.encode()) + result = self.rt.ddslib.dds_lookup_instance(self.handle, byref(sample)) + + return result def write(self, s): gk = self.keygen(s) @@ -18,35 +58,35 @@ def write(self, s): key = jsonpickle.encode(kh) value = jsonpickle.encode(s) sample = DDSKeyValue(key.encode(), value.encode()) - self.rt.ddslib.dds_write(self.handle, byref(sample)) + rc = self.rt.ddslib.dds_write(self.handle, byref(sample)) + if rc != 0: + raise(Exception("Write failed")) + return rc def write_all(self, xs): for x in xs: self.write(x) - def dispose_instance(self, s): + def dispose(self, s): gk = self.keygen(s) kh = KeyHolder(gk) key = jsonpickle.encode(kh) value = jsonpickle.encode(s) sample = DDSKeyValue(key.encode(), value.encode()) - self.rt.ddslib.dds_dispose(self.handle, byref(sample)) - + rc = self.rt.ddslib.dds_dispose(self.handle, byref(sample)) + if rc != 0: + raise Exception("Dispose operation failed, return code = {0}".format(rc)) -class Writer: - def __init__(self, pub, topic, ps = None): - self.rt = Runtime.get_runtime() - self.dp = pub.dp - self.qos = self.rt.to_rw_qos(ps) - self.handle = self.rt.ddslib.dds_create_writer(pub.handle, topic.topic, self.qos, None) - assert (self.handle > 0) + return rc - def write(self, s): - self.rt.ddslib.dds_write(self.handle, byref(s)) - - def write_all(self, xs): - for x in xs: - self.write(x) + def write_dispose(self, s): + gk = self.keygen(s) + kh = KeyHolder(gk) + key = jsonpickle.encode(kh) + value = jsonpickle.encode(s) + sample = DDSKeyValue(key.encode(), value.encode()) + rc = self.rt.ddslib.dds_writedispose(self.handle, byref(sample)) + if rc != 0: + raise Exception("Dispose operation failed, return code = {0}".format(rc)) - def dispose_instance(self, s): - self.rt.ddslib.dds_dispose(self.handle, byref(s)) + return rc diff --git a/configure b/configure index f3d3e9f..30ec1f4 100755 --- a/configure +++ b/configure @@ -1,14 +1,18 @@ # -*-Makefile-*- #!/bin/bash +set -ev if [ "$(uname)" == "Darwin" ]; then - BIT_LIB=libddstubs.dylib -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then - BIT_LIB=libddstubs.so + STUB_LIB=libddstubs.dylib + BIT_LIB=libddsbit.dylib + HELLO_LIB=libddshelloworld.dylib +elif [ "$(uname -s)" == "Linux" ]; then + STUB_LIB=libddstubs.so + BIT_LIB=libddsbit.so + HELLO_LIB=libddshelloworld.so fi -pushd &> /dev/null cd bit rm -Rf build mkdir build @@ -16,9 +20,12 @@ cd build cmake .. make if [ "$(uname)" == "Darwin" ]; then + cp ${STUB_LIB} /usr/local/lib cp ${BIT_LIB} /usr/local/lib -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then + cp ${HELLO_LIB} /usr/local/lib +elif [ "$(uname -s)" == "Linux" ]; then + sudo cp ${STUB_LIB} /usr/local/lib sudo cp ${BIT_LIB} /usr/local/lib + sudo cp ${HELLO_LIB} /usr/local/lib fi -popd &> /dev/null \ No newline at end of file diff --git a/examples/helloworld/reader.py b/examples/helloworld/reader.py new file mode 100644 index 0000000..437a923 --- /dev/null +++ b/examples/helloworld/reader.py @@ -0,0 +1,42 @@ +__author__ = 'ADlink Technology' + +from cdds import * +import time + + +class HelloWorldMessage(FlexyTopic): + def __init__(self, userID, messageText): + super(FlexyTopic, self).__init__() + self.userID = userID + self.message = messageText + + def gen_key(self): + return self.userID + + def __str__(self): + return 'HelloWorldMessage(userID: {0}, message: {1})'.format(self.userID, self.message) + + +def subscriber(): + dp = Participant(0) + + topic = FlexyTopic(dp, 'HelloWorldData_Msg') + + subscriber = dp.create_subscriber() + + dataReader = FlexyReader(subscriber, topic, None, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + + print('reader>> waiting for a message!') + + while True: + time.sleep(5) + + samples = dataReader.take(all_samples()) + + for sample in samples: + if sample[1].valid_data: + print('message >> {0})'.format(sample[0])) + + +if __name__ == '__main__': + subscriber() diff --git a/examples/helloworld/writer.py b/examples/helloworld/writer.py new file mode 100644 index 0000000..0348937 --- /dev/null +++ b/examples/helloworld/writer.py @@ -0,0 +1,39 @@ +__author__ = 'ADlink Technology' + +from cdds import * +import time + + +class HelloWorldMessage(FlexyTopic): + def __init__(self, userID, messageText): + super(FlexyTopic, self).__init__() + self.userID = userID + self.message = messageText + + def gen_key(self): + return self.userID + + def __str__(self): + return 'HelloWorldMessage(userID: {0}, message: {1})'.format(self.userID, self.message) + + +def publsiher(): + dp = Participant(0) + + topic = FlexyTopic(dp, 'HelloWorldData_Msg') + publisher = dp.create_publisher() + + writer = FlexyWriter(publisher, topic, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + + cnt = 0 + + while True: + message = HelloWorldMessage(((cnt % 2) + 1), 'Hello World {0}'.format(cnt)) + cnt += 1 + writer.write(message) + print('Writer wrote: {0}'.format(message)) + time.sleep(1) + + +if __name__ == '__main__': + publsiher() diff --git a/f05log.py b/f05log.py index ffd0e91..cab07d7 100644 --- a/f05log.py +++ b/f05log.py @@ -3,16 +3,19 @@ from fog05.interfaces.Types import * import sys + def cache_discovered(dr): - for (s, i) in dr.take(all_samples()): + for(s, i) in dr.take(all_samples()): if i.valid_data: print(str(s)) + def cache_discovery_event(r, s): print("Cache discovery event") + def log_samples(dr): - for (s, i) in dr.take(all_samples()): + for(s, i) in dr.take(all_samples()): if i.valid_data: print(str(s)) @@ -82,15 +85,16 @@ def start_tlog(root): hitmv_topic = FlexyTopic(dp, "FOSStoreHitMV") hitmv_writer = FlexyWriter(pub, - hitmv_topic, - DDS_Event) + hitmv_topic, + DDS_Event) hitmv_reader = FlexyReader(sub, - hitmv_topic, + hitmv_topic, log_samples, DDS_Event) -if __name__=='__main__': + +if __name__ == '__main__': if len(sys.argv) > 1: start_tlog(sys.argv[1]) print("Press 'x' or 'X' to exit...") diff --git a/requirements.txt b/requirements.txt index 9f7a8db..e2e3789 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,8 @@ -jsonpickle>=0.0.0 -pytest>=3.0 -flake8>=3.0 -nose>=1.3.7 -coverage>=4.1 -mock>=1.3.0 -mvar>=0.0.1 \ No newline at end of file +#jsonpickle>=0.0.0 +#unittest>=0.0.0 +#pytest>=3.0 +#flake8>=3.0 +#nose>=1.3.7 +#coverage>=4.1 +#mock>=1.3.0 +#mvar>=0.0.1 \ No newline at end of file diff --git a/setup.py b/setup.py index 0dd8895..5019457 100644 --- a/setup.py +++ b/setup.py @@ -8,5 +8,5 @@ packages=['cdds', ], author='kydos', url='https://github.com/atolab/python-cdds', - install_requires=['jsonpickle'] + install_requires=['jsonpickle', 'idl_parser'] ) diff --git a/test_flexy_reader.py b/test_flexy_reader.py index 7091091..db59baf 100644 --- a/test_flexy_reader.py +++ b/test_flexy_reader.py @@ -3,7 +3,9 @@ from cdds import * import time -# TODO: Factor out the definition of Vehicle position... +# TODO:Factor out the definition of Vehicle position... + + class VehiclePosition(Topic): def __init__(self, cid): super(Topic, self).__init__() @@ -25,21 +27,24 @@ def moveBy(self, dx, dy): def __str__(self): return 'VehiclePosition({0}, {1}, {2})'.format(self.key_, self.x, self.y) + def data_available(r): print('reader>> Listenerr Called!') samples = r.take(all_samples()) for s in samples: if s[1].valid_data: - print ('reader>> {0})'.format(s[0])) + print('reader>> {0})'.format(s[0])) + def liveliness_changed(r, e): print(">>>>> Changed Liveliness!!") + def testDynaTypes(): rt = Runtime() dp = Participant(0) - t = FlexyTopic(dp, 'KeyValue') + t = FlexyTopic(dp, 'KeyValue') dr = FlexyReader(dp, t, data_available, [Reliable(), KeepLastHistory(10)]) dr.on_liveliness_changed(liveliness_changed) @@ -52,5 +57,6 @@ def testDynaTypes(): while True: time.sleep(60) + if __name__ == '__main__': testDynaTypes() diff --git a/test_flexy_writer.py b/test_flexy_writer.py index d4a72ac..f2e86b6 100644 --- a/test_flexy_writer.py +++ b/test_flexy_writer.py @@ -1,9 +1,9 @@ +from random import randint +import sys +import time +from cdds import * _author__ = 'Angelo Corsaro' -from cdds import * -import time -import sys -from random import randint class VehiclePosition(Topic): def __init__(self, cid): @@ -26,6 +26,7 @@ def moveBy(self, dx, dy): def __str__(self): return 'VehiclePosition({0}, {1}, {2})'.format(self.key_, self.x, self.y) + if __name__ == '__main__': cid = randint(0, 1000) @@ -41,7 +42,7 @@ def __str__(self): # print("Reliable id = {0}".format(Reliable().id)) # print("KeepLastHistory id = {0}".format(KeepLastHistory(1).id)) # 'VehiclePosition' - t = FlexyTopic(dp, 'KeyValue') #, None, [Reliable(),Persistent(), KeepLastHistory(1)]) + t = FlexyTopic(dp, 'KeyValue') # , None, [Reliable(),Persistent(), KeepLastHistory(1)]) # p = Publisher(dp, 'cdds-python.demo') w = FlexyWriter(dp, t, [Reliable(), KeepLastHistory(10)]) @@ -50,11 +51,10 @@ def __str__(self): dx = 1 dy = 1 - - while (True): + while(True): w.write(vpos) - print('Wrote: {0}'.format(vpos)) + print('Wrote:{0}'.format(vpos)) vpos.moveBy(dx, dy) time.sleep(1) - #print('Press a key to move the vehicle...') - #input() + # print('Press a key to move the vehicle...') + # input() diff --git a/test_sread.py b/test_sread.py index 0270f99..8af5d7f 100644 --- a/test_sread.py +++ b/test_sread.py @@ -1,9 +1,11 @@ __author__ = 'Angelo Corsaro' from cdds import * -import time +import time + +# TODO:Factor out the definition of Vehicle position... + -# TODO: Factor out the definition of Vehicle position... class VehiclePosition: def __init__(self, cid): self.x = 0 @@ -24,11 +26,12 @@ def moveBy(self, dx, dy): def __str__(self): return 'VehiclePosition({0}, {1}, {2})'.format(self.key_, self.x, self.y) + def testDynaTypes(): rt = Runtime() dp = Participant(0) - t = FlexyTopic(dp, 'KeyValue') + t = FlexyTopic(dp, 'KeyValue') # s = Subscriber(dp, [Partition(['cdds-python.demo'])]) dr = FlexyReader(dp, t) @@ -36,7 +39,8 @@ def testDynaTypes(): while True: samples = dr.stake(new_samples(), dds_secs(3)) for s in samples: - print ('reader>> {0})'.format(s[0])) + print('reader>> {0})'.format(s[0])) + if __name__ == '__main__': testDynaTypes() diff --git a/tests/example.idl b/tests/example.idl new file mode 100644 index 0000000..9561d75 --- /dev/null +++ b/tests/example.idl @@ -0,0 +1,9 @@ +module HelloWorldData +{ + struct Msg + { + long userID; + string message; + }; + #pragma keylist Msg userID +}; diff --git a/tests/helloworld.idl b/tests/helloworld.idl new file mode 100644 index 0000000..b4ac0fa --- /dev/null +++ b/tests/helloworld.idl @@ -0,0 +1,9 @@ +module HelloWorldData +{ + struct Msg + { + long userID; + string message; + }; + #pragma keylist Msg userID +}; \ No newline at end of file diff --git a/tests/testBasic.py b/tests/testBasic.py new file mode 100644 index 0000000..d0df807 --- /dev/null +++ b/tests/testBasic.py @@ -0,0 +1,15 @@ +import unittest +from cdds import * + +__author__ = 'ADlink Technology' + + +class BasicTestCase(unittest.TestCase): + def test_participant(self): + dp = Participant(0) + self.assertTrue(dp is not None) + self.assertIsInstance(dp, Participant) + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testEntity.py b/tests/testEntity.py new file mode 100644 index 0000000..42e12a1 --- /dev/null +++ b/tests/testEntity.py @@ -0,0 +1,90 @@ +import unittest + +from cdds import * + +__author__ = 'ADlink Technology' + + +class EntityTest(unittest.TestCase): + def setUp(self): + self.rt = Runtime.get_runtime() + + def test_create_entity(self): + e = Participant(0) + self.assertIsNotNone(e, "Created entity is not initialized correctly") + self.assertIsInstance(e, Entity, "Created object is not of the correct type") + + def test_set_parent_get_parent(self): + dp = Participant(0) + self.assertEqual(dp, dp.parent) + + topic_name = 'topic_name' + + topic = dp.create_topic(topic_name) + parent_entity = topic.parent + self.assertIsNotNone(parent_entity, " Get parent on a topic entity returned null") + self.assertEqual(parent_entity, dp) + + pub = dp.create_publisher() + parent_entity = pub.participant + self.assertIsNotNone(parent_entity, " Get parent on a publisher entity returned null") + self.assertEqual(parent_entity, dp, "Get parent on a publisher entity a wrong entity") + + sub = dp.create_subscriber() + parent_entity = sub.parent + self.assertIsNotNone(parent_entity, " Get parent on a subscriber entity returned null") + self.assertEqual(dp, parent_entity, "Get parent on a subscriber entity returned a wrong entity") + + dw = pub.create_writer(topic) + parent_entity = dw.parent + self.assertIsNotNone(parent_entity, " Get parent on a datawriter entity returned null") + self.assertEqual(parent_entity, pub, "Get parent on a datawriter entity a wrong entity") + + dr = sub.create_reader(topic) + parent_entity = dr.parent + self.assertIsNotNone(parent_entity, " Get parent on a datareader entity returned null") + self.assertEqual(parent_entity, sub, "Get parent on a datareader entity a wrong entity") + + def test_get_participant(self): + dp = Participant(0) + + entity = dp.participant + + self.assertEqual(dp, entity) + + topic_name = 'topic_name' + + topic = dp.create_topic(topic_name) + entity = topic.participant + + self.assertIsNotNone(entity, " Get participant on a topic entity returned null") + self.assertIsInstance(entity, Participant, "Get participant returned an entity of an invalid type") + self.assertEqual(entity, dp, "Get participant on a topic entity returned a wrong result") + + pub = dp.create_publisher() + entity = pub.participant + self.assertIsNotNone(entity, " Get participant on a publisher entity returned null") + self.assertIsInstance(entity, Participant, "Get participant returned an entity of an invalid type") + self.assertEqual(entity, dp, "Get participant on a publisher entity a wrong entity") + + sub = dp.create_subscriber() + entity = sub.participant + self.assertIsNotNone(entity, " Get participant on a subscriber entity returned null") + self.assertIsInstance(entity, Participant, "Get participant returned an entity of an invalid type") + self.assertEqual(dp, entity, "Get participant on a subscriber entity returned a wrong entity") + + dw = pub.create_writer(topic) + entity = dw.participant + self.assertIsNotNone(entity, " Get participant on a datawriter entity returned null") + self.assertIsInstance(entity, Participant, "Get participant returned an entity of an invalid type") + self.assertEqual(entity, dp, "Get participant on a datawriter entity a wrong entity") + + dr = sub.create_reader(topic) + entity = dr.participant + self.assertIsNotNone(entity, " Get participant on a datareader entity returned null") + self.assertIsInstance(entity, Participant, "Get participant returned an entity of an invalid type") + self.assertEqual(entity, dp, "Get participant on a datareader entity a wrong entity") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testGaurdCondition.py b/tests/testGaurdCondition.py new file mode 100644 index 0000000..73a4700 --- /dev/null +++ b/tests/testGaurdCondition.py @@ -0,0 +1,104 @@ +import unittest + +from cdds import * + +from idl_parser import parser + +parser_ = parser.IDLParser() + + +__author__ = 'ADlink Technology' + + +class GaurdConditionTest(unittest.TestCase): + def setUp(self): + self.helloworld_lib = CDLL(helloworld_lib_path) + + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + + topic_name = "HelloWorldData_Msg" + # type_support = self.get_hello_world_simple_value_type_support() + type_support = self.rt.get_key_value_type_support() + + self.topic = self.dp.create_topic(topic_name, type_support) + + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + def tearDown(self): + self.rt.close() + + def testInitGaurdCond(self): + gc = GaurdCondition(self.dp) + + self.assertIsNotNone(gc, "Gaurd condition is not initialized correctly") + self.assertIsInstance(gc, GaurdCondition, "Created gaurd condition is not of the good type") + + def testSetGuardCond(self): + gc = GaurdCondition(self.dp) + + self.assertIsNotNone(gc, "Gaurd condition is not initialized correctly") + self.assertIsInstance(gc, GaurdCondition, "Created gaurd condition is not of the good type") + + rt = gc.set_guard_condition(True) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + rt = gc.set_guard_condition(False) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + def testReadGuardCond(self): + gc = GaurdCondition(self.dp) + + self.assertIsNotNone(gc, "Gaurd condition is not initialized correctly") + self.assertIsInstance(gc, GaurdCondition, "Created gaurd condition is not of the good type") + + rt = gc.set_guard_condition(True) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + triggered = gc.read_trigger() + + self.assertIsNotNone(triggered, " read guard condition did not get expected object") + self.assertTrue(triggered, "Read gaurdCondition did not return expected value") + + rt = gc.set_guard_condition(False) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + triggered = gc.read_trigger() + + self.assertIsNotNone(triggered, " read guard condition did not get expected object") + self.assertFalse(triggered, "Read gaurdCondition did not return expected value") + + def testTakeGuardCond(self): + gc = GaurdCondition(self.dp) + + self.assertIsNotNone(gc, "Gaurd condition is not initialized correctly") + self.assertIsInstance(gc, GaurdCondition, "Created gaurd condition is not of the good type") + + rt = gc.set_guard_condition(True) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + triggered = gc.take_trigger() + + self.assertIsNotNone(triggered, " take guard condition did not get expected object") + self.assertTrue(triggered, "Take gaurdCondition did not return expected value") + + triggered = gc.read_trigger() + + self.assertIsNotNone(triggered, " read guard condition did not get expected object") + self.assertFalse(triggered, "Read gaurdCondition did not return expected value") + + rt = gc.set_guard_condition(False) + self.assertTrue(rt, "set_gaurdcondition did not return the expected result") + + triggered = gc.take_trigger() + + self.assertIsNotNone(triggered, " take guard condition did not get expected object") + self.assertFalse(triggered, "take gaurdCondition did not return expected value") + + triggered = gc.read_trigger() + + self.assertIsNotNone(triggered, " read guard condition did not get expected object") + self.assertFalse(triggered, "Read gaurdCondition did not return expected value") diff --git a/tests/testParticipant.py b/tests/testParticipant.py new file mode 100644 index 0000000..f49946a --- /dev/null +++ b/tests/testParticipant.py @@ -0,0 +1,70 @@ +import unittest + +__author__ = 'ADlink Technology' + +from cdds.participant import Participant +from cdds.runtime import Runtime +import cdds.py_dds_utils as utils + + +class ParticipantBasicTest (unittest.TestCase): + def setUp(self): + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.topic_name = "topic_name" + self.type_support = self.rt.get_key_value_type_support() + self.topic = self.dp.create_topic(self.topic_name, self.type_support) + + def test_create_participant(self): + """ + Test that the participant can be created successfully + """ + participant = Participant(0) + self.assertTrue(participant is not None) + self.assertIsInstance(participant, Participant) + + def test_create_topic(self): + """ + test create topic + """ + other_topic_name = "other_topic_name" + other_topic = self.dp.create_topic(other_topic_name, self.type_support) + self.assertTrue(other_topic is not None, "Could not create topic") + + def test_find_topic(self): + """ + test find topic + """ + foundTopic = self.dp.find_topic("topic_name") + if(foundTopic is not None): + topic_to_test = utils._FoundTopic_Init(self.dp, foundTopic) + else: + topic_to_test = None + found_topic_name = topic_to_test.get_name() + self.assertTrue(topic_to_test is not None, + "Found topic should not be none") + # self.assertEqual(self.topic.topic, foundTopic, "Find topic failed") + self.assertEqual(self.topic.name, found_topic_name, + "Find using name failed") + + def test_create_publisher(self): + """ + Test create publisher + """ + participant = Participant(0) + pub = participant.create_publisher() + self.assertTrue(pub is not None) + self.assertTrue(pub.handle > 0, "Failed to create a publisher") + + def test_create_subscriber(self): + """ + Test create subscriber + """ + participant = Participant(0) + sub = participant.create_subscriber() + self.assertTrue(sub is not None) + self.assertTrue(sub.handle > 0, "Failed to create a subscriber") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testPublisher.py b/tests/testPublisher.py new file mode 100644 index 0000000..0643774 --- /dev/null +++ b/tests/testPublisher.py @@ -0,0 +1,39 @@ +import unittest + +from cdds import * + +__author__ = 'ADlink Technology' + + +class PublisherTest(unittest.TestCase): + def setUp(self): + self.rt = Runtime.get_runtime() + self.participant = Participant(0) + self.publisher = Publisher(self.participant) + + def test_initialize_subscriber(self): + dp = Participant(0) + pub = Publisher(dp) + self.assertIsNotNone(pub, "Publisher is not created correctly") + self.assertIsInstance(pub, Publisher, "Create publisher didn't produce an entity of the food type") + + def test_create_writer(self): + topic_name = "topic_name" + type_support = self.rt.get_key_value_type_support() + topic = Topic(self.participant, topic_name, type_support) + datawriter_ps = [Reliable(), KeepLastHistory(10)] + datawriter = self.publisher.create_writer(topic, datawriter_ps) + + self.assertIsNotNone(datawriter, "Create_writer failed") + self.assertIsInstance(datawriter, Writer, "Create_datawriter created an entity of a wrong type") + + def test_suspend_resume(self): + rc = self.publisher.suspend() + self.assertEqual(rc, -2, "Suspend did not return the correct return code") + + rc = self.publisher.resume() + self.assertEqual(rc, -2, "Resume did not return the correct return code") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testQueryCondition.py b/tests/testQueryCondition.py new file mode 100644 index 0000000..7c273dc --- /dev/null +++ b/tests/testQueryCondition.py @@ -0,0 +1,692 @@ +import unittest +from ctypes import c_bool, c_void_p + +import jsonpickle + +from cdds import * + +import sys + +from idl_parser import parser + +import cdds.py_dds_utils as utils + +import time + +__author__ = 'ADlink Technology' + +parser_ = parser.IDLParser() + + +class QueryConditionTest(unittest.TestCase): + def setUp(self): + self.helloworld_lib = CDLL(helloworld_lib_path) + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + + topic_name = "HelloWorldData_Msg" + type_support = self.rt.get_key_value_type_support() + self.topic = self.dp.create_topic(topic_name, type_support) + + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + MYFUNCTYPE = CFUNCTYPE(c_bool, c_void_p) + self.my_c_func = MYFUNCTYPE(self.filter) + self.message_c_func = MYFUNCTYPE(self.filter_message) + + def tearDown(self): + self.rt.close() + + def test_init_QueryCondition(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + self.assertIsNotNone(cond, "QueryCondition creation failed") + self.assertIsInstance(cond, QueryCondition, "Query condition is not of the good type") + + def test_get_mask(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + res_mask = cond.get_mask() + self.assertIsNotNone(res_mask, "get mask returned a not valid object") + self.assertEqual(res_mask.value, c_uint(mask).value, "get_msk retuened a wrong_value {0} != {1}".format(res_mask, mask)) + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + res_mask = cond.get_mask() + self.assertIsNotNone(res_mask, "get mask returned a not valid object") + self.assertEqual(res_mask.value, c_uint(mask).value, "get_msk retuened a wrong_value {0} != {1}".format(res_mask, mask)) + + def test_get_reader(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + handle = cond.get_reader_handle() + self.assertIsNotNone(handle, " get_reader_handle returned an invalid handle") + self.assertEqual(handle, self.reader.handle, " get_reader_handle returned wrong handle") + + def test_read(self): + print("Begin test_read") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + for i in range(0, 5): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(0, 5), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + mask = DDS_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + mask2 = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + cond2 = QueryCondition(self.reader, mask2, self.message_c_func) + + msg = HelloWorldData_Msg(userID=1, message="new message ") + print("Writer >> Begin writeing data") + self.writer.write_dispose(msg) + time.sleep(5) + + print('query_condition >> begin read loop!') + print('mask = DDS_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE') + print('Cond userID % 2 = 0') + cnt_samples = 0 + sample_read = False + while(not sample_read): + time.sleep(1) + try: + samples = cond.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertIn(val_.userID, range(0, 5), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + for i in range(0, 3): + newMsg = HelloWorldData_Msg(userID=i, message="new message {0}".format(i)) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error during write operation") + msg = HelloWorldData_Msg(userID=3, message="new message ") + print("Writer >> Begin writeing data") + self.writer.write_dispose(msg) + time.sleep(5) + + print('query_condition >> begin read loop!') + print('mask2 = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE') + print('Cond message.find("new")!= -1 ') + cnt_samples = 0 + sample_read = False + while(not sample_read): + time.sleep(1) + try: + samples = cond2.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID == 3, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 1, "read_condition: read samples are not as expected") + + def test_read_n(self): + print("Begin test_read_n") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + for i in range(10, 15): + newMsg = HelloWorldData_Msg(userID=i, message="new message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + print("rc = ", rc) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + sample_read = False + print('cond >> begin read loop!') + cnt_samples = 0 + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_n(2) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s.status.valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in {10, 12}, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 2, "Different number read by read_n(2)") + cond2 = QueryCondition(self.reader, mask, self.message_c_func) + sample_read = False + print('cond >> begin read loop!') + cnt_samples = 0 + while(not sample_read): + time.sleep(1) + try: + samples = cond2.read_n(3) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s.status.valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in {11, 13, 14}, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 3, "Different number read by read_n(2)") + + def test_read_mask(self): + print("Begin test_read_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + print("Writer >> Begin writeing data") + + for i in range(30, 35): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + + time.sleep(5) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + read_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ANY_INSTANCE_STATE + print('cond >> begin read loop!(read_mask = {0}, mask = {1})'.format(read_mask, mask)) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_mask(read_mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].view_state=", s[1].view_state) + print("s[1].instance_state=", s[1].instance_state) + print("s[1].sample_state=", s[1].sample_state) + self.assertTrue(val_.userID in range(30, 35), "unexpected message read") + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + self.assertEqual(s[1].view_state, DDS_NEW_VIEW_STATE, "Read samples does not have the expected view_state, userID={0}".format(val_.userID)) + except: + raise Exception("Invalid data received") + self.assertEqual(cnt_samples, 3, "Wrong number of samples read") + + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + + for i in range(30, 40): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error while write operation") + + msg = HelloWorldData_Msg(userID=32, message="new message to dispose 32") + print("Writer >> Begin writing dispose data") + self.writer.write_dispose(msg) + + msg = HelloWorldData_Msg(userID=37, message="new message to dispose 35") + print("Writer >> Begin writing dispose data") + + self.writer.write_dispose(msg) + time.sleep(5) + + # All read samples will have sample_state = not_read, + # and will have view_state = DDS_NEW_VIEW_STATE + # and instance_state = DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + read_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!(read_mask = {0}, mask = {1})'.format(read_mask, mask)) + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_mask(read_mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(30, 40), "unexpected message read val_.userID={0}".format(val_.userID)) + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + self.assertEqual(s[1].view_state, DDS_NEW_VIEW_STATE, "ViewState is not correct") + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + + def test_read_instacne(self): + print("Begin test_read_instance") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + for i in range(60, 65): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + + cnt_samples = 0 + sample_read = False + print('cond>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + self.assertTrue(val_.userID in {60, 62, 64}, "Read message has an invalid key {0}".format(val_.userID)) + + except: + print("Invalid data read") + self.assertEqual(cnt_samples, 3, "Wrong numbe of samples read") + data = newMsg + print(">>>>>>>>>>>>>>>>>>>>>>>> data =", data) + inst_hdl = cond.lookup_instance(data) + + print("inst_hdl = ", inst_hdl) + + for i in range(60, 70): + newMsg = HelloWorldData_Msg(userID=i, message="second message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + self.assertIsNotNone(inst_hdl, "Instance handle is not valid a valid handle") + cnt_samples = 0 + sample_read = False + print('reader>> begin read_instance loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_instance(inst_hdl) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID is data.userID, "Read message has an invalid key {0}".format(val_.userID)) + self.assertEqual(s[1].instance_handle, inst_hdl, "Instacne handle of read sample is not the same as the one found in lookup_instance") + else: + print("No samples read") + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 1, "read samples are not as expected") + + def test_take(self): + print("Begin test_take") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + for i in range(100, 105): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertTrue(s[1].view_state | DDS_NOT_NEW_VIEW_STATE, "ViewState is not correct") + + self.assertTrue(val_.userID in {100, 102, 104}, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + self.assertEqual(cnt_samples, 3, "read samples are not as expected") + for i in range(100, 110): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in {106, 108}, "Read message has an invalid key {0}".format(val_.userID)) + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertTrue(s[1].view_state | DDS_NEW_VIEW_STATE, "ViewState is not correct") + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + self.assertEqual(cnt_samples, 2, "read samples are not as expected") + + def test_take_mask(self): + print("Begin test_take_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + print("Writer >> Begin writeing data") + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = QueryCondition(self.reader, mask, self.my_c_func) + + for i in range(120, 125): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + + time.sleep(5) + + take_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ANY_INSTANCE_STATE + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take_mask(take_mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + except: + print("Error occured while trying to read data while testing read_mask") + + print("Writer >> Begin writeing data") + for i in range(120, 130): + newMsg = HelloWorldData_Msg(userID=i, message="new message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred while write operation, file: __FILE__ on line __LINE__") + time.sleep(5) + + sample = HelloWorldData_Msg(userID=123, message="message to dispose") + self.writer.write_dispose(sample) + + sample = HelloWorldData_Msg(userID=127, message="message to dispose") + self.writer.write_dispose(sample) + time.sleep(5) + + # mask used in take_mask is mask | take_mask + take_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + + cnt_samples = 0 + sample_read = False + print('cond.take_mask >> begin read loop!') + print('test take_mask(\"DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE| DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE\"') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take_mask(take_mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print('s[1].sample_state = {0}'.format(s[1].sample_state)) + print('s[1].instance_state {0}'.format(s[1].instance_state)) + + self.assertTrue(val_.userID in {126, 128}, "unexpected message read userID={0}".format(val_.userID)) + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + + except: + raise Exception("Invalid data received") + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + + mask2 = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + cond2 = QueryCondition(self.reader, mask2, self.message_c_func) + + # 3 samples are read, but one of them is disposed + + mask_take = DDS_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + print("mask2 = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE") + print('mask_take = DDS_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE') + + cnt_samples = 0 + sample_read = False + print('cond 2 >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond2.take_mask(mask_take) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID in {123, 127}, "unexpected message read") + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state") + except: + raise Exception("Invalid data received") + # All samplse are taken now, there is only the disposed samples with userId =113 + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + + def filter(self, s): + sp = cast(c_void_p(s), POINTER(DDSKeyValue)) + result = False + if(sp[0].value is not None and sp[0].key is not None): + sam = jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')) + # val_ = (HelloWorldData_Msg)(**sam) + key = sam['userID'] + result = (key > 0) and (key % 2 == 0) + + return result + + def filter_message(self, s): + sp = cast(c_void_p(s), POINTER(DDSKeyValue)) + result = False + if(sp[0].value is not None and sp[0].key is not None): + sam = jsonpickle.decode(sp[0].value.decode(encoding='UTF-8')) + # val_ = (HelloWorldData_Msg)(**sam) + key = sam['message'] + result = (key.find('new') is not -1) + return result + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testReadCondition.py b/tests/testReadCondition.py new file mode 100644 index 0000000..9bde7e2 --- /dev/null +++ b/tests/testReadCondition.py @@ -0,0 +1,588 @@ +__author__ = 'ADlink Technology' +import time +import unittest +from cdds import * +import cdds.py_dds_utils as utils +from idl_parser import parser + +parser_ = parser.IDLParser() + + +class ReadConditionTest(unittest.TestCase): + def setUp(self): + self.helloworld_lib = CDLL(helloworld_lib_path) + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + topic_name = "HelloWorldData_Msg" + # type_support = self.get_hello_world_simple_value_type_support() + type_support = self.rt.get_key_value_type_support() + self.topic = self.dp.create_topic(topic_name, type_support) + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + def test_init_readCondition(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + self.assertIsNotNone(cond, "ReadCondition creation faild") + + def test_get_mask(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + res_mask = cond.get_mask() + + self.assertIsNotNone(res_mask, "get mask returned a not valid object") + self.assertEqual(res_mask.value, c_uint(mask).value, "get_msk retuened a wrong_value {0} != {1}".format(res_mask, mask)) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + res_mask = cond.get_mask() + + self.assertIsNotNone(res_mask, "get mask returned a not valid object") + self.assertEqual(res_mask.value, c_uint(mask).value, "get_msk retuened a wrong_value {0} != {1}".format(res_mask, mask)) + + def test_get_reader(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + + handle = cond.get_reader_handle() + + self.assertIsNotNone(handle, " get_reader_handle returned an invalid handle") + self.assertEqual(handle, self.reader.handle, " get_reader_handle returned wrong handle") + + def test_read(self): + print("Begin test_read") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + for i in range(0, 5): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred dring write operation in __FILE__ on line: __LINE__") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(0, 5), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + msg = HelloWorldData_Msg(userID=1, message="Message to dispose") + print("Writer >> Begin writeing data") + self.writer.write_dispose(msg) + time.sleep(5) + print('read>_condition >> begin read loop!') + cnt_samples = 0 + sample_read = False + while(not sample_read): + time.sleep(1) + try: + samples = cond.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID is msg.userID, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + self.assertEqual(cnt_samples, 2, "read_condition: read samples are not as expected") + + def test_read_n(self): + print("Begin test_read_n") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + for i in range(10, 15): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + time.sleep(5) + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + sample_read = False + print('cond >> begin read loop!') + cnt_samples = 0 + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_n(2) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s.status.valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(10, 15), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 2, "Diferent number read by read_n(2)b") + + def test_read_mask(self): + print("Begin test_read_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + print("Writer >> Begin writeing data") + + for i in range(30, 33): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred dring write operation in __FILE__ on line: __LINE__") + + time.sleep(5) + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ANY_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + read_mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE + print('cond >> begin read loop!(read_mask = {0}, mask = {1})'.format(read_mask, mask)) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_mask(read_mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].view_state=", s[1].view_state) + print("s[1].instance_state=", s[1].instance_state) + print("s[1].sample_state=", s[1].sample_state) + + self.assertTrue(val_.userID in range(30, 33), "unexpected message read") + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 3, "Wrong number of samples read") + + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + for i in range(30, 36): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred dring write operation in __FILE__ on line: __LINE__") + msg = HelloWorldData_Msg(userID=32, message="Message to dispose 32") + print("Writer >> Begin writing dispose data") + self.writer.write_dispose(msg) + msg = HelloWorldData_Msg(userID=35, message="Message to dispose 35") + print("Writer >> Begin writing dispose data") + self.writer.write_dispose(msg) + time.sleep(5) + # All read samples will have sample_state = not_read, + # bau will have view_state = DDS_NEW_VIEW_STATE | DDS_NOT_NEW_VIEW_STATE + # and instance_state = DDS_ALIVE_INSTANCE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + read_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NOT_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!(read_mask = {0}, mask = {1})'.format(read_mask, mask)) + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_mask(read_mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].view_state=", s[1].view_state) + print("s[1].instance_state=", s[1].instance_state) + print("s[1].sample_state=", s[1].sample_state) + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertTrue(val_.userID in range(30, 36), "unexpected message read val_.userID={0}".format(val_.userID)) + if val_.userID == 32 or val_.userID == 35: + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state") + else: + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + if val_.userID < 33 and val_.userID != 32: + self.assertEqual(s[1].view_state, DDS_NOT_NEW_VIEW_STATE, "ViewState is not correct") + elif(val_.userID == 32): + self.assertTrue(s[1].view_state | DDS_NOT_NEW_VIEW_STATE, "ViewState is not correct") + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + else: + self.assertEqual(s[1].view_state, DDS_NEW_VIEW_STATE, "ViewState is not correct") + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 8, "Wrong number of samples read") + + def test_read_instacne(self): + print("Begin test_read_instance") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + + for i in range(60, 65): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('cond>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + self.assertTrue(val_.userID in range(60, 65), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + + self.assertEqual(cnt_samples, 5, "Wrong numbe of samples read") + data = newMsg + + inst_hdl = cond.lookup_instance(data) + + print("inst_hdl = ", inst_hdl) + + for i in range(60, 65): + newMsg = HelloWorldData_Msg(userID=i, message="second message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + self.assertIsNotNone(inst_hdl, "Instance handle is not valid a valid handle") + cnt_samples = 0 + sample_read = False + print('reader>> begin read_instance loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.read_instance(inst_hdl) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID is data.userID, "Read message has an invalid key {0}".format(val_.userID)) + self.assertEqual(s[1].instance_handle, inst_hdl, "Instacne handle of read sample is not the same as the one found in lookup_instance") + else: + print("No samples read") + + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 1, "read samples are not as expected") + + def test_take(self): + print("Begin test_read") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_NEW_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + + for i in range(100, 105): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertTrue(s[1].view_state | DDS_NOT_NEW_VIEW_STATE, "ViewState is not correct") + self.assertTrue(val_.userID in range(100, 105), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + + for i in range(100, 110): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('cond >> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + + self.assertTrue(val_.userID in range(105, 110), "Read message has an invalid key {0}".format(val_.userID)) + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state") + self.assertTrue(s[1].sample_state | DDS_NOT_READ_SAMPLE_STATE, "sample_state is not correct") + self.assertTrue(s[1].view_state | DDS_NOT_NEW_VIEW_STATE, "ViewState is not correct") + + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + + def test_take_mask(self): + print("Begin test_take_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + print("Writer >> Begin writeing data") + + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + cond = ReadCondition(self.reader, mask) + + for i in range(110, 113): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + + time.sleep(5) + + take_mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ANY_INSTANCE_STATE + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take_mask(take_mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + except: + print("Error occured while trying to read data while testing read_mask") + + print("Writer >> Begin writeing data") + for i in range(113, 116): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred dring write operation in __FILE__ on line: __LINE__") + time.sleep(5) + + sample = HelloWorldData_Msg(userID=113, message="message to dispose") + self.writer.write_dispose(sample) + time.sleep(5) + + # mask used in take_mask is mask | take_mask + take_mask = DDS_READ_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_ALIVE_INSTANCE_STATE + + cnt_samples = 0 + sample_read = False + print('cond.take_mask >> begin read loop!') + print('test take_mask(\"DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE| DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE\"') + while(not sample_read): + time.sleep(1) + try: + samples = cond.take_mask(take_mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print('s[1].sample_state = {0}'.format(s[1].sample_state)) + print('s[1].instance_state {0}'.format(s[1].instance_state)) + + self.assertTrue(val_.userID in range(113, 116), "unexpected message read userID={0}".format(val_.userID)) + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + + except: + raise Exception("Invalid data received") + + # 3 samples are read, but one of them is disposed + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.take_mask(mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertEqual(val_.userID, 113, "unexpected message read") + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state") + + except: + raise Exception("Invalid data received") + # All samplse are taken now, there is only the disposed samples with userId =113 + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testReader.py b/tests/testReader.py new file mode 100644 index 0000000..2cfdb6b --- /dev/null +++ b/tests/testReader.py @@ -0,0 +1,650 @@ +import unittest + +from cdds import * + +from idl_parser import parser + +import cdds.py_dds_utils as utils + +import time + +__author__ = 'ADlink Technology' + +parser_ = parser.IDLParser() + + +class DataReaderTest(unittest.TestCase): + def setUp(self): + self.helloworld_lib = CDLL(helloworld_lib_path) + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + topic_name = "HelloWorldData_Msg" + # type_support = self.get_hello_world_simple_value_type_support() + type_support = self.rt.get_key_value_type_support() + self.topic = self.dp.create_topic(topic_name, type_support) + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + def test_init_reader(self): + print("Begin test_init_reader") + self.assertIsNotNone(self.reader, "Initializing the data_writer failed") + self.assertIsInstance(self.reader, Reader) + + def test_read(self): + print("Begin test_read") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + newMsg = HelloWorldData_Msg(userID=1, message="Other message") + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred during write operation") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID is newMsg.userID, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + + self.assertEqual(cnt_samples, 1, "read samples are not as expected") + + def test_read_n(self): + print("Begin test_read_n") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + for i in range(10, 15): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + time.sleep(5) + sample_read = False + print('reader>> begin read loop!') + cnt_samples = 0 + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_n(2) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s.status.valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + print("sam = ", sam) + print("type(sam) = ", type(sam)) + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(10, 15), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 2, "Diferent number read by read_n(2) b") + + def test_read_mask(self): + print("Begin test_read_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + print("Writer >> Begin writeing data") + for i in range(30, 33): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + time.sleep(5) + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_mask(mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + except: + print("Error occured while trying to read data while testing read_mask") + print("Writer >> Begin writeing data") + for i in range(33, 36): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "An error occurred while write operation") + time.sleep(5) + sample = HelloWorldData_Msg(userID=33, message="message to dispose") + self.writer.dispose(sample) + time.sleep(5) + mask = DDS_NOT_READ_SAMPLE_STATE | DDS_ALIVE_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_mask(mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(30, 36), "unexpected message read") + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + except: + raise Exception("Invalid data received") + self.assertEqual(cnt_samples, 2, "Wrong number of samples read") + mask = DDS_ANY_SAMPLE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE | DDS_ANY_VIEW_STATE + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_mask(mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertEqual(val_.userID, 33, "unexpected message read") + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state") + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 1, "Wrong number of samples read") + + def test_read_wl(self): + print("Begin test_read_wl") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + for i in range(50, 55): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_wl() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID in range(50, 55), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + + # FIXME: Correct the implementation of this test + def test_read_instacne(self): + print("Begin test_read_instance") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + for i in range(60, 65): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + self.assertTrue(val_.userID in range(60, 65), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + self.assertEqual(cnt_samples, 5, "Wrong numbe of samples read") + data = newMsg + print(">>>>>>>>>>>>>>>>>>>>>>>> data =", data) + inst_hdl = self.reader.lookup_instance(data) + print("inst_hdl = ", inst_hdl) + self.assertIsNotNone(inst_hdl, "Instance handle is not valid a valid handle") + cnt_samples = 0 + sample_read = False + print('reader>> begin read_instance loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_instance(inst_hdl) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID is data.userID, "Read message has an invalid key {0}".format(val_.userID)) + self.assertEqual(s[1].instance_handle, inst_hdl, "Instance handle of read sample is not the same as the one found in lookup_instance") + else: + print("No samples read") + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 1, "read samples are not as expected") + + def test_take(self): + print("Begin test_read") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + for i in range(100, 105): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.take() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle ", s[1].instance_handle) + + self.assertTrue(val_.userID in range(100, 105), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + self.assertEqual(cnt_samples, 5, "read samples are not as expected") + + def test_take_mask(self): + print("Begin test_take_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + print("Writer >> Begin writeing data") + + for i in range(110, 113): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + + time.sleep(5) + + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_mask(mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + except: + print("Error occured while trying to read data while testing read_mask") + + print("Writer >> Begin writeing data") + for i in range(113, 116): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "An error occurred during write operation") + time.sleep(5) + + sample = HelloWorldData_Msg(userID=113, message="message to dispose") + self.writer.dispose(sample) + time.sleep(5) + + mask = DDS_READ_SAMPLE_STATE | DDS_ALIVE_INSTANCE_STATE | DDS_ANY_VIEW_STATE + + cnt_samples = 0 + sample_read = False + print('reader.take_mask >> begin read loop!') + print('test take_mask(\"DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE| DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE\"') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.take_mask(mask) + if samples is not None: + print("samples is not none") + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + print("valid sample") + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print('s[1].sample_state = {0}'.format(s[1].sample_state)) + print('s[1].instance_state {0}'.format(s[1].instance_state)) + + self.assertTrue(val_.userID in range(110, 113), "unexpected message read userID={0}".format(val_.userID)) + self.assertEqual(s[1].sample_state, DDS_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 3, "Wrong number of samples read") + mask = DDS_ANY_SAMPLE_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE | DDS_ANY_VIEW_STATE + + print("Test read with mask DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE ") + + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.take_mask(mask) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertEqual(val_.userID, 113, "unexpected message read") + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state") + + except: + raise Exception("Invalid data received") + + self.assertEqual(cnt_samples, 1, "Wrong number of samples read") + + def test_take_next(self): + print("Begin test_read_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + print("Writer >> Begin writeing data") + for i in range(70, 80): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation failed") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_n(2) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(70, 80)) + except: + print("Error occured while trying to read data while testing read_mask") + self.assertEqual(cnt_samples, 2) + sample = HelloWorldData_Msg(userID=75, message="message to dispose") + rc = self.writer.dispose(sample) + self.assertEqual(rc, 0, "Dispose operation failed") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.take_next() + if samples is not None and len(samples) > 0: + self.assertEqual(len(samples), 1, "More samples read(len(samples) = {0} > 1)".format(len(samples))) + samples_as_list = list(samples) + + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + sam = s[0] + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID in range(70, 80), "unexpected message read") + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + if val_.userID != 75: + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + else: + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + else: + sample_read = True + except: + raise Exception("Invalid data received") + self.assertEqual(cnt_samples, 8, "Wrong number of samples read") + + def test_read_next(self): + print("Begin test_read_mask") + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + print("Writer >> Begin writeing data") + for i in range(80, 90): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("written sample {0} ".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation failed") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_n(2) + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(80, 90)) + except: + print("Error occured while trying to read data while testing read_mask") + self.assertEqual(cnt_samples, 2) + sample = HelloWorldData_Msg(userID=85, message="message to dispose") + rc = self.writer.dispose(sample) + self.assertEqual(rc, 0, "Dispose operation failed") + time.sleep(5) + cnt_samples = 0 + sample_read = False + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_next() + if samples is not None and len(samples) > 0: + self.assertEqual(len(samples), 1, "More samples read(len(samples) = {0} > 1)".format(len(samples))) + samples_as_list = list(samples) + + for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + print("scanning sample_list") + if s[0] is not None and s[1].valid_data: + sam = s[0] + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + self.assertTrue(val_.userID in range(80, 90), "unexpected message read") + self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + if val_.userID != 85: + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + else: + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read samples does not have the expected instance_state, userID={0}".format(val_.userID)) + else: + sample_read = True + except: + raise Exception("Invalid data received") + self.assertEqual(cnt_samples, 8, "Wrong number of samples read") + + def get_hello_world_key_value_type_support(self): + return self.helloworld_lib.HelloWorldDataMsg_keys + + def get_hello_world_simple_value_type_support(self): + return self.helloworld_lib.HelloWorldData_Msg_desc + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testSequence.py b/tests/testSequence.py new file mode 100644 index 0000000..2662134 --- /dev/null +++ b/tests/testSequence.py @@ -0,0 +1,64 @@ +import unittest +from cdds import * +import time + +__author__ = 'ADlink Technology' + + +class SequqnceTypeTopic(FlexyTopic): + def __init__(self, longID, longSequence): + super(FlexyTopic, self).__init__() + self.longID = longID + self.longSequence = longSequence + + def gen_key(self): + return self.longID + + def __str__(self): + return 'SequenceMessage(longID: {0}, longSequence: {1})'.format(self.longID, self.longSequence) + + +class BasicTestCase(unittest.TestCase): + def test_sendReceive(self): + dp = Participant(0) + + self.assertTrue(dp is not None) + self.assertIsInstance(dp, Participant) + + topic = FlexyTopic(dp, 'Sequence_Topic') + publisher = Publisher(dp) + writer = FlexyWriter(publisher, topic, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + + cnt = 0 + message = SequqnceTypeTopic(1, [21, 32, 43]) + + cnt += 1 + + writer.write(message) + print('Writer wrote: {0}'.format(message)) + time.sleep(1) + + topic_reader = FlexyTopic(dp, 'Sequence_Topic') + + subscriber = Subscriber(dp) + + dataReader = FlexyReader(subscriber, topic_reader, None, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + + print('reader>> waiting for a message!') + + messageReceived = False + + while not messageReceived: + print(messageReceived) + time.sleep(1) + samples = dataReader.take(all_samples()) + + for sample in samples: + if sample[1].valid_data: + print('message >> {0})'.format(sample[0])) + self.assertEqual(sample[0].longID, message.longID, "received sample is not correct") + messageReceived = True + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testSequenceOfStructArray.py b/tests/testSequenceOfStructArray.py new file mode 100644 index 0000000..a0282c9 --- /dev/null +++ b/tests/testSequenceOfStructArray.py @@ -0,0 +1,104 @@ +import unittest +from struct import * +from cdds import * +import time + +__author__ = 'ADlink Technology' + + +class Inner_Struct(FlexyTopic): + def __init__(self, short, double): + super(FlexyTopic, self).__init__() + self.short1 = short + self.double1 = double + + def gen_key(self): + return self.short1 + + def __str__(self): + return 'InnerSeq({0}, {1})'.format(self.short1, self.double1) + + def __eq__(self, other): + if not isinstance(other, Inner_Struct): + # don't attempt to compare against unrelated types + return NotImplemented + + return self.short1 == other.short1 and self.double1 == other.double1 + __repr__ = __str__ + + +class Inner_Struct_Array(FlexyTopic): + def __init__(self, seq): + super(FlexyTopic, self).__init__() + self.SeqArray = seq + + def __str__(self): + return format('Inner_Struct_Array {self.SeqArray}') + + def __getitem__(self, item_number): + return self.SeqArray[item_number] + + def __eq__(self, other): + if not isinstance(other, Inner_Struct_Array): + # don't attempt to compare against unrelated types + return NotImplemented + cnt = 0 + for elem in self.SeqArray: + if elem != other.SeqArray[cnt]: + return False + cnt += 1 + return True + + +class SequenceOfStructArray_struct(FlexyTopic): + def __init__(self, longID, arraySequence): + super(FlexyTopic, self).__init__() + self.longID = longID + self.arraySequence = Inner_Struct_Array(arraySequence) + + def gen_key(self): + return self.longID + + def __str__(self): + return 'SequenceMessage(longID: {0}, InnerArraySeq: {1})'.format(self.longID, self.arraySequence) + + +class BasicTestCase(unittest.TestCase): + def test_sendReceive(self): + dp = Participant(0) + self.assertTrue(dp is not None) + self.assertIsInstance(dp, Participant) + topic = FlexyTopic(dp, 'Sequence_struct_Topic') + publisher = Publisher(dp) + writer = FlexyWriter(publisher, topic, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + + message = SequenceOfStructArray_struct( + 13, + ([ + [Inner_Struct(11, 1.1), Inner_Struct(12, 1.2)], + [Inner_Struct(21, 2.1), Inner_Struct(22, 2.2)], + [Inner_Struct(31, 3.1), Inner_Struct(32, 3.2)] + ])) + + writer.write(message) + print('Writer wrote: {0}'.format(message)) + time.sleep(1) + + topic_reader = FlexyTopic(dp, 'Sequence_struct_Topic') + subscriber = Subscriber(dp) + dataReader = FlexyReader(subscriber, topic_reader, None, [Reliable(), TransientLocal(), KeepLastHistory(10)]) + print('reader>> waiting for a message!') + messageReceived = False + while not messageReceived: + time.sleep(1) + samples = dataReader.take(all_samples()) + for sample in samples: + if sample[1].valid_data: + print('received message >> {0})'.format(sample[0])) + self.assertEqual(message.longID, sample[0].longID) + self.assertEqual(message.arraySequence[0], sample[0].arraySequence[0]) + messageReceived = True + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testSubscriber.py b/tests/testSubscriber.py new file mode 100644 index 0000000..19232ff --- /dev/null +++ b/tests/testSubscriber.py @@ -0,0 +1,31 @@ +import unittest +from cdds import * + +__author__ = 'ADlink Technology' + + +class SubscriberTest(unittest.TestCase): + def setUp(self): + self.rt = Runtime.get_runtime() + self.participant = Participant(0) + self.subscriber = Subscriber(self.participant) + + def test_initialize_subscriber(self): + dp = Participant(0) + sub = Subscriber(dp) + self.assertIsNotNone(sub, "Subscriber is not created correctly") + self.assertIsInstance(sub, Subscriber, "Create subscriber didn't produce an entity of the food type") + + def test_create_reader(self): + topic_name = "topic_name" + type_support = self.rt.get_key_value_type_support() + topic = Topic(self.participant, topic_name, type_support) + datareader_ps = [Reliable(), KeepLastHistory(10)] + datareader = self.subscriber.create_reader(topic, datareader_ps) + + self.assertIsNotNone(datareader, "Create_reader failed") + self.assertIsInstance(datareader, Reader, "Create_dataReader created an entity of a wrong type") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testTopic.py b/tests/testTopic.py new file mode 100644 index 0000000..cf9e968 --- /dev/null +++ b/tests/testTopic.py @@ -0,0 +1,38 @@ +__author__ = 'ADlink Technology' + +import unittest +from cdds import * +from cdds.py_dds_utils import * + + +class TopicTest(unittest.TestCase): + def setUp(self): + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.name = "topic_name" + self.type_support = self.rt.get_hello_world_simple_value_type_support() + self.topic = Topic(self.dp, self.name, self.type_support, None, None) + + def tearDown(self): + self.dp.rt.close() + pass + + def test_create_topic_based_on_topic_desc(self): + """ + test create topic desc + """ + self.assertTrue(self.topic is not None, "Create Topic failed") + self.assertIsInstance(self.topic, Topic, "created topic is not of the valid class(Topic)") + +# def test_try_gen_class(self): +# get_dds_classes_from_idl('/home/firas/cyclone/cdds_python/tests/example.idl', 'HelloWorldData.Msg') +# # self.assertTrue(gen_info is not None) + + def test_get_type_name(self): + expected_topic_name = "HelloWorldData::Msg" + get_name = self.topic.type_name() + self.assertEqual(get_name, expected_topic_name, "Wrong topic type name returned ") + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tests/testWaitset.py b/tests/testWaitset.py new file mode 100644 index 0000000..dc9224d --- /dev/null +++ b/tests/testWaitset.py @@ -0,0 +1,128 @@ +import unittest +from cdds import * +from idl_parser import parser +import cdds.py_dds_utils as utils + +__author__ = 'ADlink Technology' + +parser_ = parser.IDLParser() + + +class WaitsetTest(unittest.TestCase): + def setUp(self): + + self.helloworld_lib = CDLL(helloworld_lib_path) + + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + + topic_name = "HelloWorldData_Msg" + # type_support = self.get_hello_world_simple_value_type_support() + type_support = self.rt.get_key_value_type_support() + + self.topic = self.dp.create_topic(topic_name, type_support) + + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + def tearDown(self): + self.rt.close() + + def test_init_Waitset(self): + ws0 = WaitSet(self.dp) + self.assertIsNotNone(ws0, "Waitset Constructor created an invalid object") + self.assertIsInstance(ws0, WaitSet, "Waitset constructor created an object of not expected type") + + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + self.assertIsNotNone(cond, "ReadCondition creation faild") + + ws = WaitSet(self.dp, cond) + self.assertIsNotNone(ws, "Waitset Constructor created an invalid object") + self.assertIsInstance(ws, WaitSet, "Waitset constructor created an object of not expected type") + + def test_attach(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + self.assertIsNotNone(cond, "ReadCondition creation failed") + + ws = WaitSet(self.dp) + self.assertIsNotNone(ws, "Waitset Constructor created an invalid object") + self.assertIsInstance(ws, WaitSet, "Waitset constructor created an object of not expected type") + + rc = ws.attach(cond) + self.assertTrue(rc, "Attach did not return the expected result") + + cond_list = ws.conditions + self.assertIsNotNone(cond_list, "Attached conditions of the waitset after attach operation is an invalid value") + self.assertIn(cond, cond_list, "Condition is not attached to the condition list as expected") + + def test_detach(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + self.assertIsNotNone(cond, "ReadCondition creation failed") + + ws = WaitSet(self.dp) + self.assertIsNotNone(ws, "Waitset Constructor created an invalid object") + self.assertIsInstance(ws, WaitSet, "Waitset constructor created an object of not expected type") + + rc = ws.attach(cond) + self.assertTrue(rc, "Attach did not return the expected result") + + cond_list = ws.conditions + self.assertIsNotNone(cond_list, "Attached conditions of the waitset after attach operation is an invalid value") + self.assertIn(cond, cond_list, "Condition is not attached to the condition list as expected") + + rc = ws.detach(cond) + self.assertTrue(rc, "Attach did not return the expected result") + + cond_list = ws.conditions + self.assertIsNotNone(cond_list, "Attached conditions of the waitset after attach operation is an invalid value") + self.assertNotIn(cond, cond_list, "Condition is not attached to the condition list as expected") + + def test_wait(self): + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond = ReadCondition(self.reader, mask) + self.assertIsNotNone(cond, "ReadCondition creation failed") + + ws = WaitSet(self.dp) + self.assertIsNotNone(ws, "Waitset Constructor created an invalid object") + self.assertIsInstance(ws, WaitSet, "Waitset constructor created an object of not expected type") + + rc = ws.attach(cond) + self.assertTrue(rc, "Attach did not return the expected result") + cond_list = ws.conditions + self.assertIsNotNone(cond_list, "Attached conditions of the waitset after attach operation is an invalid value") + self.assertIn(cond, cond_list, "Condition is not attached to the condition list as expected") + + rc = ws.wait(dds_secs(1)) + + self.assertEqual(rc, 0, "The number of triggered entity is not correct") + + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + i = 1 + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + rc = ws.wait(dds_secs(5)) + + self.assertEqual(rc, 1, "The number of triggered entity is not correct") + + mask1 = DDS_NOT_READ_SAMPLE_STATE | DDS_ANY_INSTANCE_STATE | DDS_ANY_VIEW_STATE + cond1 = ReadCondition(self.reader, mask1) + self.assertIsNotNone(cond1, "ReadCondition creation failed") + + rc = ws.attach(cond1) + + i = 2 + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + + rc = ws.wait(dds_secs(5)) + self.assertEqual(rc, 2, "The number of triggered entity is not correct") diff --git a/tests/testWriter.py b/tests/testWriter.py new file mode 100644 index 0000000..a91ef16 --- /dev/null +++ b/tests/testWriter.py @@ -0,0 +1,268 @@ +import unittest + +from cdds import * + +from idl_parser import parser + +import cdds.py_dds_utils as utils + +import time + +__author__ = 'ADlink Technology' +parser_ = parser.IDLParser() + + +class DataWriterTest(unittest.TestCase): + def setUp(self): + self.helloworld_lib = CDLL(helloworld_lib_path) + + self.rt = Runtime.get_runtime() + self.dp = Participant(0) + self.pub = Publisher(self.dp) + self.sub = Subscriber(self.dp) + + topic_name = "HelloWorldData_Msg" + # type_support = self.get_hello_world_simple_value_type_support() + type_support = self.rt.get_key_value_type_support() + + self.topic = self.dp.create_topic(topic_name, type_support) + + self.writer = Writer(self.pub, self.topic, [Reliable(), KeepLastHistory(10)]) + self.reader = Reader(self.sub, self.topic, [Reliable(), KeepLastHistory(10)]) + + def test_init_writer(self): + self.assertIsNotNone(self.writer, "Initializing the data_writer failed") + self.assertIsInstance(self.writer, Writer) + + def get_hello_world_key_value_type_support(self): + # return self.helloworld_lib.HelloWorldDataMsg_keys + return self.writer.rt.get_key_value_type_support + + def get_hello_world_simple_value_type_support(self): + return self.helloworld_lib.HelloWorldData_Msg_desc + + def test_write(self): + idl_path = '/tmp/example.idl' + + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + newMsg = HelloWorldData_Msg(userID=1, message="Other message") + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Error occurred during write operation") + print("Writer >> Writing data completed") + time.sleep(5) + sample_read = False + cnt_samples = 0 + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data and x[0] and x[0] != '', samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + if sam is not None: + cnt_samples += 1 + print("sam =", sam) + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + + self.assertTrue(val_.userID is newMsg.userID, "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + def test_writedispose(self): + idl_path = '/tmp/example.idl' + + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + + for i in range(10, 20): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + + time.sleep(5) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + print("Writer >> Writing data completed") + time.sleep(5) + sample_read = False + cnt_samples = 0 + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data and x[0] and x[0] != '', samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + if sam is not None: + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle = ", s[1].instance_handle) + self.assertTrue(val_.userID in range(10, 20), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + sample_to_dispose = HelloWorldData_Msg(userID=13, message="Other message 13") + rc = self.writer.write_dispose(sample_to_dispose) + self.assertEqual(rc, 0, "dispose instance failed") + time.sleep(5) + print("Sample disposed") + sample_read = False + cnt_samples = 0 + mask = DDS_ANY_SAMPLE_STATE | DDS_ANY_VIEW_STATE | DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE + print('reader>> begin read loop!') + print("cnt_samples ", cnt_samples) + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read_mask(mask) + print("here 1") + if samples is not None: + print("here 2") + samples_as_list = list(samples) + print("samples ", samples) + print("samples_as_list ", samples_as_list) + # for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + for s in list(samples_as_list): + print("here 3") + if s[0] is not None and s[1].valid_data: + print("here 4") + sample_read = True + sam = s[0] + if sam is not None: + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle = ", s[1].instance_handle) + print("s[1].instance_state = ", s[1].instance_state) + if(val_.userID != 13): + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read message has an invalid instacne_state {0}".format(s[1].instance_state)) + self.assertEqual(s[1].sample_state, DDS_READ_SAMPLE_STATE, "Read samples does not have the good mask") + else: + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read message has an invalid instacne_state {0}".format(s[1].instance_state)) + # self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask") + self.assertTrue(val_.userID in range(10, 20), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + def test_dispose(self): + idl_path = '/tmp/example.idl' + className = "HelloWorldData_Msg" + HelloWorldData_Msg = utils.create_class(className, idl_path) + for i in range(30, 40): + newMsg = HelloWorldData_Msg(userID=i, message="Other message {0}".format(i)) + print("Writer >> Begin writeing data {0}".format(newMsg)) + rc = self.writer.write(newMsg) + self.assertEqual(rc, 0, "Write operation did not succeed") + time.sleep(1) + time.sleep(5) + print("Writer >> Begin writeing data") + rc = self.writer.write(newMsg) + print("Writer >> Writing data completed") + time.sleep(5) + sample_read = False + cnt_samples = 0 + print('reader>> begin read loop!') + while(not sample_read): + time.sleep(1) + try: + samples = self.reader.read() + if samples is not None: + samples_as_list = list(samples) + for s in list(filter(lambda x: x[1].valid_data and x[0] and x[0] != '', samples_as_list)): + if s[0] is not None and s[1].valid_data: + sample_read = True + sam = s[0] + if sam is not None: + cnt_samples += 1 + + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle = ", s[1].instance_handle) + self.assertTrue(val_.userID in range(30, 40), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + sample_to_dispose = HelloWorldData_Msg(userID=33, message="Other message 33") + rc = self.writer.write_dispose(sample_to_dispose) + self.assertEqual(rc, 0, "dispose instance failed") + time.sleep(5) + print("Sample disposed") + sample_read = False + cnt_samples = 0 + print('reader>> begin read loop!') + print("cnt_samples ", cnt_samples) + while(not sample_read): + time.sleep(1) + try: + # samples = self.reader.read_mask(mask) + samples = self.reader.read() + print("here 1") + if samples is not None: + print("here 2") + samples_as_list = list(samples) + print("samples ", samples) + print("samples_as_list ", samples_as_list) + # for s in list(filter(lambda x: x[1].valid_data, samples_as_list)): + for s in list(samples_as_list): + print("here 3") + if s[0] is not None and s[1].valid_data: + print("here 4") + sample_read = True + sam = s[0] + if sam is not None: + cnt_samples += 1 + val_ = (HelloWorldData_Msg)(**sam) + print('********************************************************') + print('******************Read data was**********************') + print('val = {}'.format(val_)) + print('val_.userID {}'.format(val_.userID)) + print('val_.message {}'.format(val_.message)) + print("s[1].instance_handle = ", s[1].instance_handle) + print("s[1].instance_state = ", s[1].instance_state) + if(val_.userID != 33): + self.assertEqual(s[1].instance_state, DDS_ALIVE_INSTANCE_STATE, "Read message with userID={0} has an invalid instacne_state {1}".format(val_.userID, s[1].instance_state)) + self.assertEqual(s[1].sample_state, DDS_READ_SAMPLE_STATE, "Read samples does not have the good mask, val_userID={0}".format(val_.userID)) + else: + self.assertEqual(s[1].instance_state, DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE, "Read message with userID={0} has an invalid instacne_state {1}".format(val_.userID, s[1].instance_state)) + # self.assertEqual(s[1].sample_state, DDS_NOT_READ_SAMPLE_STATE, "Read samples does not have the good mask, val_userID={0}".format(val_.userID)) + self.assertTrue(val_.userID in range(30, 40), "Read message has an invalid key {0}".format(val_.userID)) + except: + print("Invalid data read") + raise Exception("Unexpected error:", sys.exc_info()[0]) + + +if __name__ == "__main__": + unittest.main() # run all tests diff --git a/tox.ini b/tox.ini index f85a248..29264aa 100644 --- a/tox.ini +++ b/tox.ini @@ -8,17 +8,20 @@ usedevelop = True install_command = pip install -U {opts} {packages} setenv = VIRTUAL_ENV={envdir} -deps = - -r{toxinidir}/requirements.txt -commands = nosetests --with-coverage --cover-package=yaks yaks +#deps = +# -r{toxinidir}/requirements.txt +# commands = nosetests --with-coverage --cover-package=yaks yaks +commands = python3 -m unittest discover -s ./tests/ + # nosetests --with-coverage # --cover-package=yaks yaks [testenv:pep8] -commands = flake8 +# commands = flake8 #[testenv:integration] #commands = nosetests integration [flake8] +ignore = E501, F405 , E722, F403, F821, F401, F841 show-source = True builtins = _