static AccessPointRadioInfo generateAccessPoint(CnStatistics ap, string ip, string sysContact) { var apRI = new AccessPointRadioInfo() { Name = ap.name, Esn = ap.mac, IP = ip, ConnectedSMs = ap.connected_sms, Lan = ap.lan_status, Channel = Double.Parse(ap.radio.frequency), ColorCode = Byte.Parse(ap.radio.color_code), SyncState = ap.radio.sync_state, TxPower = ap.radio.tx_power ?? 0, Tower = ap.tower, Azimuth = 0, Downtilt = 0, Uptime = TimeSpan.FromSeconds(Double.Parse(ap.status_time)) }; // Parse the sysContact into Azimuth and Downtilt var azdtMatch = Regex.Match(sysContact, @"\[(?<azimuth>\d*)AZ\s(?<downtilt>\d*)DT\]"); if (azdtMatch.Success) { // If we can parse the azimuth and downtilt save it to the AP if we can't set it to an invalid value so we know it wasn't good (0 would be a valid value so would -1) var goodAzimuth = Int32.TryParse(azdtMatch.Groups["azimuth"].ToString(), out int azimuth); var goodDowntilt = Int32.TryParse(azdtMatch.Groups["downtilt"].ToString(), out int downtilt); apRI.Azimuth = goodAzimuth ? azimuth : 999; apRI.Downtilt = goodDowntilt ? downtilt : 999; } return(apRI); }
/// <summary> /// Generate our unified SM View based on the AP & SM Device and Statistics from cnMaestro, /// as well as snmp we had to pull direct, and return a clean object. /// </summary> /// <param name="apDevice"></param> /// <param name="apInfo"></param> /// <param name="smDevice"></param> /// <param name="smStats"></param> /// <param name="smSnmp"></param> /// <returns></returns> public static SubscriberRadioInfo GenerateSmRadioInfo(CnDevice apDevice, AccessPointRadioInfo apInfo, CnDevice smDevice, CnStatistics smStats, IDictionary <string, string> smSnmp) { Double.TryParse(smSnmp[SNMP.OIDs.smFrequencyHz], out double smFrequencyHz); Int32.TryParse(smSnmp[SNMP.OIDs.smAirDelayNs], out int smAirDelayNs); double smDistanceM = RFCalc.MetersFromAirDelay(smAirDelayNs, smFrequencyHz, false); // If we have smGain from cnMaestro let's use it if not fall back to our configured value. Int32.TryParse(smStats.gain, out int smGain); if (smGain <= 0) { smGain = cambiumRadios.SM[smDevice.product].AntennaGain; } // Odd irregularity where cnMaestro sends a -30 let's assume max Tx since it's obviously transmitting as we have a SM to calculate on the panel. var apTx = apInfo.TxPower; if (apTx <= 0) { apTx = cambiumRadios.AP[apDevice.product].MaxTransmit; } // smEPL === The power transmitted from the AP and what we expect to see on the SM var smEPL = RFCalc.EstimatedPowerLevel( smDistanceM, smFrequencyHz, 0, Tx: cambiumRadios.AP[apDevice.product].Radio(apTx), Rx: cambiumRadios.SM[smDevice.product].Radio(smStats.radio.tx_power, smGain)); // apEPL === The power transmitted from the SM and what we expect to see on the AP var apEPL = RFCalc.EstimatedPowerLevel( smDistanceM, smFrequencyHz, 0, Tx: cambiumRadios.SM[smDevice.product].Radio(smStats.radio.tx_power, smGain), Rx: cambiumRadios.AP[apDevice.product].Radio(apTx)); Console.WriteLine($"Generated SM DeviceInfo: {smDevice.name}"); //TODO: change coordinate system to use a strongly typed lat/long not the coordinates from cnLocation that are just an array as its confusing. var GeoDistance = GeoCalc.GeoDistance((double)smDevice.location.coordinates[1], (double)smDevice.location.coordinates[0], (double)apDevice.location.coordinates[1], (double)apDevice.location.coordinates[0]); return(new SubscriberRadioInfo() { Name = smDevice.name, Esn = smDevice.mac, Tower = apDevice.tower, Firmware = smDevice.software_version, Latitude = smDevice.location.coordinates[1], Longitude = smDevice.location.coordinates[0], SmGain = smGain, APName = apDevice.name, DistanceM = (int)smDistanceM, DistanceGeoM = (int)GeoDistance, IP = smDevice.ip, Model = smDevice.product, SmEPL = Math.Round(smEPL, 2), SmAPL = smStats.radio.dl_rssi ?? -1, SmSNRH = smStats.radio.dl_snr_h ?? -1, SmSNRV = smStats.radio.dl_snr_v ?? -1, ApSNRH = smStats.radio.ul_snr_h ?? -1, ApSNRV = smStats.radio.ul_snr_v ?? -1, SmImbalance = smStats.radio.dl_rssi_imbalance ?? 0, ApModel = apDevice.product, ApEPL = Math.Round(apEPL, 2), ApAPL = smStats.radio.ul_rssi ?? -1, ApTxPower = apTx, SmTxPower = smStats.radio.tx_power ?? cambiumRadios.SM[smDevice.product].MaxTransmit, SmMaxTxPower = cambiumRadios.SM[smDevice.product].MaxTransmit, }); }