Пример #1
0
        /// <summary>
        /// passed a sector build a folder containing the sector and all sm's attached to the sector.
        /// </summary>
        /// <param name="ap"></param>
        private Folder generateSector(AccessPointRadioInfo ap, CnLocation location)
        {
            // Create this sectors folder to hold all subscribers
            var sectorFolder = new Folder()
            {
                Name = ap.Name
            };

            // Tracker to know if we should show this sector by default (users are connected to it with bad signal)
            bool showSector = false;

            // Fetch all subscribers for this specific sector.
            var sectorSubscribers = _subscribers.Where(sm => sm.Latitude != 0 && sm.Longitude != 0 && sm.APName == ap.Name);

            sectorFolder.Description = CreateDescriptionFromObject(ap);

            // Loop through and create all the placemarks for these sector subscribers.
            if (settings.showSubscribers)
            {
                foreach (var sm in sectorSubscribers)
                {
                    // Check if the sm coordinates are realistic (within our configured range of the sector)
                    if (sm.DistanceGeoM <= settings.SmInvalidationRangeM)
                    {
                        var smPlacemark = generateSmPlacemark(sm);
                        if (smPlacemark.Visibility == true)
                        {
                            showSector = true;
                        }

                        sectorFolder.AddFeature(smPlacemark);
                    }
                }
            }

            if (ap.Azimuth != 999)
            {
                // Generate the plot to show the coverage based on the sectors azimuth and distance
                var sectorPlot    = generateSectorPlot((double)location.coordinates[1], (double)location.coordinates[0], ap.Azimuth, 500, 90);
                var plotPlacemark = new Placemark()
                {
                    Name = ap.Name + " Coverage", Geometry = sectorPlot, StyleUrl = new Uri($"#plot_{ap.Channel.ToString()}", UriKind.Relative)
                };

                // We chose in settings to always show sector plots
                if (settings.alwaysShowSectorPlot == true)
                {
                    showSector = true;
                }
                ;
                plotPlacemark.Visibility = showSector;
                sectorFolder.AddFeature(plotPlacemark);
            }
            else
            {
                Console.WriteLine($"AP Missing Azimuth: {ap.Name}");
            }

            return(sectorFolder);
        }
Пример #2
0
        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);
        }
Пример #3
0
        /// <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,
            });
        }