/*********************************************************************
*
* Afag Telnet C# Integration Sample Header
*
*********************************************************************
* FileName: aflexCommunicationClass.cs
* Dependencies: aflex_CSharp_Integration_Sample
* Company: ima-tec GmbH
*
* Software License Agreement
*
*
* THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
* WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
* LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* AFAG BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
* PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
* BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
* THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
* SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
* (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
*
*
********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace aflex_CSharp_Integration_Sample {
class aflexCommunicationClass {
//the target Values are the aflex Input values
private UInt16 pr_target_direction;
private UInt16 pr_target_intensity;
private UInt16 pr_target_auxPowerOut;
private Byte pr_target_ConfigNumber;
private Byte pr_target_GeneralRelease;
private Byte pr_target_ControllerRestart;
//The actual device Values are the aflex Output values
private UInt16 pr_actual_direction;
private UInt16 pr_actual_intensity;
private UInt16 pr_actual_auxPowerOut;
private Byte pr_actual_ConfigNumber;
private Byte pr_actual_AutoMode;
private Byte pr_actual_GeneralRelease;
private Byte pr_actual_ControllerRestart;
//Bitoffset of the Values
private const Byte pr_BitOff_direction = 48;
private const Byte pr_BitOff_intensity = 64;
private const Byte pr_BitOff_auxPowerOut = 8;
private const Byte pr_BitOff_ConfigNumber = 0;
private const Byte pr_BitOff_AutoMode = 32;
private const Byte pr_BitOff_GeneralRelease = 40;
private const Byte pr_BitOff_ControllerRestart = 24;
//The aflex ControlUnit TelnetServer doesn't transmit a new package each time a value changed.
//So the Client has to poll the aflex Outputs to detect the changes. For this the following TimeSpan are used.
private TimeSpan pr_sync_direction= new TimeSpan();
private TimeSpan pr_sync_intensity = new TimeSpan();
private TimeSpan pr_sync_auxPowerOut = new TimeSpan();
private TimeSpan pr_sync_ConfigNumber= new TimeSpan();
private TimeSpan pr_sync_AutoMode = new TimeSpan();
private TimeSpan pr_sync_GeneralRelease = new TimeSpan();
private TimeSpan pr_sync_ControllerRestart = new TimeSpan();
private const int TimerPeriod = 10; //fixed timer period in Milliseconds. Adjust that value due the Application requirements
private TimeSpan tick = new TimeSpan(0, 0, 0, 0, TimerPeriod); //Timespan to Add each Timer tick
private TimeSpan pr_MaxSync = new TimeSpan(0,0,0,0,100); //Timespan for polling the aflex Outputs. Adjust that value due the Application requirements, max value "ticks" * 7!
private Timer objSyncTimer; //Timer for polling
public TCPCommunicationClass objTelnetConnection; //connection interface
private bool pr_b_LoggedIn; //Telnet Client logged in
private bool pr_b_HBT; //Heartbeat state of the Telnet Server
///
/// Occurs when a aflex value is recieved. Transmit the PropertyName as string.
///
public event EventHandler aflexValueChanged;
///
/// This Timer is used for cyclic polling the aflex outputs. TimerPeriod should be adjust due the Application requirements.
///
///
private void objSyncTimer_Tick(object state) {
if (pr_b_LoggedIn) {
pr_sync_direction = pr_sync_direction.Add(tick);
pr_sync_intensity= pr_sync_intensity.Add(tick);
pr_sync_auxPowerOut = pr_sync_auxPowerOut.Add(tick);
pr_sync_ConfigNumber = pr_sync_ConfigNumber.Add(tick);
pr_sync_AutoMode = pr_sync_AutoMode.Add(tick);
pr_sync_GeneralRelease = pr_sync_GeneralRelease.Add(tick);
pr_sync_ControllerRestart =pr_sync_ControllerRestart.Add(tick);
//only send one "GO" command each tick --> return. The pr_sync_XXXX Timespan is reset when reading the "RO" input command from the Server.
//So take care that the pr_MaxSync greater than "tick" * 7.
if (pr_sync_AutoMode > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_AutoMode);
return; //only send one Command each Tick
}
if (pr_sync_GeneralRelease > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_GeneralRelease);
return; //only send one Command each Tick
}
if(pr_sync_intensity > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_intensity);
return; //only send one Command each Tick
}
if (pr_sync_auxPowerOut > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_auxPowerOut);
return; //only send one Command each Tick
}
if (pr_sync_ConfigNumber > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_ConfigNumber);
return; //only send one Command each Tick
}
if (pr_sync_ControllerRestart > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_ControllerRestart);
return; //only send one Command each Tick
}
if (pr_sync_direction > pr_MaxSync) {
objTelnetConnection.SendCommand("GO " + pr_BitOff_direction);
return; //only send one Command each Tick
}
}
}
public aflexCommunicationClass() {
objSyncTimer = new Timer(objSyncTimer_Tick, null, TimerPeriod, TimerPeriod);
objTelnetConnection = new TCPCommunicationClass();
objTelnetConnection.ResultReceived += ObjTelnetConnection_ResultReceived;
objTelnetConnection.ConnectionAbort += ObjTelnetConnection_ConnectionAbort;
}
private void ObjTelnetConnection_ConnectionAbort(object sender, EventArgs e) {
this.pr_b_LoggedIn = false;
if (aflexValueChanged != null) aflexValueChanged("LoggedIn", new EventArgs());
}
///
/// check the RX string for valid commands
///
/// input string
private void ObjTelnetConnection_ResultReceived(string Result) {
if (Result != null) {
string[] array_result = Result.Split(' '); //split with separator "space"
string str_PropertyName = String.Empty;
if (Result.Contains("\r\nTU")) { //Welcome String of Telnet server
objTelnetConnection.SendCommand("admin");
} else {
if (array_result.Length == 1) { //TU & TP are the only commands with Lengt == 1
switch (array_result[0]) { //after the TCP/IP connection is established the client has to log in on the Server. This is request by the server with the commands "TU" and "TP".
case "TU": //Type User to login to TelnetServer
objTelnetConnection.SendCommand("admin");
break;
case "TP": //Type Password of TelnetServer
objTelnetConnection.SendCommand("TelnetServer");
break;
}
} else if (array_result.Length > 1) { //all other Commands Length > 1
switch (array_result[0]) {
case "RO": //Read Output
str_PropertyName = readRxValue(array_result);
break;
case "AK": //ACK from Set Input Command
str_PropertyName = readRxValue(array_result);
break;
case "ER": //Errorcode
str_PropertyName = "ER:" + array_result[1];
break;
case "LI": //Login/Logout response
if (Convert.ToByte(array_result[1]) == 1) {
pr_b_LoggedIn = true; //Now we can transfer aflex commands to the server
} else {
pr_b_LoggedIn = false;
}
str_PropertyName = "LoggedIn";
break;
case "HBT": //Heartbeat only for visualisation
pr_b_HBT = array_result[1] == "1" ? true : false;
str_PropertyName = "HBT";
break;
}
}
}
if (aflexValueChanged != null) aflexValueChanged(str_PropertyName, new EventArgs());
}
}
///
/// detect the RX commands and get the values
///
/// Rx input string array
/// PropertyName as string
private string readRxValue(string[] Input) {
if (Input.Length >= 2) {
switch (Convert.ToByte(Input[1])) {
case pr_BitOff_AutoMode:
pr_actual_AutoMode = Convert.ToByte(Input[2]);
pr_sync_AutoMode = pr_sync_AutoMode.Subtract(pr_sync_AutoMode); //Reset Sync Timespan
return "AutoMode";
case pr_BitOff_auxPowerOut:
pr_actual_auxPowerOut = Convert.ToUInt16(Input[2]);
pr_sync_auxPowerOut = pr_sync_auxPowerOut.Subtract(pr_sync_auxPowerOut); //Reset Sync Timespan
return "AuxPowerOut";
case pr_BitOff_ConfigNumber:
pr_actual_ConfigNumber = Convert.ToByte(Input[2]);
pr_sync_ConfigNumber = pr_sync_ConfigNumber.Subtract(pr_sync_ConfigNumber); //Reset Sync Timespan
return "ConfigNumber";
case pr_BitOff_ControllerRestart:
pr_actual_ControllerRestart = Convert.ToByte(Input[2]);
pr_sync_ControllerRestart = pr_sync_ControllerRestart.Subtract(pr_sync_ControllerRestart); //Reset Sync Timespan
if (pr_actual_ControllerRestart != 0 && pr_target_ControllerRestart != 0) {
pr_target_ControllerRestart = 0;
objTelnetConnection.SendCommand("SI " + pr_BitOff_ControllerRestart + " " + pr_target_ControllerRestart); //After setting ControllerRestart, reset the Command to start the Restart.
}
return "ControllerRestart";
case pr_BitOff_direction:
pr_actual_direction = Convert.ToUInt16(Input[2]);
pr_sync_direction = pr_sync_direction.Subtract(pr_sync_direction); //Reset Sync Timespan
return "Direction";
case pr_BitOff_GeneralRelease:
pr_actual_GeneralRelease = Convert.ToByte(Input[2]);
pr_sync_GeneralRelease = pr_sync_GeneralRelease.Subtract(pr_sync_GeneralRelease); //Reset Sync Timespan
return "GeneralRelease";
case pr_BitOff_intensity:
pr_actual_intensity = Convert.ToUInt16(Input[2]);
pr_sync_intensity = pr_sync_intensity.Subtract(pr_sync_intensity); //Reset Sync Timespan
return "Intensity";
}
}
return String.Empty;
}
#region Commands
///
/// Establish the connetion to the Telnet Server
///
/// IP Adress of the ControlUnit
/// Port that is configured in the ControlUnit (default Port 23)
public bool Connect(IPAddress IPAdress,int Port) {
return this.objTelnetConnection.Connect(IPAdress, Port);
}
///
/// disconnects from Telnet Server
///
public void Disconnect() {
this.pr_b_LoggedIn = false;
this.objTelnetConnection.Disconnect();
}
///
/// Calculates the target direction and transmits the value to the aflex
///
/// Direction [°]: 0-360 allowed
public void SetDirection (double Degree) {
//Direction Value = (MaxValue / 360) * target dircetion (user manual 6.6.1)
//MaxValue (16Bit) = 65535
if (pr_b_LoggedIn) {
//Calculate UINT16 Value 7
if (Degree <= 360.0 && Degree >= 0.0) {
pr_target_direction = (UInt16)((UInt16.MaxValue / 360.0) * Degree);
objTelnetConnection.SendCommand("SI " + pr_BitOff_direction + " " + pr_target_direction);
}
}
}
///
/// Calculates the target intensity and transmit value to the aflex
///
/// Intensity [%]: 0-100 allowed
public void SetIntensity(double Intensity) {
//Intensity Value = (MaxValue / 100%) * target direction[%] (user manual 6.6.1)
//MaxValue (16Bit) = 65535
if (pr_b_LoggedIn) {
if (Intensity <= 100.0 && Intensity >= 0.0) {
pr_target_intensity = (UInt16)((UInt16.MaxValue / 100.0) * Intensity);
objTelnetConnection.SendCommand("SI " + pr_BitOff_intensity + " " + pr_target_intensity);
}
}
}
///
/// Set the general release of the ControlUnit
///
/// true = release | false = inhibit
public void SetGeneralRelease (bool Value) {
if (pr_b_LoggedIn) {
if (Value) pr_target_GeneralRelease = Byte.MaxValue;
else pr_target_GeneralRelease = 0;
objTelnetConnection.SendCommand("SI " + pr_BitOff_GeneralRelease + " " + pr_target_GeneralRelease);
}
}
///
/// Calculates the target AuxPowerOutput of the ControlUnit and transmitt it. (AuxPowerOut --> Backlight)
///
/// Intensity [%]: 0-100 allowed
public void SetAuxPowerOut(double Intensity) {
//Intensity Value = (MaxValue / 100%) * target direction[%] (user manual 6.6.1)
//MaxValue (16Bit) = 65535
if (pr_b_LoggedIn) {
if (Intensity <= 100.0 && Intensity >= 0.0) {
pr_target_auxPowerOut = (UInt16)((UInt16.MaxValue / 100.0) * Intensity);
objTelnetConnection.SendCommand("SI " + pr_BitOff_auxPowerOut + " " + pr_target_auxPowerOut);
}
}
}
///
/// Load a aflexConfiguration
///
/// Config number to load. 1-49 allowed
public void LoadConfiguration(byte ConfigNumber) {
if (pr_b_LoggedIn) {
if (ConfigNumber < 50 && ConfigNumber > 0) {
pr_target_ConfigNumber = ConfigNumber;
objTelnetConnection.SendCommand("SI " + pr_BitOff_ConfigNumber + " " + pr_target_ConfigNumber);
}
}
}
///
/// restart the ControlUnit. Telnet connection will be lost. Manual reconnect required.
///
public void RestartController() {
if (pr_b_LoggedIn) {
pr_target_ControllerRestart = Byte.MaxValue;
objTelnetConnection.SendCommand("SI " + pr_BitOff_ControllerRestart + " " + pr_target_ControllerRestart);
}
}
#endregion
#region Get/Set
///
/// Client logged in on the Telnet Server
///
public bool LoggedIn {
get {
return pr_b_LoggedIn;
}
}
///
/// actual state of the Telnet Hearbeat. Toggles if connection established
///
public bool HeartbeatState {
get {
return pr_b_HBT;
}
}
///
/// actual aflex intensity as double [%] 0-100%
///
public double actual_intensity {
get {
return (double)((pr_actual_intensity * 100.0 / UInt16.MaxValue));
}
}
///
/// actual aflex direction as double [°] 0-360°
///
public double actual_direction {
get {
return (double)((pr_actual_direction * 360.0 / UInt16.MaxValue)); //Convert uint16 value to double [°]
}
}
///
/// actual ControlUnit auxPowerOutput as double [%] 0-100%
///
public double actual_auxPowerOut {
get {
return (double)((pr_actual_auxPowerOut * 100.0 / UInt16.MaxValue));
}
}
///
/// actual aflex Configuration Number as byte.
///
public byte actual_ConfigNumber {
get {
return pr_actual_ConfigNumber;
}
}
///
/// actual ControlUnit AutoMode. False - Manual | True - Automatic
///
public bool actual_AutoMode {
get {
return pr_actual_AutoMode > 0 ? true : false;
}
}
///
/// actual ControlUnit General Release. False - inhibit | True - released (if inhibit all power outputs are blocked)
///
public bool actual_GeneralRelease {
get {
return pr_actual_GeneralRelease > 0 ? true : false;
}
}
///
/// actual ControlUnit Restart bool
///
public bool actual_ControllerRestart {
get {
return pr_actual_ControllerRestart > 0 ? true : false;
}
}
#endregion
}
}