Home
Categories
Dictionary
Glossary
Download
Project Details
Changes Log
What Links Here
FAQ
License

External Communication CSharp tutorial



In this tutorial, we will communicate with a C# executable for the External Communication module. We will reuse the first tutorial.

Note that in this tutorial, we will start the C# executable independantly, but the External Communication Launcher tutorial will explain how to start the C# executable through the framework.

Overview

In the first tutorial, we had two modules:
  • The PublishModule module increments or decrements a value cyclically
  • The EventModule module allows to click on a toggle to set if the first module should increment or decrement the value, and shows the value
We will implement the PublishModule with the ExternalComm module.

Architecture

We won't change anything for the services or types configuration of the first tutorial, but we will duplicate the EventModule in the applications configuration. We will have two applications:
  • The eventAppli module will be identical from the module defined in the first tutorial
  • The publishAppli application will use an External Communication module. This module will communicate with a C# executable

externalcommcsharp

XML configuration

Applications configuration

The applications configuration is:
      <applications>
         <application name="eventAppli">
            <deployment>
               <lib url="samplesEvent.jar" />
            </deployment>
            <modules>
               <module name="EventModule" > 
                  <implementation path="org.da.samples.protoframework.event.EventModule" >
                     <initEntryPoint method="init" />
                     <defaultReceiveEntryPoint method="subscribe" />
                  </implementation>
                  <interfaces>
                     <eventSend service="event" attach="attach"/>
                     <subscribe service="published" />
                  </interfaces>             
               </module>
            </modules>
         </application>      
         <application name="publishAppli" >
            <deployment>
               <lib url="externalComm.jar" />
            </deployment>
            <interfaces>
               <eventReceived service="event" />
               <push service="published" />
            </interfaces> 
         </application>       
      </applications>

Network configuration

The network configuration for the External Communication will be:
      <network>
         <channel name="event" type="input" port="8080" >
            <service name="published" />
         </channel>  
         <channel name="publish" type="output" port="8081">
            <service name="event" />     
         </channel>
      </network>

Framework properties

The properties configuration will be:
      <properties>
         <application name="externalComm" >
            <module name="externalComm" >
               <moduleProperty key="network" value="network.xml" />      
               <moduleProperty key="endianness" value="littleEndian" />		
               <moduleProperty key="charAs8Bits" value="true" />					 
            </module>
         </application>
      </properties>

Filelist configuration

Thel filelist configuration refer to the files defined for the framework.
      <files>
         <file url="applicationsEvent.xml" />
         <file url="services.xml" />
         <file url="types.xml" />
         <file url="properties.xml" />
      </files>

Coding the C# application

We will create a C# application whose target will be called PublishAppli.exe.

We will call the PublishAppli.exe executable with the following arguments:
      PublishAppli.exe input=8080 output=8081
The full source code is in the PublishAppli.cs file.

Code structure

The PublishAppli.exe will be a C# executable with the following code structure and the decoding of the arguments:
      namespace PublishAppli
      {
        class PublishAppli {
              int portEmission = 10000;
              int portReception = 10001;

          static void Main(string[] args) {
              PublishAppli appli = new PublishAppli();
              DecodeArgs(appli, args);
          }

              private static void DecodeArgs(PublishAppli appli, string[] args) {
                int _portReception = -1;
                int _portEmission = -1;
                for (int i = 0; i < args.Length; i++) {
                   string arg = args[i];
                   int index = arg.IndexOf("=");
                   if (index != -1) {
                      string key = arg.Substring(0, index);
                      string value = arg.Substring(index + 1);
                      if (key.Equals("input")) {
                         _portReception = int.Parse(value);
                      } else if (key.Equals("output")) {
                         _portEmission = int.Parse(value);
                      }
                   }
                }
                if (_portReception != -1 && _portEmission != -1) {
                  appli.SetPorts(_portReception, _portEmission);
                }
              }

              PublishAppli() {
                Console.WriteLine("Start PublishAppli");
              }

              public void SetPorts(int portReception, int portEmission) {
                this.portReception = portReception;
                this.portEmission = portEmission;
              }      
     
           }
      }

Creation of the Sockets and associated Threads

We will create an associated Thread for the notification of the event service, and the notification of the cyclic invocation of the publish service, and the creation of the associated Threads:
  • The Client Thread is used to send cyclically the value through the publish service
  • The Server Thread is used to be notified by the event service
      class PublishAppli {
         int portEmission = 10000;
         int portReception = 10001;
         Socket client;
         IPEndPoint remoteEndPoint;
         System.Threading.Timer timer = null;      
      
         PublishAppli() {
           Console.WriteLine("Start PublishAppli");
           LaunchThreadServer();
           LaunchThreadClient();
         }

         public void SetPorts(int portReception, int portEmission) {
           this.portReception = portReception;
           this.portEmission = portEmission;
         }

         public void LaunchThreadServer() {
           Thread t = new Thread(new ThreadStart(CreateServer));
           t.Start();
         }

         public void LaunchThreadClient()  {
           Thread t = new Thread(new ThreadStart(CreateClient));
           t.Start();
         }    
      
         public void CreateClient() {
           client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
           IPAddress localhost = System.Net.IPAddress.Parse("127.0.0.1");
           remoteEndPoint = new IPEndPoint(localhost, portEmission);
           try {
             timer = new System.Threading.Timer(Publish, null, 200, 200);
           }  catch (SocketException e) {
             Console.Error.Write(e.Message);
           }
         }
      }  

Handle the event Service notification

The following code decodes the content of the event service:
      public void CreateServer() {
         UdpClient listener = new UdpClient(portReception);
         IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, portReception); 

         try {
           while (true) {
             byte[] bytes = listener.Receive(ref groupEP);
             int index = 0;
             // MAGIC keyword
             System.BitConverter.ToInt32(bytes, index);
             index += 4;
             // Service ID
             long id = System.BitConverter.ToInt64(bytes, index);
             index += 8;
             // INVOKE keyword
             char c = (char)bytes[index];
             index += 1;
             // Time stamp
             System.BitConverter.ToInt64(bytes, index);
             index += 8;
             // Request  ID
             System.BitConverter.ToInt64(bytes, index);
             index += 8;
             // event
             state = System.BitConverter.ToBoolean(bytes, index);
             if (state) {
               step = 1;
               Console.WriteLine("Received event = true");                      
             } else {
               step = -1;
               Console.WriteLine("Received event = false");
             }
           }
         } catch (SocketException e) {
            Console.Error.Write(e.Message);
         } finally {
            Console.WriteLine("End PublishAppli");
            listener.Close();
         }
      }    

Handle the publish Service invocation

The following code is invoked to send cyclically for the publish service[1]
handled by the CreateClient() Thread
:
      public void Publish(object state) {
         byte[] bytes = new byte[34];
         int index = 0;
         // MAGIC keyword
         byte[] _bytes = BitConverter.GetBytes(0xDA666);
         _bytes.CopyTo(bytes, index);
         index += 4;
         // Service ID
         _bytes = BitConverter.GetBytes((long)2);
         _bytes.CopyTo(bytes, index);
         index += 8;
         // INVOKE keyword
         bytes[index] = 0x01;
         index++;
         // Time stamp
         _bytes = BitConverter.GetBytes((long)0);
         _bytes.CopyTo(bytes, index);
         index += 8;
         // Request  ID
         _bytes = BitConverter.GetBytes((long)0);
         _bytes.CopyTo(bytes, index);
         index += 8;
         // value
         _bytes = BitConverter.GetBytes(count);
         _bytes.CopyTo(bytes, index);
         client.SendTo(bytes, bytes.Length, SocketFlags.None, remoteEndPoint); 
         count += step;
      }   

Usage

You will have to start the PublishAppli.exe executable with the following arguments (for example in a .bat file):
      PublishAppli.exe input=8080 output=8081
Then start the framework using the filelist configuration[2]
The order of starting is not important, you may also start the framework first

Notes

  1. ^ handled by the CreateClient() Thread
  2. ^ The order of starting is not important, you may also start the framework first

See also


Categories: builtin-applis | tutorials

Copyright 2017-2020 Dassault Aviation. All Rights Reserved. Documentation and source under the LGPL v3 licence