Skip to main content

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:

  1. Active dynamic/static monitoring based on a generic DDS Participant.
  2. Passive (non-intrusive) dynamic monitoring using network sniffing techniques.
  3. Offline network recording dissection.

Engine's monitor outputs & plugins:

  1. A generic C++, C# and Python APIs for receiving monitored messages in JSON and Map formats via push/poll methods.
  2. Customized integration to operational monitoring tools (proprietary and open-source).
  3. Textual reports generation.
  4. Integration to databases (relational and non-relational).

Engine's message injection:

  1. A C++, C# and Python APIs for injecting messages via JSON or Map formats.
  2. Message injection based on a user-provided textual format (e.g. CSV).

DDS XML/IDL Type Files Introspection:

  1. A simplified C++, C# and Python APIs for extracting detailed information on a selected DDS type's structure.
  2. 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

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

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

Omnicon_GenericDDSEngine_Py-4.6.3-2-cp39-cp39-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.9Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.3-2-cp38-cp38-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.8Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.3-2-cp37-cp37m-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.7mWindows x86-64

Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.9Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.8Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-win_amd64.whl (4.5 MB view details)

Uploaded CPython 3.7mWindows x86-64

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-2-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 8e25ee3406c0a4e8e3cfb9eca5d729c09aa892a61d9cdbcc31edf04ef3197fd9
MD5 f5f845147d33e5b30b1bf01114fd5ca7
BLAKE2b-256 4858550def35eb4c45eaf8e9bcd79976130d36b168de22268059d8cd6f75b81a

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-2-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 2f7fb98736d5dedfcddf668862d43d8dd79e3cda9a5b66ff9c6fc280563858c3
MD5 4b9cb0ee271fb0c0f6a181c3f018cf04
BLAKE2b-256 15387c2695e9c18238c615b9e99b01511d8bcbcfdf4f0d4d9d4f020903b27e1a

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-2-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-2-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 5ce4926cbd33c33006535adfd761f0a156a88a58d25763e09b04031b46f4872d
MD5 81ea2c228f02b2efe63aa389aafc2f39
BLAKE2b-256 aff86c5c500e91528a26281d5fbe64b4edfe35740592c655c8173aae8b86c00f

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 6597fc3defa3a52db3e113b117770dfbe92575ab158f303c0d13135b5ddeb095
MD5 a4ce2295a1ea7e796b2539ddf1ca94d0
BLAKE2b-256 c6a89069807adbe6126353dc86cd2a8e7016ac4a6f402dcc26704fdc6d6f56c7

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp39-cp39-manylinux2014_x86_64.whl.

File metadata

File hashes

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

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 e93c924390a1a0bd127e10ae230f8849ea308c5c00e5a9cef4f1bcfdccbb0f61
MD5 af941e4e950bbf71798cabcb700667a6
BLAKE2b-256 e4bc7c31c24e94956e8f196263b725fba966465ea5f9546db5929e4f6a50ddd4

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp38-cp38-manylinux2014_x86_64.whl.

File metadata

File hashes

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

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 1ba1bca5af187e1f17ac5875592cc6b02c88dee95c2e42f08a744fad8b3e65ee
MD5 d891575c0daee67306621aee7877467f
BLAKE2b-256 e4d3e04b153f5e24182475f2ecc8c2d5940823149e46d77dc4d041c47eb28a9e

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.3-1-cp37-cp37m-manylinux2014_x86_64.whl.

File metadata

File hashes

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

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page