//Parse Record From Data String public static ControllerRecord ParseRecordFromWatch(byte[] recordPayload) { String debugWatch = BitConverter.ToString(recordPayload).Replace("-", ""); ControllerRecord newRecord = new ControllerRecord(); //Response is by byte, 2 digit year, month, weekday, date, hour, min, seconds. //Ignore weekday. //Format is in BCD try { newRecord.controllerDateTime = new DateTime(2000 + Int32.Parse(recordPayload[0].ToString("X")), Int32.Parse(recordPayload[1].ToString("X")), Int32.Parse(recordPayload[2].ToString("X")), Int32.Parse(recordPayload[4].ToString("X")), Int32.Parse(recordPayload[5].ToString("X")), Int32.Parse(recordPayload[6].ToString("X"))); } catch (Exception e) //Catch if Data is out of Range { return(null); } //I don't know why the record index is split across bytes but it is. I suspect that the high byte is a memory page number. //Look The original code was using 1 Indexed VB Strings and Concatenation To do this. UInt32 lng1 = ((UInt32 )WGTools.NetToUInt16(recordPayload, 7) << 8) + (UInt32)(recordPayload[9] & 0x0F); UInt32 lng2 = ((UInt32)WGTools.NetToUInt16(recordPayload, 10) << 8) + (UInt32)((recordPayload[9] & 0xF0) >> 4); //Check if Card Data Available if ((WGTools.NetToUInt32(recordPayload, 12) != 0xFFFFFFFF) && (WGTools.NetToUInt32(recordPayload, 16) == 0xFFFFFFFF)) { //Lost of Door Status Stuff HEre. Ignore it for now return(null); } newRecord.responseType = recordPayload[25]; newRecord.is10Digit = false; //Read In Card Data if ((newRecord.responseType & 0x04) > 0) { newRecord.cardID = WGTools.NetToUInt32(recordPayload, 12); newRecord.statusByte = recordPayload[20]; newRecord.flagsByte = (byte)((newRecord.statusByte >= 128) ? 0 : 1); //Scan Success? newRecord.readDateTime = WGTools.NetToDateTime32(recordPayload, 16); if (newRecord.readDateTime == DateTime.MinValue) { return(null); } if ((newRecord.responseType & 0x08) > 0) { newRecord.readDateTime.AddSeconds(1.0); } if ((newRecord.responseType & 1L) > 0) { newRecord.is10Digit = true; } return(newRecord); } else { newRecord.cardID = (UInt32)WGTools.NetToUInt16(recordPayload, 19) + (UInt32)recordPayload[21] * 0x10000; newRecord.statusByte = recordPayload[15]; newRecord.flagsByte = (byte)((newRecord.statusByte >= 128) ? 0 : 1); //Scan Success? newRecord.readDateTime = WGTools.NetToDateTime32(recordPayload, 16); if (newRecord.readDateTime == DateTime.MinValue) { return(null); } return(newRecord); } return(null); }
public static List <WGController> ScanNet(UInt16 udpPort) { //Get a List of all NICS, and set up a UDPClient ON Each NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces(); List <UdpClient> clients = new List <UdpClient>(); foreach (NetworkInterface n in nics) { if (n.NetworkInterfaceType == NetworkInterfaceType.Loopback) { continue; //Ignore Loopback Interface } if (n.OperationalStatus != OperationalStatus.Up) { continue; //This adapter is off or not connected } IPInterfaceProperties ipProps = n.GetIPProperties(); if (ipProps == null) { continue; //IP Not Supported } IPv4InterfaceProperties ip4Props = ipProps.GetIPv4Properties(); if (ip4Props == null) { continue; //IPv4 Not Supported } //Build UDPClient List foreach (UnicastIPAddressInformation uc in ipProps.UnicastAddresses) { if (uc.Address.AddressFamily != AddressFamily.InterNetwork) { continue; } IPEndPoint listenEP = new IPEndPoint(uc.Address, 0); UdpClient udpClient = new UdpClient(listenEP); clients.Add(udpClient); } } //Broadcast Status Request to All Interfaces foreach (UdpClient c in clients) { byte[] dgram = WGTools.strTobyte("7EFFFF0111000000000000000000000000000000000000000000000000000010020D"); IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, 60000); int snt = c.Send(dgram, dgram.Length, endPoint); } System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); List <ConnectionInfo.ScanResponse> recvResp = new List <ConnectionInfo.ScanResponse>(); //Listen for 1 second on each interface while (watch.ElapsedMilliseconds < 1500) { foreach (UdpClient c in clients) { try { while (true) { //IPEndPoint object will allow us to read datagrams sent from any source. IPEndPoint remEP = new IPEndPoint(IPAddress.Any, 0); c.Client.ReceiveTimeout = 100; byte[] recvBytes = c.Receive(ref remEP); ConnectionInfo.ScanResponse s = new ConnectionInfo.ScanResponse(); s.ep = (IPEndPoint)c.Client.LocalEndPoint; s.respBytes = recvBytes; lock (recvResp) { recvResp.Add(s); } } } catch //Task Done if Socket is closed, or other exception { } } } //Close All the Clientss foreach (UdpClient c in clients) { c.Close(); } List <WGController> controllers = new List <WGController>(); //Parse Received Bytes foreach (ConnectionInfo.ScanResponse s in recvResp) { byte[] buf = s.respBytes; if (buf.Length != 34) { continue; //Verify Packet Length } if (buf[33] != (byte)13 | buf[0] != (byte)126) { continue; //Verify Start and End Bytes } long checksum = 0; for (int i = 1; i <= 30; i++) { checksum += buf[i]; } //CheckSum if (checksum != (buf[32] * 256L + buf[31])) { continue; //Verify Checksum } string byteString = WGTools.byteTostr(buf); string tst = byteString.Substring(4, 4); if (byteString.Substring(6, 4) != "0111") { continue; //Validate Response Type } WGController controller = new WGController(); controller.Connection.ID = WGTools.NetToUInt16(buf, 1); controller.Connection.MAC = WGTools.NetToMacString(buf, 5); controller.Connection.IP_Address = WGTools.NetToIPString(buf, 11); // $"{buf[12]}.{buf[13]}.{buf[14]}.{buf[15]}"; controller.Connection.Netmask = WGTools.NetToIPString(buf, 15); //$"{buf[16]}.{buf[17]}.{buf[18]}.{buf[19]}"; controller.Connection.Gateway = WGTools.NetToIPString(buf, 19); //$"{buf[20]}.{buf[21]}.{buf[22]}.{buf[23]}"; controller.Connection.udpPort = WGTools.NetToUInt16(buf, 23); controller.Connection.Password = WGTools.NetToUInt32(buf, 25); controller.Connection.HostIP = s.ep.Address; controllers.Add(controller); } return(controllers); }
//SendCommand Helper private byte[] SendCommand(byte[] commCmd, byte[] payload) { //Standard Command is 34 bytes long. TODO: Add helper for specialized longer commands. byte[] dGram = new byte[34]; //Set Start and End Flags dGram[0] = WGParams.CommFlag.COMM_STARTFLAG; dGram[33] = WGParams.CommFlag.COMM_ENDFLAG; //Set Controller ID WGTools.UInt16ToNet(Connection.ID, ref dGram, 1); //Copy Command Array.Copy(commCmd, 0, dGram, 3, 2); //Copy Payload if (payload != null) { Array.Copy(payload, 0, dGram, 5, 26); } //Calculate Checksum UInt16 checksum = 0; for (int i = 1; i <= 30; i++) { checksum += dGram[i]; } //Copy Checksum WGTools.UInt16ToNet(checksum, ref dGram, 31); //Send Data And Wait For Response UdpClient client = new UdpClient(new IPEndPoint(Connection.HostIP, 0)); IPEndPoint endPoint = new IPEndPoint(IPAddress.Broadcast, 60000); int snt = client.Send(dGram, dGram.Length, endPoint); byte[] recvBytes; try { //Wait Up to 1 Second for Response client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000); IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0); recvBytes = client.Receive(ref remoteEP); } catch (Exception x) { //UDP Failed. return(null); } //Verify bytes receive is long enough for our checks if (recvBytes.Length <= 8) //Start/End Flag, ControllerID, Command, CheckSum { return(null); } //Verify Magic Bytes if (recvBytes[0] != WGParams.CommFlag.COMM_STARTFLAG) { return(null); } if (recvBytes[recvBytes.Length - 1] != WGParams.CommFlag.COMM_ENDFLAG) { return(null); } //Verify Controller Index UInt16 remoteID = WGTools.NetToUInt16(recvBytes, 1); if (remoteID != this.Connection.ID) { return(null); } //Verify Controller Command Response UInt16 remoteCmd = WGTools.NetToUInt16(recvBytes, 3); UInt16 localCmd = WGTools.NetToUInt16(commCmd, 0); if (remoteCmd != localCmd) { return(null); } //Verify Checksum //Calculate Checksum UInt16 recvCheckSum = 0; for (int i = 1; i <= recvBytes.Length - 4; i++) { recvCheckSum += recvBytes[i]; } UInt16 recvActCheckSum = WGTools.NetToUInt16(recvBytes, recvBytes.Length - 3); if (recvActCheckSum != recvCheckSum) { return(null); } //TODO: Verify Payload Length based on command byte[] recvPayload = new byte[recvBytes.Length - 8]; Array.Copy(recvBytes, 5, recvPayload, 0, recvPayload.Length); return(recvPayload); }
//Records have 2x records per transaction public static ControllerRecord[] ParseRecordFromRecord(byte[] recordPayload) { ControllerRecord[] newRecords = new ControllerRecord[2]; //First Record //******************************************* newRecords[0] = new ControllerRecord(); newRecords[0].is10Digit = false; newRecords[0].cardID = (UInt32)WGTools.NetToUInt16(recordPayload, 0) + (UInt32)recordPayload[2] * 0x10000; if (newRecords[0].cardID == 22202125) { return(null); } newRecords[0].statusByte = recordPayload[3]; newRecords[0].flagsByte = (byte)((newRecords[0].statusByte >= 128) ? 0 : 1); //Scan Success? //num5 "Character" newRecords[0].readDateTime = WGTools.NetToDateTime32(recordPayload, 4); if (newRecords[0].readDateTime == DateTime.MinValue) { return(null); } //Check if Card Data Available if ((WGTools.NetToUInt64(recordPayload, 8) == 0xFFFFFFFFFFFFFFFF)) { return(null); } //Get Record ID if ((WGTools.NetToUInt32(recordPayload, 8) != 0x00000000) && (WGTools.NetToUInt32(recordPayload, 8) != 0xFFFFFFFF)) { newRecords[0].recordIndex = WGTools.NetToUInt32(recordPayload, 8); } //Record Local Time newRecords[0].localTime = DateTime.Now; if (newRecords[0].cardID == 25565535L) //Special card ID. Not sure what this actually means { newRecords[0] = null; } //Second Record //******************************************* newRecords[1] = new ControllerRecord(); newRecords[1].is10Digit = false; newRecords[1].cardID = (UInt32)WGTools.NetToUInt16(recordPayload, 12) + (UInt32)recordPayload[14] * 0x10000; if (newRecords[1].cardID == 22202125) { newRecords[1] = null; return(newRecords); } newRecords[1].statusByte = recordPayload[15]; newRecords[1].flagsByte = (byte)((newRecords[1].statusByte >= 128) ? 0 : 1); //Scan Success? //num5 "Character" newRecords[1].readDateTime = WGTools.NetToDateTime32(recordPayload, 16); if (newRecords[1].readDateTime == DateTime.MinValue) { newRecords[1] = null; return(newRecords); } //Check if Card Data Available if (WGTools.NetToUInt64(recordPayload, 20) == 0xFFFFFFFFFFFFFFFF) { newRecords[1] = null; return(newRecords); } //Get Record ID if ((WGTools.NetToUInt32(recordPayload, 20) != 0x00000000) && (WGTools.NetToUInt32(recordPayload, 20) != 0xFFFFFFFF)) { newRecords[1].recordIndex = WGTools.NetToUInt32(recordPayload, 20); } //Record Local Time newRecords[1].localTime = DateTime.Now; if (newRecords[1].cardID == 25565535L) //Special card ID. Not sure what this actually means { newRecords[1] = null; return(newRecords); } return(newRecords); }