Omnicon Generic DDS Engine Python API
Project description
OmniCon GenericDDSEngine PythonAPI
Introduction
OmniCon's Generic DDS Engine is a pluggable software library that provides simple, fully generic monitoring and message injection capabilities for Data Distribution Service (DDS).
Motivation
This project encapsulates DDS-complex API and configuration. It provides a simple, user friendly API to easily incorporate DDS traffic to generic monitoring and visualization tools.
Engine Capabilites
Engine's monitor inputs:
- Active dynamic/static monitoring based on a generic DDS Participant.
- Passive (non-intrusive) dynamic monitoring using network sniffing techniques.
- Offline network recording dissection.
Engine's monitor outputs & plugins:
- A generic C++, C# and Python APIs for receiving monitored messages in JSON and Map formats via push/poll methods.
- Customized integration to operational monitoring tools (proprietary and open-source).
- Textual reports generation.
- Integration to databases (relational and non-relational).
Engine's message injection:
- A C++, C# and Python APIs for injecting messages via JSON or Map formats.
- Message injection based on a user-provided textual format (e.g. CSV).
DDS XML/IDL Type Files Introspection:
- A simplified C++, C# and Python APIs for extracting detailed information on a selected DDS type's structure.
- Documentation / ICD generator.
DDS Overview
The OMG Data Distribution Service (DDS™) is a middleware protocol and API standard for data-centric connectivity from the Object Management Group® (OMG®). It integrates the components of a system together, providing low-latency data connectivity, extreme reliability, and a scalable architecture that business and mission-critical Internet of Things (IoT) applications need.
For more information refer to https://www.dds-foundation.org/.
Installation
- pip install Omnicon-GenericDDSEngine-Py
- Requires: Visual Studio redistributable (https://aka.ms/vs/17/release/vc_redist.x64.exe)
- An Omnnicon license is required to utilize the API. Please Contact Info@OmniconSystems.com.
Examples
For full API documentation and examples refer to https://www.OmniconSystems.com
Active Dynamic Monitoring
Demonstrate how to dinamically monitor every topic in a desired DDS domain. The same API applies for Passive monitoring.
import Omnicon_GenericDDSEngine_Py as omnicon
from time import sleep
class ActiveDynamicMonitorExampleListener(omnicon.EngineListener):
def OnUserDataJson(self, sampleJson):
print("OnUserDataJson")
print(sampleJson)
def OnDiscoveryDataJson(self, sampleJson):
print("OnDiscoveryDataJson")
print(sampleJson)
class ActiveDynamicMonitorExample:
def __init__(self):
print(self.run())
@staticmethod
def run():
print("Active Dynamic Monitoring Example")
# Factory configuration (optional) (can also be performed via an XML configuration)
factory_configuration = omnicon.FactoryConfiguration()
factory_configuration.loggerConfiguration.verbosity = omnicon.LogSeverityLevel.trace
if not omnicon.GenericDDSEngine.SetFactoryConfiguration(factory_configuration):
print("error setting factory configuration")
return False
# Engine configuration (can also be performed via API)
engine = omnicon.GenericDDSEngine()
engine_configuration = omnicon.EngineConfiguration()
engine_configuration.engineOperationMode = omnicon.EngineOperationMode.ACTIVE_DYNAMIC_MONITORING
engine_configuration.ddsConfigurationFilesPath.append("./EngineConfigurationExamples/ActiveDynamicMonitoring")
engine_configuration.enableJsonOutput = True
if not engine.Init(engine_configuration):
return False
# Register to engine's callbacks/events
listener = ActiveDynamicMonitorExampleListener()
if not engine.BindListener(listener, omnicon.ON_USER_DATA_JSON | omnicon.ON_DISCOVERY_DATA_JSON):
return False
if not engine.Run():
return False
print("Running Example...")
input('Press Enter to Exit ')
sleep(1)
engine.UnbindListener()
print("Shutting Down...")
Required Standard DDS configuration files include a basic participant with the DDS types files and DDS domain. For example:
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<types>
<enum name="ShapeFillKind">
<enumerator name="SOLID_FILL"/>
<enumerator name="TRANSPARENT_FILL"/>
<enumerator name="HORIZONTAL_HATCH_FILL"/>
<enumerator name="VERTICAL_HATCH_FILL"/>
</enum>
<struct name= "ShapeType">
<member name="color" stringMaxLength="128" type="string" key="true"/>
<member name="x" type="int32"/>
<member name="y" type="int32"/>
<member name="shapesize" type="int32"/>
</struct>
<struct name= "ShapeTypeExtended" baseType="ShapeType">
<member name="fillKind" type="nonBasic" nonBasicTypeName= "ShapeFillKind"/>
<member name="angle" type="float32"/>
</struct>
</types>
<domain_library name="Domain_Lib">
<domain name="Domain" domain_id="7"/>
</domain_library>
<domain_participant_library name="Participants_Lib">
<domain_participant name="OmniCon_Engine_Participant" domain_ref="Domain_Lib::Domain">
<subscriber name="Subscriber"/>
</domain_participant>
</domain_participant_library>
</dds>
Message Injection
Demonstrate how to generically inject every DDS Topic using dictionary/json format.
import Omnicon_GenericDDSEngine_Py as omnicon
from time import sleep
class MessageInjectionExample:
def __init__(self):
print(self.run())
@staticmethod
def run():
print("Message Injection Example")
engine = omnicon.GenericDDSEngine()
# Engine configuration (can also be performed via xml config file)
engine_configuration = omnicon.EngineConfiguration()
engine_configuration.engineOperationMode = omnicon.EngineOperationMode.MESSAGE_INJECTION
engine_configuration.ddsConfigurationFilesPath.append("./EngineConfigurationExamples/MessageInjection")
if not engine.Init(engine_configuration):
return False
if not engine.Run():
return False
# Prevent data races:
sleep(2)
print("List of available writers: ")
for writerInfo in engine.GetWritersInfo():
print(writerInfo.entityName, "to Topic", writerInfo.topicName)
print("")
# Primitive Topic message:
primitive_topic_input = {
"SampleData.myLongLong": "-1",
"SampleData.myUnsignedShort": "0",
"SampleData.myFloat": "-6789889.3392",
"SampleData.myDouble": "-6789898989.33999442",
"SampleData.myBoolean": "0", # can also use "False"
"SampleData.myChar": "",
"SampleData.myWchar": "0", # wchar is treated as number
"SampleData.myOctet": "0",
"SampleData.myShort": "-32768",
"SampleData.myLong": "-2147483648",
"SampleData.myUnsignedLong": "0"
}
print("Injecting Primitive Topic Message")
engine.InjectMessage("Publisher::PrimitiveTypeTopic_DW", primitive_topic_input)
# String Topic Message
string_topic_input = {
"SampleData.myBoundedString": "Hello",
"SampleData.myUnboundedString": "OmniCon",
"SampleData.myBoundedWString": "!"
}
print("Injecting String Topic Message")
engine.InjectMessage("Publisher::StringsTypeTopic_DW", string_topic_input)
# Enum Topic Message
enum_topic_input = {
"SampleData.mySimpleEnum": "2",
"SampleData.myDigitsEnum": "-1",
"SampleData.LetterPrimitiveEnum": "1"
}
print("Injecting Enum Topic Message")
engine.InjectMessage("Publisher::EnumTypeTopic_DW", enum_topic_input)
# PrimitiveNested Topic Message
primitive_nested_topic_input = {
"SampleData.myAliasLongType": "1",
"SampleData.myFirstType.myChar": "1",
"SampleData.myFirstType.myWchar": "1",
"SampleData.myFirstType.myOctet": "1",
"SampleData.PrimitiveSecondNested.myFloat": "2.5",
"SampleData.PrimitiveSecondNested.myNestedType.myChar": "z",
"SampleData.PrimitiveSecondNested.myDouble": "3.14159265359"
}
print("Injecting PrimitiveNested Topic Message")
engine.InjectMessage("Publisher::PrimitiveNestedTypeTopic_DW", primitive_nested_topic_input)
# Array Topic Message
array_type_topic_input = {
"SampleData.myKey": "1",
"SampleData.AliasCharArray[0]": "1",
"SampleData.PrimitiveOneDimensionalLiteralSizeArray.boolean_array[0]": "1",
"SampleData.PrimitiveOneDimensionalLiteralSizeArray.boolean_array[1]": "0",
"SampleData.PrimitiveOneDimensionalLiteralSizeArray.boolean_array[2]": "1",
"SampleData.PrimitiveOneDimensionalLiteralSizeArray.short_array[0]": "223",
}
print("Injecting ArrayTypeTopic Topic Message")
engine.InjectMessage("Publisher::ArrayTypeTopic_DW", array_type_topic_input)
# Sequence Topic Message
sequence_topic_message = {
"SampleData": {
"myKey": "0",
"myBooleanSeq": [
"TRUE"
],
"myAliasLongUSeq": [],
"myAliasSeqEnumMember": [
"(1) - GREEN",
"(2) - BLUE"
],
"myAliasSeqStringMember": [
"ABC"
],
"myPrimitiveSeq": [
{
"myChar": "\u0000",
"myWchar": "0",
"myOctet": "0",
"myShort": "2",
"myUnsignedShort": "0",
"myLong": "0",
"myUnsignedLong": "0",
"myLongLong": "0",
"myUnsignedLongLong": "0",
"myFloat": "0",
"myDouble": "0",
"myBoolean": "TRUE"
}
],
}
}
print("Injecting SequenceTypeTopic Topic Message")
engine.InjectMessage("Publisher::SequenceTypeTopic_DW", sequence_topic_message)
# Union Topic Message
union_type_topic_input = {
"SampleData.myKey": "1",
"SampleData.mySimpleUnion.AliasLong_2_3": "111",
# "SampleData.PositionError.Error3DMember.sigmaXX": "23",
"SampleData.PositionError.Error2DMember.sigmaXX": "245"
}
print("Injecting UnionTypeTopic Topic Message")
engine.InjectMessage("Publisher::UnionTypeTopic_DW", union_type_topic_input)
input("Press Enter to Exit...")
return True
Required Standard DDS configuration files include a basic participant with the DDS types files and DDS domain. For example:
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<types>
<!--User Types-->
<include file="TypeFiles/ShapeType.xml" />
<include file="TypeFiles/myIncludedTypesTester.xml" />
<include file="TypeFiles/myGenericTypesTester.xml" />
</types>
<!-- Optional -->
<qos_library name="QOSLibrary">
<qos_profile name="DefaultProfile" is_default_participant_factory_profile="true" is_default_qos="true" >
<participant_qos/>
<datawriter_qos>
<property>
<value>
<!--Required for unbounded types support-->
<element>
<name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name>
<value>4096</value>
</element>
</value>
</property>
</datawriter_qos>
<datareader_qos>
<property>
<value>
<!--Required for unbounded types support-->
<element>
<name>dds.data_reader.history.memory_manager.fast_pool.pool_buffer_max_size</name>
<value>4096</value>
</element>
</value>
</property>
</datareader_qos>
</qos_profile>
</qos_library>
<domain_library name="Domain_Lib">
<domain name="Domain" domain_id="7">
<!--Types Definition-->
<register_type name="ShapeType" type_ref="ShapeType" />
<register_type name="PrimitiveType" type_ref="PrimitiveType" />
<register_type name="MyNamespace::StringsType" type_ref="MyNamespace::StringsType" />
<register_type name="EnumType" type_ref="EnumType" />
<register_type name="PrimitiveNestedType" type_ref="PrimitiveNestedType" />
<register_type name="SequenceType" type_ref="SequenceType" />
<register_type name="UnionType" type_ref="UnionType" />
<register_type name="ArrayType" type_ref="ArrayType" />
<!--Topics Definition-->
<topic name="Square" register_type_ref="ShapeType"/>
<topic name="PrimitiveTypeTopic" register_type_ref="PrimitiveType" />
<topic name="StringsTypeTopic" register_type_ref="MyNamespace::StringsType" />
<topic name="EnumTypeTopic" register_type_ref="EnumType" />
<topic name="PrimitiveNestedTypeTopic" register_type_ref="PrimitiveNestedType" />
<topic name="SequenceTypeTopic" register_type_ref="SequenceType" />
<topic name="UnionTypeTopic" register_type_ref="UnionType" />
<topic name="ArrayTypeTopic" register_type_ref="ArrayType" />
</domain>
</domain_library>
<domain_participant_library name="Participants_Lib">
<domain_participant name="OmniCon_Engine_Participant" domain_ref="Domain_Lib::Domain">
<publisher name="Publisher">
<data_writer name="PrimitiveTypeTopic_DW" topic_ref="PrimitiveTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="StringsTypeTopic_DW" topic_ref="StringsTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="EnumTypeTopic_DW" topic_ref="EnumTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="PrimitiveNestedTypeTopic_DW" topic_ref="PrimitiveNestedTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="ArrayTypeTopic_DW" topic_ref="ArrayTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="SequenceTypeTopic_DW" topic_ref="SequenceTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
<data_writer name="UnionTypeTopic_DW" topic_ref="UnionTypeTopic">
<datawriter_qos base_name="QOSLibrary::DefaultProfile"/>
</data_writer>
</publisher>
</domain_participant>
</domain_participant_library>
</dds>
Type Introspection Example
Demonstrate how to extract DDS type infromation for analysis purposes.
import Omnicon_GenericDDSEngine_Py as omnicon
class TypeIntrospectionExample:
def __init__(self):
print(self.run())
@staticmethod
def run():
print("Type Introspection Example")
factory_configuration = omnicon.FactoryConfiguration()
factory_configuration.loggerConfiguration.verbosity = omnicon.LogSeverityLevel.trace
omnicon.GenericDDSEngine.SetFactoryConfiguration(factory_configuration)
engine = omnicon.GenericDDSEngine()
# Engine configuration (can also be performed via xml config file)
engine_configuration = omnicon.EngineConfiguration()
engine_configuration.engineOperationMode = omnicon.EngineOperationMode.TYPE_INTROSPECTION
engine_configuration.ddsConfigurationFilesPath.append("./EngineConfigurationExamples/TypeIntrospection/TopicNamesToTypesDefMap.xml")
if not engine.Init(engine_configuration):
return False
if not engine.Run():
return False
DDSTopicToTypeXMLMapping = omnicon.GenericDDSEngine.GetTopicNameToTypeNameMap(
"./EngineConfigurationExamples/TypeIntrospection/TopicNamesToTypesDefMap.xml")
for topic, type in DDSTopicToTypeXMLMapping.items():
print(topic + " - " + type)
dds_type = engine.IntrospectType(type)
if dds_type is None:
print(type + " is None")
for element in dds_type.structure:
print(element.name)
if element.typeKindName == "STRUCTURE":
print("\tdataTypeName - " + (element).dataTypeName)
if element.typeKindName == "STRING":
print("\tlen - " + str((element).length))
if element.typeKindName == "ENUMERATION":
print("\tENUMERATION")
if element.typeKindName == "SEQUENCE":
print("\tlen - " + str((element).length))
Required Standard DDS configuration files include a basic DDS types/topic XML definition. For example:
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.1.0/rti_dds_profiles.xsd"
version="6.1.0">
<types>
<include file="TypeFiles//myIncludedTypesTester.xml"/>
<include file="TypeFiles//myGenericTypesTester.xml"/>
<include file="TypeFiles//ShapeType.xml"/>
</types>
<domain_library name="Domain_Lib">
<domain name="Domain">
<!--Types Definition-->
<register_type name="ShapeType" type_ref="ShapeTypeExtended" />
<register_type name="PrimitiveType" type_ref="PrimitiveType" />
<register_type name="MyNamespace::StringsType" type_ref="MyNamespace::StringsType" />
<register_type name="EnumType" type_ref="EnumType" />
<register_type name="PrimitiveNestedType" type_ref="PrimitiveNestedType" />
<register_type name="SequenceType" type_ref="SequenceType" />
<register_type name="UnionType" type_ref="UnionType" />
<register_type name="ArrayType" type_ref="ArrayType" />
<!--Topics Definition-->
<topic name="Square" register_type_ref="ShapeType"/>
<topic name="PrimitiveTypeTopic" register_type_ref="PrimitiveType" />
<topic name="StringsTypeTopic" register_type_ref="MyNamespace::StringsType" />
<topic name="EnumTypeTopic" register_type_ref="EnumType" />
<topic name="PrimitiveNestedTypeTopic" register_type_ref="PrimitiveNestedType" />
<topic name="SequenceTypeTopic" register_type_ref="SequenceType" />
<topic name="UnionTypeTopic" register_type_ref="UnionType" />
<topic name="ArrayTypeTopic" register_type_ref="ArrayType" />
</domain>
</domain_library>
</dds>
OmniCon Distributed System LTD All Rights Reserved ©2019-2023
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8e25ee3406c0a4e8e3cfb9eca5d729c09aa892a61d9cdbcc31edf04ef3197fd9 |
|
MD5 | f5f845147d33e5b30b1bf01114fd5ca7 |
|
BLAKE2b-256 | 4858550def35eb4c45eaf8e9bcd79976130d36b168de22268059d8cd6f75b81a |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2f7fb98736d5dedfcddf668862d43d8dd79e3cda9a5b66ff9c6fc280563858c3 |
|
MD5 | 4b9cb0ee271fb0c0f6a181c3f018cf04 |
|
BLAKE2b-256 | 15387c2695e9c18238c615b9e99b01511d8bcbcfdf4f0d4d9d4f020903b27e1a |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5ce4926cbd33c33006535adfd761f0a156a88a58d25763e09b04031b46f4872d |
|
MD5 | 81ea2c228f02b2efe63aa389aafc2f39 |
|
BLAKE2b-256 | aff86c5c500e91528a26281d5fbe64b4edfe35740592c655c8173aae8b86c00f |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 6597fc3defa3a52db3e113b117770dfbe92575ab158f303c0d13135b5ddeb095 |
|
MD5 | a4ce2295a1ea7e796b2539ddf1ca94d0 |
|
BLAKE2b-256 | c6a89069807adbe6126353dc86cd2a8e7016ac4a6f402dcc26704fdc6d6f56c7 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | f8eedac208e8375e188e82112c0f31a70780e369ae1e974017fd51c21c98b33d |
|
MD5 | dbd2f28699c47f9f2b878f4de8df09b5 |
|
BLAKE2b-256 | edd28af01705344fdfd995a9332b7636ac02e327db4b4789e6867a56a463c001 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e93c924390a1a0bd127e10ae230f8849ea308c5c00e5a9cef4f1bcfdccbb0f61 |
|
MD5 | af941e4e950bbf71798cabcb700667a6 |
|
BLAKE2b-256 | e4bc7c31c24e94956e8f196263b725fba966465ea5f9546db5929e4f6a50ddd4 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ae72181f3aea63d3b95e9219500ff3c6ced693cc99fd0c281d933bdcf5624a70 |
|
MD5 | 3e84dfa1d0c1533ca1cee89bedbcb308 |
|
BLAKE2b-256 | b66f4cee5d441a404d61e57e8b191f78d18ad6d9c91433e168d5facfc2786695 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1ba1bca5af187e1f17ac5875592cc6b02c88dee95c2e42f08a744fad8b3e65ee |
|
MD5 | d891575c0daee67306621aee7877467f |
|
BLAKE2b-256 | e4d3e04b153f5e24182475f2ecc8c2d5940823149e46d77dc4d041c47eb28a9e |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-manylinux2014_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ea0c75eb89d3f2e319386aab39592bab3c604ea998f2203594a819845d23f229 |
|
MD5 | 95ba9a40bdf955a30606e53a7483bfca |
|
BLAKE2b-256 | f1581e995e6a63802876ecbffd69cdf6f8d9e9f4ba24bd17828b658f5bb3ef2c |