/// <summary> /// Generate a polygon that represents the coverage area of a sector based on azimuth and distance specified /// </summary> /// <param name="latitude"></param> /// <param name="longitude"></param> /// <param name="azimuth"></param> /// <param name="meters"></param> private Polygon generateSectorPlot(double latitude, double longitude, double azimuth, double distance, double sectorWidth, double sectorPointSplit = 8) { var sectorEdges = new LinearRing(); var Coordinates = new CoordinateCollection { new Vector(latitude, longitude) // Starting point }; // Find the first point of the arc var startAzi = azimuth - (sectorWidth / 2); if (startAzi < 0) { startAzi = 360 + startAzi; } ; for (double x = 0; x <= sectorWidth; x += (sectorWidth / sectorPointSplit)) // Split the total number of points on the arc { var newAzi = startAzi + x > 360 ? startAzi + x - 360 : startAzi + x; var newLocation = GeoCalc.LocationFromAzimuth(latitude, longitude, distance, newAzi); // Find this point on the arc lat/long Coordinates.Add(new Vector(newLocation.latitude, newLocation.longitude)); } Coordinates.Add(new Vector(latitude, longitude)); // Close point sectorEdges.Coordinates = Coordinates; return(new Polygon() { OuterBoundary = new OuterBoundary { LinearRing = sectorEdges } }); }
public void GetBoundingBox() { var bBox = GeoCalc.GetBoundingBox(TestConstants.NEPoint, 2000, 2000); Assert.AreEqual(45, Geometry.ToBearingDegrees(GeoCalc.GetBearing(bBox.SouthWestVertex, TestConstants.NEPoint)), 1); Assert.AreEqual(225, Geometry.ToBearingDegrees(GeoCalc.GetBearing(bBox.NorthEastVertex, TestConstants.NEPoint)), 1); Assert.AreEqual(2828, GeoCalc.GetDistance(bBox.SouthWestVertex, bBox.NorthEastVertex), 3); }
/// <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, }); }