/// <summary> /// Calculates the signal strength based off Block Error Rate thresholds /// </summary> /// <returns></returns> private static void CalculateSignalStrength(StatsPacketModel Packet) { if (Packet.BlockError < 11) // 0-10 Packet.SignalStrength = 5; else if (Packet.BlockError < 31) // 11-30 Packet.SignalStrength = 4; else if (Packet.BlockError < 51) // 31-50 Packet.SignalStrength = 3; else if (Packet.BlockError < 71) // 51-70 Packet.SignalStrength = 2; else if (Packet.BlockError < 91) // 71-90 Packet.SignalStrength = 1; else // 91-100 Packet.SignalStrength = 0; }
/// <summary> /// Updates the current info with the given stats information /// </summary> /// <param name="Stats"></param> public void Update(StatsPacketModel Stats) { if (Stats != null) { this.MACAddress = Stats.MACAddress; this.SignalStrength = Stats.SignalStrength; this.QualityLED = Stats.QualityLED; this.Ethernet = Stats.Ethernet; } }
/// <summary> /// Parses The Stats Response UDP packet from a radio control /// little endian: Network ID, Total packets, Failed Packets, Passed Packets, Broadcast Packets, Unicast Packets, AverageTX, /// AverageRX, BER, and RSSI will look backwards /// </summary> /// <param name="packet">Packet received from Stats request on radio</param> public static StatsPacketModel ParseStatsPacket(byte[] packet) { StatsPacketModel Info = new StatsPacketModel(); int offset = 3; // Offset 3 MAC Address - 6 bytes Info.MACAddress = ParseMAC(packet, ref offset); // Offset 9 Network ID - 4 bytes byte[] network = Encoding.Convert(Encoding.BigEndianUnicode, Encoding.Unicode, packet, offset, 4); // change to little endian Info.NetworkID = BitConverter.ToString(network); offset += 4; // Offset 13 Radio Status, RF Connected/RadioActive/RFChannel - 1 byte #region Bit Checking int temp = packet[offset] >> 6; if (temp >= 2) { Info.RFConnect = true; // Bit 7 of RadioStatus byte is T/F RF Connected temp -= 2; } else { Info.RFConnect = false; } if (temp == 1) { Info.RadioActive = true; // Bit 6 of RadioStatus byte is T/F RFActive } else { Info.RadioActive = false; } #endregion Info.RFChannel = ((byte)(packet[offset++] << 2) >> 2); // bit 5:0 is RFChannel - cut off bit 7:6 // Offset 14 Ethernet Status, Link Up/Full Duplex/10 Mbps - 1 byte #region Bit Checking temp = packet[offset++] >> 5; if (temp >= 4) { Info.EthernetLink = true; // bit 7 is T/F Link Up temp -= 4; } else { Info.EthernetLink = false; } if (temp >= 2) { Info.EthernetDuplex = true; // bit 6 is T/F Full Duplex temp -= 2; } else { Info.EthernetDuplex = false; } if (temp == 1) { Info.EthernetSpeed = true; // bit 5 is T/F 100 Mbps } else { Info.EthernetSpeed = false; } #endregion if (Info.EthernetLink) { if (Info.EthernetSpeed) { Info.Ethernet = "100 Mbps"; if (Info.EthernetDuplex) { Info.Ethernet += " Full Duplex"; } } else if (Info.EthernetDuplex) { Info.Ethernet = "Full Duplex"; } } else { Info.Ethernet = "Disconnected"; } // Offset 15 Device ID, Server/Client/(Number of IDs or Device ID) - 1 byte temp = packet[offset] >> 6; if (temp == 3) // b7:b6 = 1:1 is Client { Info.Device = StatsPacketModel.DeviceType.Client; } else if (temp == 0) // b7:b6 = 0:0 is Device Not Configured { Info.Device = StatsPacketModel.DeviceType.NotConfigured; } else // b7:b6 = 1:0 or 0:1 is Server { Info.Device = StatsPacketModel.DeviceType.Server; } Info.DeviceID = ((byte)(packet[offset++] << 2) >> 2); // Device ID/Number of Clients // Offset 16 byte 7 - Determine if set to manual or automatic channel mode Info.IsManualChannelMode = (packet[offset] & (1 << 7)) != 0; // Offset 16 bytes 6:0 Number of connected Client - only Server will have number other than 0 Info.ConnectedDevices = packet[offset++] & 127; // bitwise AND with value 127 since we only want bits 6:0 (not bit 7) // Offset 17 Total Packets Info.TotalPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian offset += 4; // Offset 21 Failed Packets Info.FailedPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian offset += 4; // Offset 25 Passed Packets Info.PassedPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian offset += 4; // Offset 29 Broadcast Packets Info.BroadcastPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian offset += 4; // Offset 33 Unicast Packets Info.UnicastPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian offset += 4; // Offset 37 AverageTXSize Info.AverageTXSize = BitConverter.ToUInt16(packet, offset); // 2 bytes - little endian offset += 2; // Offset 39 AverageRXSize Info.AverageRXSize = BitConverter.ToUInt16(packet, offset); // 2 bytes - little endian offset += 2; // Offset 41 Block Error Rate - invert from 0-100 to 100-0 // 2 bytes (first is 0-100) Info.BlockError = (float)(packet[offset]) + (float)(packet[offset + 1]) / 100; // Second byte is 0-99 hundrendths) Info.SignalPercent = (-(Info.BlockError - 101) - 1).ToString() + "%"; offset += 2; // increment offset CalculateSignalStrength(Info); // Calculate Signal Strength bars // Offset 43 RSSI - 1 byte Info.RSSI = ((sbyte)packet[offset++]).ToString() + " dBm"; // Offset 44 RFVersion - 3 bytes // Byte 1 RF Protocol (4 = multipoint) Info.RFProtocol = (StatsPacketModel.ProtocolType)packet[offset++]; // Byte 2 Frequency (3 = 900 Mhz full band, 4 = 5800 MHz, 5 = 900 Mhz Half Band, 6 = 2400 MHz) Info.RadioVersion = (StatsPacketModel.RadioVersions)packet[offset++]; // Byte 3 Firmware Release Number Info.RadioFirmware = Convert.ToString(packet[offset++], 16); // Offset 47 Ethernet Version - ASCII string with '.' separation between major, minor, and build numbers Info.Version = ASCIIEncoding.ASCII.GetString(packet, offset, 9); offset += 9; // Offset 56 Quality LEDs #region LED selector switch (packet[offset]) { case 63: { Info.QualityLED = 6; break; } case 31: { Info.QualityLED = 5; break; } case 15: { Info.QualityLED = 4; break; } case 7: { Info.QualityLED = 3; break; } case 3: { Info.QualityLED = 2; break; } case 1: { Info.QualityLED = 1; break; } default: { Info.QualityLED = 0; break; } } offset += 1; #endregion // Offset 58 Radio Uptime if (packet.Length >= offset + 4) { var seconds = BitConverter.ToUInt32(packet, offset); Info.Uptime = TimeSpan.FromSeconds(seconds); offset += 4; } // Current time Info.LastUpdate = DateTime.Now; //Spews info into a Text file --DEVELOPMENT return Info; }