DGI.Framework.Communications.Generic.SimplCommunicationsAdapter 1.0.2

SIMPL Communication Adapter

This library helps adapt a DGI Framework drivers that have a IDgiCommunication interface to a SIMPL+ module for interfacing with SIMPL communication symbols, like the TCP/IP Client, UDP/IP Communications or the a Serial Driver.

How to use

Refer to the DGI SIMP Visionary Solutions module for an example:

A DGI SIMPL device driver, just like with the DGI Framework, should be unaware of the physical method of communication. In the DGI Framework that is easily accomplish by injecting a communication driver that implements the IDgiCommunications interface. However, this is not as easily achieved in SIMPL environment.

This adapter helps mediate communications between the device driver and the SIMPL+ module that will ultimately connect to one of the SIMPL communication symbols.

In order to do so a SIMPL# Device Driver should be created with a Crestron.SimplSharp.SDK.Library package. This Driver will use this SimplDgiCommunicationsAdapter that implements IDgiCommunications and will be injected into the device driver. SimplDgiCommunicationsAdapter will then expose some public members that will be used to interface with the SIMPL+ module.

_dgiCommunicationsAdapter = new SimplDgiCommunicationsAdapter();
_visionarySolutionsSeries5Driver = new VisionarySolutionsSeries5Driver(_dgiCommunicationsAdapter);

Now when the C# driver needs to send information to the SIMPL Communication Module to transmit to the device, it will be caught by the SimplDgiCommunicationsAdapter and will be passed to the SIMPL+ module through the ExternalTransmitChanged event. The adapter then retransmits that information through its own ExternalTransmitChanged that will eventually be consumed by the SIMPL+ module. This seems redundant until you realize that the SIMPL+ module on series 4 cannot consume strings longer that 1200 characters. This adapter will break up the string into smaller 250 character chunks for the SIMPL+ module to consume. All you need to do to implement this in your SIMPL# Library wrapper is the following:

_dgiCommunicationsAdapter.ExternalTransmitChanged += (sender, data) => ExternalTransmitChanged?.Invoke(this, new SimplStringEventArgs { Value = data });

In The SIMPL+ side of the equation however, it will be necessary if the information is larger that 250 character, to capture the data using a STRING_BUFFER and CMutex like this:

CMutex receiveMutex;

CHANGE ExternalRx${
	String rxString[65534];

	receiveMutex.WaitForMutex();
	if (Len(ExternalRx$)>0) {
		rxString = RemoveByLength(Len(ExternalRx$),ExternalRx$);
		Driver.ExternalReceived(rxString);
	}
	receiveMutex.ReleaseMutex();
}

Class Diagram

A Class UML example of the implementation is shown below:

package "SIMPL# Library Device Driver" {
    class DgiFrameworkDeviceDriver{
        +DgiFrameworkDeviceDriver(IDgiCommunications)
        ==
        Other Device Specific Methods and Properties
    }
    interface CommunicationDriver <<IDgiCommunications>>{
        +IsConnected: bool
        +ErrorMessage: string
        +Status: StatusCodes
        ----
        +Connect()
        +ConnectAsync()
        +Disconnect()
        +DisconnectAsync()
        +Send()
        +SendAsync()
        +<<ConnectionChanged(ConnectionChangedArgs)>>
        +<<StatusChanged(StatusChangedArgs)>>
        +<<DataReceived(DataReceivedArgs)>>
    }
    class SimplDgiCommunicationAdapter{
        +IsConnected: bool
        +ErrorMessage: string
        +Status: StatusCodes
        ---
        +Connect()
        +ConnectAsync()
        +Disconnect()
        +DisconnectAsync()
        +Send()
        +SendAsync()
        +<<ConnectionChanged(ConnectionChangedArgs)>>
        +<<StatusChanged(StatusChangedArgs)>>
        +<<DataReceived(DataReceivedArgs)>>
        ..
        +ExternalConnectFeedback(bool)
        +ExternalStatus(ushort)
        +ExternalReceived(string)
        +<<ExternalConnectChanged(bool)>>
        +<<ExternalTransmitChanged(string)>>
        ==
        Other Device Specific Methods and Properties
    }
}
struct SimpPlusCommunicationSymbol{
    Connect-F
    Status
    RX$
    Connect
    TX$
    ==
    Other Device Specific Methods and Properties
}


DgiFrameworkDeviceDriver  ->  CommunicationDriver : target
CommunicationDriver  <|-- SimplDgiCommunicationAdapter: implements
SimplDgiCommunicationAdapter  ->  SimpPlusCommunicationSymbol : adaptee

Sequence Diagram

A sequence diagram of the methods and events can be shown below:

participant "DGI Framework Device Driver" as driver
participant "DgiCommunicationsAdapter" as adapter
participant "Simpl# Deivice Driver" as SimplSharpDriver
participant "Simpl+ Module" as SimplPlusModule
participant "Simpl Module" as SimplModule
participant "Communication Module" as CommsModule

== Connect ==
driver -> adapter++: Connect()
adapter -->> SimplSharpDriver--++: ExternalConnectChanged<bool> (true)
SimplSharpDriver ->> SimplPlusModule--++: ExternalConnectChanged<SimplUShortEventArgs> (1)
SimplPlusModule -> SimplModule --++:  ExternalConnect (Digital Join High)
SimplModule -> CommsModule --: Connect (Digital Join High)

== Connect Async ==
driver -> adapter++: ConnectAsync()
adapter -->> SimplSharpDriver--++: ExternalConnectChanged<bool> (true)
SimplSharpDriver ->> SimplPlusModule--++: ExternalConnectChanged<SimplUShortEventArgs> (1)
SimplPlusModule -> SimplModule --++:  ExternalConnect (Digital Join High)
SimplModule -> CommsModule --: Connect (Digital Join High)
... time passes ...
CommsModule -> SimplModule --++: Connect-F (Digital Join High)
SimplModule -> SimplPlusModule--++: ExternalConnect-F (Digital Join High)
SimplPlusModule -> SimplSharpDriver--++: ExternalConnectFeedback(isConnected: ushort)
SimplSharpDriver -->> adapter--++: ExternalConnectChanged(isConnected: bool)
adapter -> driver--: Task Completed
note right of driver
Will immediatly call ExternalConnectChanged with true 
but will not report task completed until it receives a Connect-F High from the Comms Module
end note

== Conection Feedback ==
CommsModule -> SimplModule --++: Connect-F (Digital Join State)
SimplModule -> SimplPlusModule--++: ExternalConnect-F (Digital Join State)
SimplPlusModule -> SimplSharpDriver--++: ExternalConnectFeedback(isConnected: ushort)
SimplSharpDriver -> adapter--++: ExternalConnectFeedback(bool)
adapter -->> driver--: ConnectionChanged<ConnectionChangedEventArgs> 

== Status Feedback ==
CommsModule -> SimplModule --++: status (Analog Join State)
SimplModule -> SimplPlusModule--++: ExternalStatus (Analog Join State)
SimplPlusModule -> SimplSharpDriver--++: ExternalStatus(status: ushort)
SimplSharpDriver -> adapter--++: ExternalStatus(ushort)
adapter -->> driver--: StatusChanged<StatusChangedEventArgs> 

== Send and Send async ==
driver -> adapter++: Send(string or byte[]) or SendAsync(string or byte[])
loop for each 250 character chunk
    adapter -->> SimplSharpDriver--++: ExternalTransmitChanged<string>
    SimplSharpDriver ->> SimplPlusModule--++: ExternalTransmitChanged<SimplStringEventArgs> 
    SimplPlusModule -> SimplModule --++:  ExternalTx$ (String)
    alt when sent messages are bigger that 250 character
        SimplModule -> SimplModule : Buffer the message
    end
    SimplModule -> CommsModule --: TX$ (String)
end

== Receive ==
note over driver, CommsModule
String Communication between SIMPL and SIMPL+ can only happen in 250 character chunks.  (1200 character limit in series 4).
Communication Symbols therefore will chunk their data in 250 character chunks.
This data will need to be received in SIMPL+ with a buffer, and then sent to the underlying SIMPL# driver who should be capable of assempling the chunks
end note
CommsModule -> SimplModule --++: RX$ (String)
    loop for each 250 character chunk
    alt when sent messages are bigger that 250 character
        SimplModule -> SimplModule : Buffer the message
    end
    SimplModule -> SimplPlusModule--++: ExternalRx$ (String)
    SimplPlusModule -> SimplSharpDriver--++: ExternalReceived(data: string)
    SimplSharpDriver -> adapter--++: ExternalReceived(data: string)
    adapter -->> driver--: DataRecieve<DataReceivedArgs>
end


== Disconnect ==
driver -> adapter++: Disconnect()
adapter -->> SimplSharpDriver--++: ExternalConnectChanged<bool> (false)
SimplSharpDriver ->> SimplPlusModule--++: ExternalConnectChanged<SimplUShortEventArgs> (0)
SimplPlusModule -> SimplModule --++:  ExternalConnect (Digital Join Low)
SimplModule -> CommsModule --: Connect (Digital Join Low)

== Disconnect Async ==
driver -> adapter++: Disconnect()
adapter -->> SimplSharpDriver--++: ExternalConnectChanged<bool> (false)
SimplSharpDriver ->> SimplPlusModule--++: ExternalConnectChanged<SimplUShortEventArgs> (0)
SimplPlusModule -> SimplModule --++:  ExternalConnect (Digital Join Low)
SimplModule -> CommsModule --: Connect (Digital Join Low)
... time passes ...
CommsModule -> SimplModule --++: Connect-F (Digital Join Low)
SimplModule -> SimplPlusModule--++: ExternalConnect-F (Digital Join Low)
SimplPlusModule -> SimplSharpDriver--++: ExternalConnectFeedback(isConnected: ushort)
SimplSharpDriver -->> adapter--++: ExternalConnectChanged(isConnected: bool)
adapter -> driver--: Task Completed
note right of driver
Will immediatly call ExternalConnectChanged with false 
but will not report task completed until it receives a Connect-F Low from the Comms Module
end note

Full API Documentations

Full descriptions of all Methods, Properties and Events can be found here

No packages depend on DGI.Framework.Communications.Generic.SimplCommunicationsAdapter.

Production Release

.NET Framework 4.7

.NET 6.0

Version Downloads Last updated
2.0.0 3 6/18/2026
1.0.3 1 6/16/2026
1.0.2 2 10/10/2024