using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; using System.Text; using System.Threading.Tasks; namespace FAtoPA { class VX3K { public static bool Started = false; private String targetip = "192.168.14.1"; private UInt16 targetport = 5000; private TcpClient socket; // Statistics public uint TXBytes { get; private set; } = 0; public uint RXBytes { get; private set; } = 0; public uint TXOK { get; private set; } = 0; public uint RXOK { get; private set; } = 0; public uint TXErr { get; private set; } = 0; public uint RXErr { get; private set; } = 0; private readonly EventInterface _event; public VX3K(EventInterface callback){ this._event = callback; } /// /// Connect to VX-3000 /// /// target IP address, default to 192.168.14.1 /// target port, default to 5000 public Boolean Connect(String ipaddress, UInt16 port) { TXBytes = 0; RXBytes = 0; TXOK = 0; RXOK = 0; TXErr = 0; RXErr = 0; raise_statistic(); if (ipaddress!=null && ipaddress.Length>0) { targetip=ipaddress; raise_log("Target IP changed to " + targetip); } if (port>0 && port<65535) { targetport=port; raise_log("Target Port changed to " + targetport); } try { TcpClient newclient = new TcpClient(); bool success = newclient.ConnectAsync(targetip, targetport).Wait(1000); if (success && newclient.Connected) { socket = newclient; raise_connect_status(true, "Connected to " + targetip + ":" + targetport); return true; } else raise_connect_status(false, "Failed to connect to " + targetip + ":" + targetport); } catch(Exception e) { raise_connect_status(false, "Error: " + e.Message); } return false; } /// /// Check if connected to VX-3000 /// /// true if connected public Boolean IsConnected() { if (socket != null) { return socket.Connected; } return false; } /// /// Disconnect from VX-3000 /// public void Disconnect() { if (socket != null) { socket.Close(); socket = null; raise_connect_status(false, "Disconnected from " + targetip + ":" + targetport); } else raise_connect_status(false, "Not connected yet"); } /// /// Set Virtual Contact Input ON/OFF
/// Contact Input ID :
/// 0 - 15 : Contact Input 1 - 16
/// 16 : Emergency Contact input 1
/// 17 : Emergency Contact input 2
///
/// VX Frame ID /// Contact Input ID /// true = ON, false = OFF /// public Boolean Virtual_Contact_Input(UInt16 vxID, UInt16 CinID, Boolean isON) { byte[] payload = new byte[6]; payload[0] = HighByte(vxID); payload[1] = LowByte(vxID); payload[2] = HighByte(CinID); payload[3] = LowByte(CinID); payload[4] = 0x00; payload[5] = (byte)(isON ? 0x01 : 0x00); byte[] cmd = make_header_request_command(0x1001, payload); if (SendCommand(cmd)) { byte[] response = ReadResponse(); if (GetCommandCode(response) == 0x1001) { if (GetResponseCode(response) == 0x0000) { raise_log("Virtual Contact Input Command Success"); return true; } else raise_log("Virtual Contact Input Command Failed, Invalid Response Code"); } else raise_log("Virtual Contact Input Command Failed, Invalid Command Code"); } return false; } /// /// Sending command to VX-3000 /// /// Array of bytes containing command /// true if success private Boolean SendCommand(byte[] cmd) { if (IsConnected() && socket != null) { if (cmd != null && cmd.Length > 0) { try { NetworkStream stream = socket.GetStream(); stream.Write(cmd, 0, cmd.Length); TXBytes += (uint)cmd.Length; TXOK++; raise_statistic(); return true; } catch (Exception e) { raise_log("SendCommand failed, Error : "+e); } } else raise_log("SendCommand failed, Invalid Command"); } else raise_log("SendCommand failed, Not Connected to VX-3000"); TXErr++; raise_statistic(); return false; } /// /// Reading response from VX-3000 /// /// array of bytes containing response , or empty array if failed private byte[] ReadResponse() { if (IsConnected() && socket != null) { try { NetworkStream stream = socket.GetStream(); byte[] response = new byte[1500]; int bytes = stream.Read(response, 0, response.Length); RXBytes += (uint)bytes; RXOK++; raise_statistic(); byte[] result = new byte[bytes]; Array.Copy(response, result, bytes); return result; } catch (Exception e) { raise_log("ReadResponse failed, Error : " + e); } } else raise_log("ReadResponse failed, Not Connected to VX-3000"); RXErr++; raise_statistic(); return Array.Empty(); } /// /// Create VX-3000 command bytes /// /// command code /// payload to send /// array of bytes private byte[] make_header_request_command(UInt16 command, byte[] payload) { UInt16 cmdlen = 8; if (payload != null && payload.Length > 0) cmdlen += (UInt16)payload.Length; byte[] header = new byte[cmdlen]; header[0] = HighByte(command); header[1] = LowByte(command); header[2] = 0x00; header[3] = 0x00; header[4] = HighByte(cmdlen); header[5] = LowByte(cmdlen); header[6] = 0x80; // request to VX3000 header[7] = 0x00; if (payload == null) return header; // no payload if (payload.Length == 0) return header; // no payload for(int i=0; i /// Return High Byte of a 16-bit value /// /// 16 bit value /// Byte value private byte HighByte(UInt16 value) { return (byte)((value >> 8) & 0xFF); } /// /// Return Low Byte of a 16-bit value /// /// 16 bit value /// Byte value private byte LowByte(UInt16 value) { return (byte)(value & 0xFF); } /// /// Get Command Code from response /// Command Code value is Big-Endian UInt16 from index 0 and 1 /// /// array of byte from Response /// Command Code or 0 if failed private UInt16 GetCommandCode(byte[] value) { if (value != null && value.Length >= 2) { return (UInt16)((value[0] << 8) | value[1]); } return 0; } /// /// Get Response Code from response /// Response Code value is Big-Endian UInt16 from index 2 and 3 /// /// array of byte from Response /// Response Code or 0 if failed private UInt16 GetResponseCode(byte[] value) { if (value != null && value.Length >= 4) { return (UInt16)((value[2] << 8) | value[3]); } return 0; } /// /// Get Command Length from response /// Command Length value is Big-Endian UInt16 from index 4 and 5 /// /// array of byte from Response /// Command Length or 0 if failed private UInt16 GetCommandLength(byte[] value) { if (value != null && value.Length >= 6) { return (UInt16)((value[4] << 8) | value[5]); } return 0; } /// /// Get Command Flag from response /// Command Flag value is Byte at index 6 /// /// array of byte from Response /// Command Flag or 0 if failed private byte GetCommandFlag(byte[] value) { if (value != null && value.Length >= 7) { return value[6]; } return 0; } /// /// Get Payload from Response /// Payload is located at index 8 to end of array /// /// array of byte from Response /// Payload bytes or empty array if failed private byte[] GetPayload(byte[] value) { if (value != null && value.Length > 8) { if ((GetCommandFlag(value) & 0x40) != 0) { byte[] payload = new byte[value.Length - 8]; Array.Copy(value, 8, payload, 0, payload.Length); return payload; } } return Array.Empty(); } private void raise_log(String msg) { if (_event!=null) _event.Log(msg); } private void raise_statistic() { if (_event != null) _event.StatisticUpdate(TXOK,RXOK, TXErr,RXErr,TXBytes,RXBytes); } private void raise_connect_status(bool success, String message) { if (_event != null) _event.ConnectStatus(success, message); } } }