Issues (2963)

LibreNMS/OS/Pmp.php (1 issue)

1
<?php
2
/**
3
 * Pmp.php
4
 *
5
 * Cambium
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19
 *
20
 * @link       https://www.librenms.org
21
 *
22
 * @copyright  2017 Paul Heinrichs
23
 * @author     Paul Heinrichs<[email protected]>
24
 */
25
26
namespace LibreNMS\OS;
27
28
use App\Models\Device;
29
use Illuminate\Support\Str;
30
use LibreNMS\Device\WirelessSensor;
31
use LibreNMS\Interfaces\Discovery\Sensors\WirelessClientsDiscovery;
32
use LibreNMS\Interfaces\Discovery\Sensors\WirelessErrorsDiscovery;
33
use LibreNMS\Interfaces\Discovery\Sensors\WirelessFrequencyDiscovery;
34
use LibreNMS\Interfaces\Discovery\Sensors\WirelessRssiDiscovery;
35
use LibreNMS\Interfaces\Discovery\Sensors\WirelessSnrDiscovery;
36
use LibreNMS\Interfaces\Discovery\Sensors\WirelessSsrDiscovery;
37
use LibreNMS\Interfaces\Discovery\Sensors\WirelessUtilizationDiscovery;
38
use LibreNMS\Interfaces\Polling\OSPolling;
39
use LibreNMS\OS;
40
use LibreNMS\RRD\RrdDefinition;
41
42
class Pmp extends OS implements
43
    OSPolling,
44
    WirelessRssiDiscovery,
45
    WirelessSnrDiscovery,
46
    WirelessFrequencyDiscovery,
47
    WirelessUtilizationDiscovery,
48
    WirelessSsrDiscovery,
49
    WirelessClientsDiscovery,
50
    WirelessErrorsDiscovery
51
{
52
    public function discoverOS(Device $device): void
53
    {
54
        parent::discoverOS($device); // yaml
55
        $data = snmp_get_multi_oid($this->getDeviceArray(), ['boxDeviceType.0', 'bhTimingMode.0', 'boxDeviceTypeID.0'], '-OQUs', 'WHISP-BOX-MIBV2-MIB');
56
        $device->features = $data['boxDeviceType.0'] ?? null;
57
58
        $ptp = [
59
            'BHUL450' => 'PTP 450',
60
            'BHUL' => 'PTP 230',
61
            'BH20' => 'PTP 100',
62
        ];
63
64
        foreach ($ptp as $desc => $model) {
65
            if (Str::contains($device->features, $desc)) {
66
                $hardware = $model . ' ' . str_replace(['timing', 'timeing'], '', $data['bhTimingMode.0']);
67
                $device->version = $data['boxDeviceTypeID.0'] ?? $device->version;
68
                break;
69
            }
70
        }
71
72
        $pmp = [
73
            'MU-MIMO OFDM' => 'PMP 450m',
74
            'MIMO OFDM' => 'PMP 450',
75
            'OFDM' => 'PMP 430',
76
        ];
77
78
        if (! isset($hardware)) {
79
            $hardware = 'PMP 100';
80
            foreach ($pmp as $desc => $model) {
81
                if (Str::contains($device->features, $desc)) {
82
                    $hardware = $model;
83
                    break;
84
                }
85
            }
86
            if (Str::contains($device->sysDescr, 'AP')) {
87
                $hardware .= ' AP';
88
            } elseif (Str::contains($device->sysDescr, 'SM')) {
89
                $hardware .= ' SM';
90
            }
91
        }
92
93
        $device->hardware = $hardware;
94
    }
95
96
    public function pollOS()
97
    {
98
        // Migrated to Wireless Sensor
99
        $fec = snmp_get_multi_oid($this->getDeviceArray(), ['fecInErrorsCount.0', 'fecOutErrorsCount.0', 'fecCRCError.0'], '-OQUs', 'WHISP-BOX-MIBV2-MIB');
100
        if (is_numeric($fec['fecInErrorsCount.0']) && is_numeric($fec['fecOutErrorsCount.0'])) {
101
            $rrd_def = RrdDefinition::make()
102
                ->addDataset('fecInErrorsCount', 'GAUGE', 0, 100000)
103
                ->addDataset('fecOutErrorsCount', 'GAUGE', 0, 100000);
104
105
            $fields = [
106
                'fecInErrorsCount' => $fec['fecInErrorsCount.0'],
107
                'fecOutErrorsCount' => $fec['fecOutErrorsCount.0'],
108
            ];
109
            $tags = compact('rrd_def');
110
            data_update($this->getDeviceArray(), 'canopy-generic-errorCount', $tags, $fields);
111
            $this->enableGraph('canopy_generic_errorCount');
112
        }
113
114
        // Migrated to Wireless Sensor
115
        if (is_numeric($fec['fecCRCError.0'])) {
116
            $rrd_def = RrdDefinition::make()->addDataset('crcErrors', 'GAUGE', 0, 100000);
117
            $fields = [
118
                'crcErrors' => $fec['fecCRCError.0'],
119
            ];
120
            $tags = compact('rrd_def');
121
            data_update($this->getDeviceArray(), 'canopy-generic-crcErrors', $tags, $fields);
122
            $this->enableGraph('canopy_generic_crcErrors');
123
        }
124
125
        $jitter = snmp_get($this->getDeviceArray(), 'jitter.0', '-Ovqn', 'WHISP-SM-MIB');
126
        if (is_numeric($jitter)) {
127
            $rrd_def = RrdDefinition::make()->addDataset('jitter', 'GAUGE', 0, 20);
128
            $fields = [
129
                'jitter' => $jitter,
130
            ];
131
            $tags = compact('rrd_def');
132
            data_update($this->getDeviceArray(), 'canopy-generic-jitter', $tags, $fields);
133
            $this->enableGraph('canopy_generic_jitter');
134
            unset($rrd_def, $jitter);
135
        }
136
137
        $multi_get_array = snmp_get_multi($this->getDeviceArray(), ['regCount.0', 'regFailureCount.0'], '-OQU', 'WHISP-APS-MIB');
138
        d_echo($multi_get_array);
139
        $registered = $multi_get_array[0]['WHISP-APS-MIB::regCount'];
140
        $failed = $multi_get_array[0]['WHISP-APS-MIB::regFailureCount'];
141
142
        if (is_numeric($registered) && is_numeric($failed)) {
143
            $rrd_def = RrdDefinition::make()
144
                ->addDataset('regCount', 'GAUGE', 0, 15000)
145
                ->addDataset('failed', 'GAUGE', 0, 15000);
146
            $fields = [
147
                'regCount' => $registered,
148
                'failed' => $failed,
149
            ];
150
            $tags = compact('rrd_def');
151
            data_update($this->getDeviceArray(), 'canopy-generic-regCount', $tags, $fields);
152
            $this->enableGraph('canopy_generic_regCount');
153
            unset($rrd_def, $registered, $failed);
154
        }
155
156
        $visible = str_replace('"', '', snmp_get($this->getDeviceArray(), '.1.3.6.1.4.1.161.19.3.4.4.7.0', '-Ovqn', ''));
157
        $tracked = str_replace('"', '', snmp_get($this->getDeviceArray(), '.1.3.6.1.4.1.161.19.3.4.4.8.0', '-Ovqn', ''));
158
        if (is_numeric($visible) && is_numeric($tracked)) {
159
            $rrd_def = RrdDefinition::make()
160
                ->addDataset('visible', 'GAUGE', 0, 1000)
161
                ->addDataset('tracked', 'GAUGE', 0, 1000);
162
            $fields = [
163
                'visible' => floatval($visible),
164
                'tracked' => floatval($tracked),
165
            ];
166
            $tags = compact('rrd_def');
167
            data_update($this->getDeviceArray(), 'canopy-generic-gpsStats', $tags, $fields);
168
            $this->enableGraph('canopy_generic_gpsStats');
169
        }
170
171
        $radio = snmp_get_multi_oid($this->getDeviceArray(), ['radioDbmInt.0', 'minRadioDbm.0', 'maxRadioDbm.0', 'radioDbmAvg.0'], '-OQUs', 'WHISP-SM-MIB');
172
        if (is_numeric($radio['radioDbmInt.0']) && is_numeric($radio['minRadioDbm.0']) && is_numeric($radio['maxRadioDbm.0']) && is_numeric($radio['radioDbmAvg.0'])) {
173
            $rrd_def = RrdDefinition::make()
174
                ->addDataset('dbm', 'GAUGE', -100, 0)
175
                ->addDataset('min', 'GAUGE', -100, 0)
176
                ->addDataset('max', 'GAUGE', -100, 0)
177
                ->addDataset('avg', 'GAUGE', -100, 0);
178
179
            $fields = [
180
                'dbm' => $radio['radioDbmInt.0'],
181
                'min' => $radio['minRadioDbm.0'],
182
                'max' => $radio['maxRadioDbm.0'],
183
                'avg' => $radio['radioDbmAvg.0'],
184
            ];
185
            $tags = compact('rrd_def');
186
            data_update($this->getDeviceArray(), 'canopy-generic-radioDbm', $tags, $fields);
187
            $this->enableGraph('canopy_generic_radioDbm');
188
        }
189
190
        $dbm = snmp_get_multi_oid($this->getDeviceArray(), ['linkRadioDbmHorizontal.2', 'linkRadioDbmVertical.2'], '-OQUs', 'WHISP-APS-MIB');
191
        if (is_numeric($dbm['linkRadioDbmHorizontal.2']) && is_numeric($dbm['linkRadioDbmVertical.2'])) {
192
            $rrd_def = RrdDefinition::make()
193
                ->addDataset('horizontal', 'GAUGE', -100, 0)
194
                ->addDataset('vertical', 'GAUGE', -100, 0);
195
            $fields = [
196
                'horizontal' => $dbm['linkRadioDbmHorizontal.2'],
197
                'vertical' => $dbm['linkRadioDbmVertical.2'],
198
            ];
199
            $tags = compact('rrd_def');
200
            data_update($this->getDeviceArray(), 'canopy-generic-450-linkRadioDbm', $tags, $fields);
201
            $this->enableGraph('canopy_generic_450_linkRadioDbm');
202
        }
203
204
        $lastLevel = str_replace('"', '', snmp_get($this->getDeviceArray(), 'lastPowerLevel.2', '-Ovqn', 'WHISP-APS-MIB'));
205
        if (is_numeric($lastLevel)) {
206
            $rrd_def = RrdDefinition::make()->addDataset('last', 'GAUGE', -100, 0);
207
            $fields = [
208
                'last' => $lastLevel,
209
            ];
210
            $tags = compact('rrd_def');
211
            data_update($this->getDeviceArray(), 'canopy-generic-450-powerlevel', $tags, $fields);
212
            $this->enableGraph('canopy_generic_450_powerlevel');
213
        }
214
215
        $vertical = str_replace('"', '', snmp_get($this->getDeviceArray(), '.1.3.6.1.4.1.161.19.3.2.2.117.0', '-Ovqn', ''));
216
        $horizontal = str_replace('"', '', snmp_get($this->getDeviceArray(), '.1.3.6.1.4.1.161.19.3.2.2.118.0', '-Ovqn', ''));
217
        $combined = snmp_get($this->getDeviceArray(), '1.3.6.1.4.1.161.19.3.2.2.21.0', '-Ovqn', '');
218
        if (is_numeric($vertical) && is_numeric($horizontal) && is_numeric($combined)) {
219
            $rrd_def = RrdDefinition::make()
220
                ->addDataset('vertical', 'GAUGE', -150, 0)
221
                ->addDataset('horizontal', 'GAUGE', -150, 0)
222
                ->addDataset('combined', 'GAUGE', -150, 0);
223
            $fields = [
224
                'vertical' => floatval($vertical),
225
                'horizontal' => floatval($horizontal),
226
                'combined' => $combined,
227
            ];
228
            $tags = compact('rrd_def');
229
            data_update($this->getDeviceArray(), 'canopy-generic-signalHV', $tags, $fields);
230
            $this->enableGraph('canopy_generic_signalHV');
231
            unset($rrd_def, $vertical, $horizontal, $combined);
232
        }
233
234
        $horizontal = str_replace('"', '', snmp_get($this->getDeviceArray(), 'radioDbmHorizontal.0', '-Ovqn', 'WHISP-SM-MIB'));
235
        $vertical = str_replace('"', '', snmp_get($this->getDeviceArray(), 'radioDbmVertical.0', '-Ovqn', 'WHISP-SM-MIB'));
236
        if (is_numeric($horizontal) && is_numeric($vertical)) {
237
            $rrd_def = RrdDefinition::make()
238
                ->addDataset('horizontal', 'GAUGE', -100, 100)
239
                ->addDataset('vertical', 'GAUGE', -100, 100);
240
241
            $fields = [
242
                'horizontal' => $horizontal,
243
                'vertical' => $vertical,
244
            ];
245
            $tags = compact('rrd_def');
246
            data_update($this->getDeviceArray(), 'canopy-generic-450-slaveHV', $tags, $fields);
247
            $this->enableGraph('canopy_generic_450_slaveHV');
248
        }
249
    }
250
251
    /**
252
     * Discover wireless bit/packet error ratio.  This is in percent. Type is error-ratio.
253
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
254
     *
255
     * @return array Sensors
256
     */
257
    public function discoverWirelessRssi()
258
    {
259
        $rssi_oid = '.1.3.6.1.4.1.161.19.3.2.2.2.0';
260
261
        return [
262
            new WirelessSensor(
263
                'rssi',
264
                $this->getDeviceId(),
265
                $rssi_oid,
266
                'pmp',
267
                0,
268
                'Cambium RSSI',
269
                null
270
            ),
271
        ];
272
    }
273
274
    /**
275
     * Discover wireless SNR.  This is in dB. Type is snr.
276
     * Formula: SNR = Signal or Rx Power - Noise Floor
277
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
278
     *
279
     * @return array Sensors
280
     */
281
    public function discoverWirelessSnr()
282
    {
283
        if ($this->isAp()) {
284
            $snr_horizontal = '.1.3.6.1.4.1.161.19.3.1.4.1.84.2'; // WHISP-APS-MIB::signalToNoiseRatioHorizontal.2
285
            $snr_vertical = '.1.3.6.1.4.1.161.19.3.1.4.1.74.2'; //WHISP-APS-MIB::signalToNoiseRatioVertical.2
286
        } else {
287
            $snr_horizontal = '.1.3.6.1.4.1.161.19.3.2.2.106.0'; // WHISP-SMS-MIB::signalToNoiseRatioSMHorizontal.0
288
            $snr_vertical = '.1.3.6.1.4.1.161.19.3.2.2.95.0'; //WHISP-SMS-MIB::signalToNoiseRatioSMVertical.0
289
        }
290
291
        return [
292
            new WirelessSensor(
293
                'snr',
294
                $this->getDeviceId(),
295
                $snr_horizontal,
296
                'pmp-h',
297
                0,
298
                'Cambium SNR Horizontal',
299
                null
300
            ),
301
            new WirelessSensor(
302
                'snr',
303
                $this->getDeviceId(),
304
                $snr_vertical,
305
                'pmp-v',
306
                0,
307
                'Cambium SNR Vertical',
308
                null
309
            ),
310
        ];
311
    }
312
313
    /**
314
     * Discover wireless frequency.  This is in MHz. Type is frequency.
315
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
316
     *
317
     * @return array Sensors
318
     */
319
    public function discoverWirelessFrequency()
320
    {
321
        $frequency = '.1.3.6.1.4.1.161.19.3.1.7.37.0'; //WHISP-APS-MIB::currentRadioFreqCarrier
322
323
        return [
324
            new WirelessSensor(
325
                'frequency',
326
                $this->getDeviceId(),
327
                $frequency,
328
                'pmp',
329
                0,
330
                'Frequency',
331
                null,
332
                1,
333
                $this->freqDivisor()
334
            ),
335
        ];
336
    }
337
338
    /**
339
     * Discover wireless utilization.  This is in %. Type is utilization.
340
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
341
     *
342
     * @return array Sensors
343
     */
344
    public function discoverWirelessUtilization()
345
    {
346
        $lowdownlink = '.1.3.6.1.4.1.161.19.3.1.12.1.1.0'; // WHISP-APS-MIB::frUtlLowTotalDownlinkUtilization
347
        $lowuplink = '.1.3.6.1.4.1.161.19.3.1.12.1.2.0'; // WHISP-APS-MIB::frUtlLowTotalUplinkUtilization
348
        $meddownlink = '.1.3.6.1.4.1.161.19.3.1.12.2.1.0'; // WHISP-APS-MIB::frUtlMedTotalDownlinkUtilization
349
        $meduplink = '.1.3.6.1.4.1.161.19.3.1.12.2.2.0'; // WHISP-APS-MIB::frUtlMedTotalUplinkUtilization
350
        $highdownlink = '.1.3.6.1.4.1.161.19.3.1.12.3.1.0'; // WHISP-APS-MIB::frUtlHighTotalDownlinkUtilization
351
        $highuplink = '.1.3.6.1.4.1.161.19.3.1.12.3.2.0'; // WHISP-APS-MIB::frUtlHighTotalUplinkUtilization
352
353
        // 450M Specific Utilizations
354
        $muSectorDownlink = '.1.3.6.1.4.1.161.19.3.1.12.2.29.0'; // WHISP-APS-MIB::frUtlMedMumimoDownlinkSectorUtilization
355
        $muDownlink = '.1.3.6.1.4.1.161.19.3.1.12.2.30.0'; // WHISP-APS-MIB::frUtlMedMumimoDownlinkMumimoUtilization
356
        $suDownlink = '.1.3.6.1.4.1.161.19.3.1.12.2.31.0'; // WHISP-APS-MIB::frUtlMedMumimoDownlinkSumimoUtilization
357
358
        return [
359
            new WirelessSensor(
360
                'utilization',
361
                $this->getDeviceId(),
362
                $lowdownlink,
363
                'pmp-downlink',
364
                0,
365
                '1m Downlink Utilization',
366
                null
367
            ),
368
            new WirelessSensor(
369
                'utilization',
370
                $this->getDeviceId(),
371
                $lowuplink,
372
                'pmp-uplink',
373
                0,
374
                '1m Uplink Utilization',
375
                null
376
            ),
377
            new WirelessSensor(
378
                'utilization',
379
                $this->getDeviceId(),
380
                $meddownlink,
381
                'pmp-downlink',
382
                1,
383
                '5m Downlink Utilization',
384
                null
385
            ),
386
            new WirelessSensor(
387
                'utilization',
388
                $this->getDeviceId(),
389
                $meduplink,
390
                'pmp-uplink',
391
                1,
392
                '5m Uplink Utilization',
393
                null
394
            ),
395
            new WirelessSensor(
396
                'utilization',
397
                $this->getDeviceId(),
398
                $highdownlink,
399
                'pmp-downlink',
400
                2,
401
                '15m Downlink Utilization',
402
                null
403
            ),
404
            new WirelessSensor(
405
                'utilization',
406
                $this->getDeviceId(),
407
                $highuplink,
408
                'pmp-uplink',
409
                2,
410
                '15m Uplink Utilization',
411
                null
412
            ),
413
            new WirelessSensor(
414
                'utilization',
415
                $this->getDeviceId(),
416
                $muSectorDownlink,
417
                'pmp-450m-sector-downlink',
418
                0,
419
                'MU-MIMO Downlink Sector utilization',
420
                null
421
            ),
422
            new WirelessSensor(
423
                'utilization',
424
                $this->getDeviceId(),
425
                $muDownlink,
426
                'pmp-450m-downlink',
427
                0,
428
                'MU-MIMO Downlink Utilization',
429
                null
430
            ),
431
            new WirelessSensor(
432
                'utilization',
433
                $this->getDeviceId(),
434
                $suDownlink,
435
                'pmp-450m-su-downlink',
436
                0,
437
                'SU-MIMO Downlink Utilization',
438
                null
439
            ),
440
        ];
441
    }
442
443
    /**
444
     * Discover wireless SSR.  This is in dB. Type is ssr.
445
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
446
     *
447
     * @return array Sensors
448
     */
449
    public function discoverWirelessSsr()
450
    {
451
        if ($this->isAp()) {
452
            $ssr = '.1.3.6.1.4.1.161.19.3.1.4.1.86.2'; //WHISP-APS-MIB::signalStrengthRatio.2
453
        } else {
454
            $ssr = '.1.3.6.1.4.1.161.19.3.2.2.108.0'; //WHISP-SMSSM-MIB::signalStrengthRatio.0
455
        }
456
457
        return [
458
            new WirelessSensor(
459
                'ssr',
460
                $this->getDeviceId(),
461
                $ssr,
462
                'pmp',
463
                0,
464
                'Cambium Signal Strength Ratio',
465
                null
466
            ),
467
        ];
468
    }
469
470
    /**
471
     * Private method to declare if device is an AP
472
     *
473
     * @return bool
474
     */
475
    private function isAp()
476
    {
477
        $device = $this->getDeviceArray();
478
479
        return Str::contains($device['hardware'], 'AP') || Str::contains($device['hardware'], 'Master');
480
    }
481
482
    /**
483
     * PMP Frequency divisor is different per model
484
     * using the following for production:
485
     * FSK 5.2, 5.4, 5.7 GHz: OID returns MHz
486
     * FSK 900 MHz, 2.4 GHz: OID returns 100's of KHz
487
     * OFDM: OID returns 10's of KHz"
488
     */
489
    private function freqDivisor()
490
    {
491
        $device = $this->getDeviceArray();
492
493
        $types = [
494
            'OFDM' => 1000,
495
            '5.4GHz' => 1,
496
            '5.2Ghz' => 1,
497
            '5.7Ghz' => 1,
498
            '2.4Ghz' => 10,
499
            '900Mhz' => 10,
500
        ];
501
502
        $boxType = snmp_get($device, 'boxDeviceType.0', '-Oqv', 'WHISP-BOX-MIBV2-MIB');
503
504
        foreach ($types as $key => $value) {
505
            if (Str::contains($boxType, $key)) {
0 ignored issues
show
It seems like $boxType can also be of type false; however, parameter $haystack of Illuminate\Support\Str::contains() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

505
            if (Str::contains(/** @scrutinizer ignore-type */ $boxType, $key)) {
Loading history...
506
                return $value;
507
            }
508
        }
509
510
        return 1;
511
    }
512
513
    /**
514
     * Discover wireless client counts. Type is clients.
515
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
516
     *
517
     * @return array Sensors
518
     */
519
    public function discoverWirelessClients()
520
    {
521
        $registeredSM = '.1.3.6.1.4.1.161.19.3.1.7.1.0'; //WHISP-APS-MIB::regCount.0
522
523
        return [
524
            new WirelessSensor(
525
                'clients',
526
                $this->getDeviceId(),
527
                $registeredSM,
528
                'pmp',
529
                0,
530
                'Client Count',
531
                null
532
            ),
533
        ];
534
    }
535
536
    /**
537
     * Discover wireless bit errors.  This is in total bits. Type is errors.
538
     * Returns an array of LibreNMS\Device\Sensor objects that have been discovered
539
     *
540
     * @return array Sensors
541
     */
542
    public function discoverWirelessErrors()
543
    {
544
        $fecInErrorsCount = '.1.3.6.1.4.1.161.19.3.3.1.95.0';
545
        $fecOutErrorsCount = '.1.3.6.1.4.1.161.19.3.3.1.97.0';
546
        $fecCRCError = '.1.3.6.1.4.1.161.19.3.3.1.223.0';
547
548
        return [
549
            new WirelessSensor(
550
                'errors',
551
                $this->getDeviceId(),
552
                $fecCRCError,
553
                'pmp-fecCRCError',
554
                0,
555
                'CRC Errors',
556
                null
557
            ),
558
            new WirelessSensor(
559
                'errors',
560
                $this->getDeviceId(),
561
                $fecOutErrorsCount,
562
                'pmp-fecOutErrorsCount',
563
                0,
564
                'Out Error Count',
565
                null
566
            ),
567
            new WirelessSensor(
568
                'errors',
569
                $this->getDeviceId(),
570
                $fecInErrorsCount,
571
                'pmp-fecInErrorsCount',
572
                0,
573
                'In Error Count',
574
                null
575
            ),
576
        ];
577
    }
578
}
579