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.0-13-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 50c793cb307f49e182f35c3e6a391e05d237fbcc4fe91bd6d96cb379e36a7638 |
|
MD5 | 11855ca5629d1235c139e7732cbd7475 |
|
BLAKE2b-256 | 9cb83dcc8dab4545fe4a29fe14740c95a07a006fbc54f9394cc5178b093266ad |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-13-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a71e71e3cba4febf40445f7dcce0c9c2061b2c5e92e37c32c087148b91443764 |
|
MD5 | 4c0eb720f5364e2373c40ec853ea89cc |
|
BLAKE2b-256 | 7962e8b5a15230484a7a94b670e704a935c991d0646cd1d5a40aa18af48203a6 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-13-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a0d6b440d8d79b2f8b2660b8dd0048dc8afb4fa6ff72d6a9e88330ce016965d3 |
|
MD5 | 876602289e377755339f40c79727ad3e |
|
BLAKE2b-256 | 18bcdedfc046829558d617708cc97ab74ca94b416b66e1fe6409bd0d022124b4 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0deee4cba3b672d2aadc39e1eeaf5520c74ca61b085e002c097e464def81da11 |
|
MD5 | ab6e0a87a08ea49366f0b86de202f099 |
|
BLAKE2b-256 | 41b2ee1c1dc3532e34ed2f6dae55e81e335fd10a7cdcc33e617fa24a976a259e |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c895930f54ed20e392f2e148bed7e04949d39d8e665ab1c8ac356bd2799cac26 |
|
MD5 | 847cc14eb4254e03943ad00237ce83d5 |
|
BLAKE2b-256 | 3d039143340b5e6f38b3a7b71ffb5dd33690ba9b02d8baa034f1f8c8231b9a78 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | de9237588098b3f084b52d63df10938ec8a1f40839b768d8576d4c9cf15c17c1 |
|
MD5 | 81a6927dbaa82986a5a71999932046c7 |
|
BLAKE2b-256 | 0a68fc58802ea251b7187c338587cfd4fad290a36315a7c086d8cf685786786c |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp39-cp39-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 22bf8f0a81c25cb3ef8b672880fb8e22a403e366f64ed36db54bb702054d2800 |
|
MD5 | 8025f8c57f0401e2d1311c8c53cc3f41 |
|
BLAKE2b-256 | 1912e41acf463245fe1c5bf180e72cd803730d37eed4e09cfc204781ee073c8d |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp38-cp38-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | adb535cbe94c3bc7a7c6823b651a94520732b42d0275ea22c46884b08eda6380 |
|
MD5 | 2840efba1c3e03ebc5cfb5681930e3f6 |
|
BLAKE2b-256 | 29132c2090ba73260f9c476c9526b40719499fcfde8cf4186c2091e47878bcd7 |
Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp37-cp37m-win_amd64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3fe37ec1d1d41b83b46aa0f30e543322be6a1683b14e5fd9973df87d1027143c |
|
MD5 | a6b584a170e7d8a1e2d166713df918f9 |
|
BLAKE2b-256 | 87957c5dba5be7ff5ef0a4202110d14c5b72f1ec34339a5fb3ae5b556cf30faa |