/********************************************************************* * * 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 } }