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.0-13-cp39-cp39-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.9Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-13-cp38-cp38-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.8Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-13-cp37-cp37m-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.7mWindows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-12-cp39-cp39-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.9Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-12-cp38-cp38-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.8Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-12-cp37-cp37m-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.7mWindows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-10-cp39-cp39-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.9Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-10-cp38-cp38-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.8Windows x86-64

Omnicon_GenericDDSEngine_Py-4.6.0-10-cp37-cp37m-win_amd64.whl (4.4 MB view details)

Uploaded CPython 3.7mWindows x86-64

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-13-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-13-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 50c793cb307f49e182f35c3e6a391e05d237fbcc4fe91bd6d96cb379e36a7638
MD5 11855ca5629d1235c139e7732cbd7475
BLAKE2b-256 9cb83dcc8dab4545fe4a29fe14740c95a07a006fbc54f9394cc5178b093266ad

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-13-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-13-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 a71e71e3cba4febf40445f7dcce0c9c2061b2c5e92e37c32c087148b91443764
MD5 4c0eb720f5364e2373c40ec853ea89cc
BLAKE2b-256 7962e8b5a15230484a7a94b670e704a935c991d0646cd1d5a40aa18af48203a6

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-13-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-13-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 a0d6b440d8d79b2f8b2660b8dd0048dc8afb4fa6ff72d6a9e88330ce016965d3
MD5 876602289e377755339f40c79727ad3e
BLAKE2b-256 18bcdedfc046829558d617708cc97ab74ca94b416b66e1fe6409bd0d022124b4

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-12-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 0deee4cba3b672d2aadc39e1eeaf5520c74ca61b085e002c097e464def81da11
MD5 ab6e0a87a08ea49366f0b86de202f099
BLAKE2b-256 41b2ee1c1dc3532e34ed2f6dae55e81e335fd10a7cdcc33e617fa24a976a259e

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-12-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 c895930f54ed20e392f2e148bed7e04949d39d8e665ab1c8ac356bd2799cac26
MD5 847cc14eb4254e03943ad00237ce83d5
BLAKE2b-256 3d039143340b5e6f38b3a7b71ffb5dd33690ba9b02d8baa034f1f8c8231b9a78

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-12-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-12-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 de9237588098b3f084b52d63df10938ec8a1f40839b768d8576d4c9cf15c17c1
MD5 81a6927dbaa82986a5a71999932046c7
BLAKE2b-256 0a68fc58802ea251b7187c338587cfd4fad290a36315a7c086d8cf685786786c

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-10-cp39-cp39-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 22bf8f0a81c25cb3ef8b672880fb8e22a403e366f64ed36db54bb702054d2800
MD5 8025f8c57f0401e2d1311c8c53cc3f41
BLAKE2b-256 1912e41acf463245fe1c5bf180e72cd803730d37eed4e09cfc204781ee073c8d

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-10-cp38-cp38-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 adb535cbe94c3bc7a7c6823b651a94520732b42d0275ea22c46884b08eda6380
MD5 2840efba1c3e03ebc5cfb5681930e3f6
BLAKE2b-256 29132c2090ba73260f9c476c9526b40719499fcfde8cf4186c2091e47878bcd7

See more details on using hashes here.

File details

Details for the file Omnicon_GenericDDSEngine_Py-4.6.0-10-cp37-cp37m-win_amd64.whl.

File metadata

File hashes

Hashes for Omnicon_GenericDDSEngine_Py-4.6.0-10-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 3fe37ec1d1d41b83b46aa0f30e543322be6a1683b14e5fd9973df87d1027143c
MD5 a6b584a170e7d8a1e2d166713df918f9
BLAKE2b-256 87957c5dba5be7ff5ef0a4202110d14c5b72f1ec34339a5fb3ae5b556cf30faa

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