Project

General

Profile

Feature #14653 ยป lcdproc_client.php

Elvis Impersonator, 08/05/2023 03:01 PM

 
1
<?php
2
/*
3
 * lcdproc_client.php
4
 *
5
 * part of pfSense (https://www.pfsense.org/)
6
 * Copyright (c) 2016-2023 Rubicon Communications, LLC (Netgate)
7
 * Copyright (c) 2016 Treer
8
 * Copyright (c) 2011 Michele Di Maria
9
 * Copyright (c) 2007-2009 Seth Mos <seth.mos@dds.nl>
10
 * All rights reserved.
11
 *
12
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15
 *
16
 * http://www.apache.org/licenses/LICENSE-2.0
17
 *
18
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23
 */
24
require_once("config.inc");
25
require_once("functions.inc");
26
require_once("interfaces.inc");
27
require_once("pfsense-utils.inc");
28
require_once("pkg-utils.inc");
29
require_once("ipsec.inc");
30
require_once("includes/functions.inc.php");
31
require_once("/usr/local/pkg/lcdproc.inc");
32
require_once("system.inc");
33

    
34
/* Calculates non-idle CPU time and returns as a percentage */
35
function lcdproc_cpu_usage() {
36
	$duration = 250000;
37
	$diff = array('user', 'nice', 'sys', 'intr', 'idle');
38
	$cpuTicks = array_combine($diff, explode(" ", get_single_sysctl("kern.cp_time")));
39
	usleep($duration);
40
	$cpuTicks2 = array_combine($diff, explode(" ", get_single_sysctl("kern.cp_time")));
41

    
42
	$totalStart = array_sum($cpuTicks);
43
	$totalEnd = array_sum($cpuTicks2);
44

    
45
	// Something wrapped ?!?!
46
	if ($totalEnd <= $totalStart) {
47
		return 0;
48
	}
49

    
50
	// Calculate total cycles used
51
	$totalUsed = ($totalEnd - $totalStart) - ($cpuTicks2['idle'] - $cpuTicks['idle']);
52

    
53
	// Calculate the percentage used
54
	$cpuUsage = floor(100 * ($totalUsed / ($totalEnd - $totalStart)));
55

    
56
	return $cpuUsage;
57
}
58

    
59
function get_uptime_stats() {
60
	exec("/usr/bin/uptime", $output, $ret);
61
	$temp = explode(",", $output[0]);
62
	if (stristr($output[0], "day")) {
63
		$status = "$temp[0] $temp[1]";
64
	} else {
65
		$status = "$temp[0] ";
66
	}
67
	$status = trim(str_replace("  ", " ", $status));
68
	$status = substr($status, strpos($status, "up ") + 3);
69

    
70
	return($status);
71
}
72

    
73
function get_loadavg_stats() {
74
	exec("/usr/bin/uptime", $output, $ret);
75

    
76
	$temp = preg_split("/ /", $output[0], -1, PREG_SPLIT_NO_EMPTY);
77
	$count = count($temp);
78
	return ($count >= 3) ? "{$temp[$count - 3]} {$temp[$count - 2]} {$temp[$count - 1]}" : "Not available";
79
}
80

    
81
function lcdproc_get_mbuf_stats() {
82
	$mbuf = "";
83
	$mbufpercent = "";
84
	get_mbuf($mbuf, $mbufpercent);
85
	return($mbuf);
86
}
87

    
88
function lcdproc_get_package_summary() {
89
	$total = 0;
90
	$needsupdating = 0;
91
	$broken = 0;
92

    
93
	$package_list = get_pkg_info('all', true, true);
94
	$installed_packages = array_filter($package_list, function($v) {
95
		return (isset($v['installed']) || isset($v['broken']));
96
	});
97
	if (!empty($installed_packages) || is_array($installed_packages)) {
98
		$total = count($installed_packages);
99
	}
100

    
101
	foreach ($installed_packages as $pkg) {
102
		if (isset($pkg['broken'])) {
103
			$broken += 1;
104
		} else if (isset($pkg['installed_version']) && isset($pkg['version'])) {
105
			$version_compare = pkg_version_compare(
106
			    $pkg['installed_version'], $pkg['version']);
107
			if ($version_compare == '<') {
108
				// we're running an older version of the package
109
				$needsupdating += 1;
110
			}
111
		}
112
	}
113
	if ($total > 0) {
114
		$result = "T: {$total}";
115
		if ($needsupdating > 0) {
116
			$result .= " NU: {$needsupdating}";
117
		}
118
		if ($broken > 0) {
119
			$result .= " B!: {$broken}";
120
		}
121
	} else {
122
		$result = "None Installed";
123
	}
124
	return $result;
125
}
126

    
127
// Returns CPU temperature if available from the system
128
function lcdproc_get_cpu_temperature() {
129
	global $config;
130
	$unit = config_get_path('installedpackages/lcdprocscreens/config/0/scr_cputemperature_unit', []);
131

    
132
	$temp_out = "";
133
	$temp_out = get_temp(); // Use function from includes/functions.inc.php
134
	if ($temp_out !== "") {
135
		switch ($unit) {
136
			case "f":
137
				$cputemperature = ($temp_out * 1.8) + 32;
138
				return $cputemperature . "F";
139
				break;
140
			case "c":
141
			default:
142
				return $temp_out . "C";
143
				break;
144
		}
145
	} else {
146
		// sysctl probably returned "unknown oid"
147
		return 'CPU Temp N/A';
148
	}
149
}
150

    
151
// NTP Status
152
function lcdproc_get_ntp_status() { // https://github.com/pfsense/pfsense/blob/master/src/usr/local/www/widgets/widgets/ntp_status.widget.php#L36
153
	global $config;
154
	if (config_path_enabled('ntpd')) {
155
		if (config_path_enabled('system', 'ipv6allow')) {
156
			$inet_version = "";
157
		} else {
158
			$inet_version = " -4";
159
		}
160
		exec('/usr/local/sbin/ntpq -pnw ' . $inet_version . ' | /usr/bin/tail +3 | /usr/bin/awk -v RS= \'{gsub(/\n[[:space:]][[:space:]]+/," ")}1\'', $ntpq_output);
161
		return $ntpq_output;
162
	} else {
163
		return false;
164
	}
165
}
166

    
167
function lcdproc_get_ntp_gps_sat_count() {
168
	global $config;
169
	if (config_path_enabled('ntpd/gps', 'extstatus')) {
170
		$lookfor = [];
171
		$lookfor['GPGSV'] = config_get_path('ntpd/gps/nmeaset/gpgsv');
172
		$lookfor['GPGGA'] = !isset($gps_sat) && config_path_enabled('ntpd/gps/nmeaset', 'gpgga');
173
		$gpsport = fopen('/dev/gps0', 'r+');
174
		while ($gpsport && ($lookfor['GPGSV'] || $lookfor['GPGGA'])) {
175
			$buffer = fgets($gpsport);
176
			if ($lookfor['GPGSV'] && substr($buffer, 0, 6) == '$GPGSV') {
177
				$gpgsv = explode(',', $buffer);
178
				$gps_satview = (int)$gpgsv[3];
179
				return ("SatIV: " . $gps_satview);
180
			} elseif ($lookfor['GPGGA'] && substr($buffer, 0, 6) == '$GPGGA') {
181
				$gpgga = explode(',', $buffer);
182
				$gps_sat = (int)$gpgga[7];
183
				return ("SatIU: " . $gps_sat);
184
			}
185
		}
186
		if ($gpsport) {
187
			fclose($gpsport);
188
		}
189
	} else {
190
		return false;
191
	}
192

    
193
}
194

    
195
function get_version() {
196
	$version = @file_get_contents("/etc/version");
197
	$version = trim($version);
198
	return(g_get('product_name') . " " . $version);
199
}
200

    
201
// Returns the max frequency in Mhz, or false if powerd is not supported.
202
// powerd is not supported on all systems - "no cpufreq(4) support" https://redmine.pfsense.org/issues/5739
203
function get_cpu_maxfrequency() {
204
	$cpufreqs = get_single_sysctl("dev.cpu.0.freq_levels");
205

    
206
	if (!empty($cpufreqs)) {
207
		$cpufreqs = explode(" ", trim($cpufreqs));
208
		$maxfreqs = explode("/", array_shift($cpufreqs));
209
		return array_shift($maxfreqs);
210
	} else {
211
		// sysctrl probably returned "unknown oid 'dev.cpu.0.freq_levels'",
212
		// see https://redmine.pfsense.org/issues/5739
213
		return false;
214
	}
215
}
216

    
217
// Returns the current frequency in Mhz, or false if powerd is not supported.
218
// powerd is not supported on all systems - "no cpufreq(4) support" https://redmine.pfsense.org/issues/5739
219
function get_cpu_currentfrequency() {
220
	$curfreq = get_single_sysctl("dev.cpu.0.freq");
221

    
222
	if (!empty($curfreq)) {
223
		return trim($curfreq);
224
	} else {
225
		// sysctrl probably returned "unknown oid 'dev.cpu.0.freq'",
226
		// see https://redmine.pfsense.org/issues/5739
227
		return false;
228
	}
229
}
230

    
231
function get_cpufrequency() {
232
	$maxfreq = get_cpu_maxfrequency();
233
	if ($maxfreq === false) {
234
		return "no cpufreq(4) support";
235
	} else {
236
		$curfreq = get_cpu_currentfrequency();
237
		return "{$curfreq}\/{$maxfreq} Mhz";
238
	}
239
}
240

    
241
function get_interfaces_stats() {
242
	$ifstatus = [];
243
	$ifdescrs = get_configured_interface_with_descr();
244

    
245
	foreach ($ifdescrs as $ifdescr => $ifname) {
246
		$ifinfo = get_interface_info($ifdescr);
247
		if ($ifinfo['status'] == "up") {
248
			$online = "Up";
249
		} else {
250
			$online = "Down";
251
		}
252
		if (!empty($ifinfo['ipaddr'])) {
253
			$ip = htmlspecialchars($ifinfo['ipaddr']);
254
		} else {
255
			$ip = "-";
256
		}
257
		$ifstatus[] = htmlspecialchars($ifname) ." [$online]";
258
	}
259
	$status = " ". implode(", ", $ifstatus);
260
	return($status);
261
}
262

    
263
function get_carp_stats() {
264
	if (get_carp_status()) {
265
		$initcount = 0;
266
		$mastercount = 0;
267
		$backupcount = 0;
268
		foreach (config_get_path('virtualip/vip', []) as $carp) {
269
			if (!is_array($carp) ||
270
			    empty($carp) ||
271
			    $carp['mode'] != "carp") {
272
				continue;
273
			}
274
			$ipaddress = $carp['subnet'];
275
			$password = $carp['password'];
276
			$netmask = $carp['subnet_bits'];
277
			$vhid = $carp['vhid'];
278
			$advskew = $carp['advskew'];
279
			$status = get_carp_interface_status("_vip{$carp['uniqid']}");
280
			switch ($status) {
281
				case "MASTER":
282
					$mastercount++;
283
					break;
284
				case "BACKUP":
285
					$backupcount++;
286
					break;
287
				case "INIT":
288
					$initcount++;
289
					break;
290
			}
291
		}
292
		$status = "";
293
		if (config_path_enabled('/','virtualip_carp_maintenancemode')) {
294
			$status .= "CARP is in Maintenance Mode. ";
295
		}
296
		$status .= "M/B/I {$mastercount}/{$backupcount}/{$initcount}";
297
	} else {
298
		$status = "CARP Disabled";
299
	}
300
	return($status);
301
}
302

    
303
function get_ipsec_tunnel_src($tunnel) {
304
	global $sad;
305
	$if = "WAN";
306
	if ($tunnel['interface']) {
307
		$if = $tunnel['interface'];
308
		$realinterface = convert_friendly_interface_to_real_interface_name($if);
309
		$interfaceip = find_interface_ip($realinterface);
310
	}
311
	return $interfaceip;
312
}
313

    
314
function output_ipsec_tunnel_status($tunnel) {
315
	global $sad;
316
	$if = "WAN";
317
	$interfaceip = get_ipsec_tunnel_src($tunnel);
318
	$foundsrc = false;
319
	$founddst = false;
320

    
321
	if (!is_array($sad)) {
322
		/* we have no sad array, bail */
323
		return(false);
324
	}
325
	foreach ($sad as $sa) {
326
		if ($sa['src'] == $interfaceip) {
327
			$foundsrc = true;
328
		}
329
		if ($sa['dst'] == $tunnel['remote-gateway']) {
330
			$founddst = true;
331
		}
332
	}
333
	if ($foundsrc && $founddst) {
334
		/* tunnel is up */
335
		$iconfn = "pass";
336
		return(true);
337
	} else {
338
		/* tunnel is down */
339
		$iconfn = "reject";
340
		return(false);
341
	}
342
}
343

    
344
function get_ipsec_stats() {
345
	global $sad;
346
	$sad = array();
347
	$sad = ipsec_dump_sad();
348

    
349
	$activecounter = 0;
350
	$inactivecounter = 0;
351

    
352
	foreach (config_get_path('ipsec/phase1', []) as $tunnel) {
353
		if (!is_array($tunnel) || empty($tunnel)) {
354
			continue;
355
		}
356

    
357
		$tun_disabled = "false";
358
		$foundsrc = false;
359
		$founddst = false;
360

    
361
		if (isset($tunnel['disabled'])) {
362
			$tun_disabled = "true";
363
			continue;
364
		}
365

    
366
		if (output_ipsec_tunnel_status($tunnel)) {
367
			/* tunnel is up */
368
			$iconfn = "true";
369
			$activecounter++;
370
		} else {
371
			/* tunnel is down */
372
			$iconfn = "false";
373
			$inactivecounter++;
374
		}
375
	}
376

    
377
	if (ipsec_enabled()) {
378
		$status = "Up/Down {$activecounter}/{$inactivecounter}";
379
	} else {
380
		$status = "IPsec Disabled";
381
	}
382
	return($status);
383
}
384

    
385
function send_lcd_commands($lcd, $lcd_cmds) {
386
	if (!is_array($lcd_cmds) || (empty($lcd_cmds))) {
387
		lcdproc_warn("Failed to interpret lcd commands");
388
		return;
389
	}
390
	get_lcd_messages($lcd);
391
	foreach ($lcd_cmds as $lcd_cmd) {
392
		if (! fwrite($lcd, "$lcd_cmd\n")) {
393
			lcdproc_warn("Connection to LCDd process lost {$errstr} ({$errno})");
394
			$lcdproc_connect_errors++;
395
			return false;
396
		}
397
	}
398
	return true;
399
}
400

    
401
function get_lcd_messages($lcd) {
402
	while (($cmd_output = fgets($lcd, 8000)) !== false) {
403
		if (preg_match("/^huh?/", $cmd_output)) {
404
			lcdproc_notice("LCDd output: \"{$cmd_output}\". Executed \"{$lcd_cmd}\"");
405
		}
406
		if (cmenu_enabled()) {
407
			if (preg_match("/^menuevent select cm_ask_enter/", $cmd_output)) {
408
				lcdproc_notice("Entering CARP Maintenance Mode");
409
				interfaces_carp_set_maintenancemode(true);
410
			}
411
			if (preg_match("/^menuevent select p_ask_yes/", $cmd_output)) {
412
				lcdproc_notice("Restarting PHP and GUI!");
413
				exec("/etc/rc.php-fpm_restart");
414
				exec("/etc/rc.restart_webgui");
415
			}
416
			if (preg_match("/^menuevent select cm_ask_leave/", $cmd_output)) {
417
				lcdproc_notice("Leaving CARP Maintenance Mode");
418
				interfaces_carp_set_maintenancemode(false);
419
			}
420
			if (preg_match("/^menuevent select r_ask_yes/", $cmd_output)) {
421
				lcdproc_notice("init REBOOT!");
422
				system_reboot();
423
			}
424
			if (preg_match("/^menuevent select s_ask_yes/", $cmd_output)) {
425
				lcdproc_notice("init SHUTDOWN!");
426
				system_halt();
427
			}
428
		}
429
	}
430
}
431

    
432
function get_lcdpanel_width() {
433
	$lcdproc_size = config_get_path('installedpackages/lcdproc/config/0/size');
434
	if (is_null($lcdproc_size)) {
435
		return "16";
436
	} else {
437
		$dimensions = explode("x", $lcdproc_size);
438
		return $dimensions[0];
439
	}
440
}
441

    
442
function get_lcdpanel_height() {
443
	$lcdproc_size = config_get_path('installedpackages/lcdproc/config/0/size');
444
	if (is_null($lcdproc_size)) {
445
		return "2";
446
	} else {
447
		$dimensions = explode("x", $lcdproc_size);
448
		return $dimensions[1];
449
	}
450
}
451

    
452
function get_lcdpanel_refresh_frequency() {
453
	return config_get_path('installedpackages/lcdproc/config/0/refresh_frequency', 5);
454
}
455

    
456
function outputled_enabled_CFontzPacket() {
457
	$driver = config_get_path('installedpackages/lcdproc/config/0/driver');
458
	$outputleds = config_get_path('installedpackages/lcdproc/config/0/outputleds');
459
	if (is_null($outputleds)) {
460
		return false;
461
	} else {
462
		if ($outputleds && ($driver == "CFontzPacket")) {
463
			return true;
464
		} else {
465
			return false;
466
		}
467
	}
468
}
469

    
470
function cmenu_enabled() {
471
	return config_path_enabled('installedpackages/lcdproc/config/0', 'controlmenu');
472
}
473

    
474
function outputled_carp() {
475
	/* Returns the status of CARP for the box.
476
	Assumes ALL CARP status are the same for all the interfaces.
477
		-1 = CARP Disabled
478
		0  = CARP on Backup
479
		1  = CARP on Master */
480

    
481
	if (get_carp_status()) {
482
		foreach (config_get_path('virtualip/vip', []) as $carp) {
483
			if (!is_array($carp) ||
484
			    empty($carp) ||
485
			    $carp['mode'] != "carp") {
486
				continue;
487
			}
488
			$status = get_carp_interface_status("_vip{$carp['uniqid']}");
489
			switch($status) {
490
				case "MASTER":
491
					return 1;
492
					break;
493
				case "BACKUP":
494
				default:
495
					return 0;
496
					break;
497
			}
498
		}
499
	} else {
500
		return -1;
501
	}
502
}
503

    
504
function outputled_gateway() {
505
	/* Returns the status of the gateways.
506
		-1 = No gateway defined
507
		0  = At least 1 gateway down or with issues
508
		1  = All gateway up */
509
	$gateways_status = return_gateways_status(true);
510
	if (empty($gateways_status)) {
511
		return -1;
512
	}
513
	foreach ($gateways_status as $gw) {
514
		if ($gw['status'] != 'online') {
515
			return 0;
516
		}
517
	}
518
	return 1;
519
}
520

    
521
function build_interface_link_list() {
522
	// Returns a dictionary of all the interfaces along with their
523
	// link and address information, keyed on the interface description.
524
	$result = array();
525
	$ifList = get_configured_interface_with_descr();
526

    
527
	foreach($ifList as $ifdescr => $ifname) {
528
		// get the interface link infos
529
		$ifinfo = get_interface_info($ifdescr);
530

    
531
		$entry = array();
532
		$entry['name'] = $ifname;
533
		$entry['mac'] = $ifinfo['macaddr'];
534

    
535
		if (($ifinfo['status'] == "up") ||
536
		    ($ifinfo['status'] == "associated")) {
537
			$entry['status'] = "up";
538
		} else {
539
			$entry['status'] = "down";
540
		}
541

    
542
		if (($ifinfo['pppoelink'] == "up") ||
543
		    ($ifinfo['pptplink']  == "up") ||
544
		    ($ifinfo['l2tplink']  == "up")) {
545
			$entry['link'] = sprintf(gettext("Uptime %s"), $ifinfo['ppp_uptime']);
546
		} else {
547
			$entry['link'] = $ifinfo['media'];
548
		}
549

    
550
		$entry['v4addr'] = (empty($ifinfo['ipaddr'])) ?
551
			"n/a" : $ifinfo['ipaddr'];
552

    
553
		$entry['v6addr'] = (empty($ifinfo['ipaddrv6'])) ?
554
			"n/a" : $ifinfo['ipaddrv6'];
555

    
556
		$result[$ifdescr] = $entry;
557
	}
558
	return $result;
559
}
560

    
561
function build_interface_traffic_stats_list() {
562
	// Returns a dictionary of all the interfaces along with their in/out
563
	// traffic stats, keyed on the interface name.
564
	global $config;
565

    
566
	$result = array();
567
	$interfaceList = get_configured_interface_with_descr();
568

    
569
	foreach($interfaceList as $key => $description) {
570
		// get the interface stats (code from ifstats.php)
571
		$interface      = $config['interfaces'][$key];
572
		$interfaceName  = $interface['if'];
573
		$interfaceStats = pfSense_get_interface_stats($interfaceName);
574

    
575
		calculate_interfaceBytesPerSecond_sinceLastChecked($interfaceName, $interfaceStats, $in_Bps, $out_Bps);
576
		calculate_bytesToday($interfaceName, $interfaceStats, $in_bytesToday, $out_bytesToday);
577

    
578
		$entry = array();
579
		$entry['descr']       = $description;
580

    
581
		$entry['in_Bps']      = $in_Bps;
582
		$entry['out_Bps']     = $out_Bps;
583
		$entry['total_Bps']   = $in_Bps + $out_Bps;
584

    
585
		$entry['in_bytes']    = $interfaceStats['inbytes'];
586
		$entry['out_bytes']   = $interfaceStats['outbytes'];
587
		$entry['total_bytes'] = $interfaceStats['inbytes'] + $interfaceStats['outbytes'];
588

    
589
		$entry['in_bytes_today']    = $in_bytesToday;
590
		$entry['out_bytes_today']   = $out_bytesToday;
591
		$entry['total_bytes_today'] = $in_bytesToday + $out_bytesToday;
592

    
593
		$result[$interface['if']] = $entry;
594
	}
595
	return $result;
596
}
597

    
598
function sort_interface_list_by_bytes_today(&$interfaceTrafficStatsList) {
599
	uasort($interfaceTrafficStatsList, "cmp_total_bytes_today");
600
}
601

    
602
function sort_interface_list_by_total_bytes(&$interfaceTrafficStatsList) {
603
	uasort($interfaceTrafficStatsList, "cmp_total_bytes");
604
}
605

    
606
function sort_interface_list_by_bps(&$interfaceTrafficStatsList) {
607
	uasort($interfaceTrafficStatsList, "cmp_total_Bps");
608
}
609

    
610
function cmp_total_Bps($a, $b) {
611
	if ($a['total_Bps'] == $b['total_Bps']) return 0;
612
	return ($a['total_Bps'] < $b['total_Bps']) ? 1 : -1;
613
}
614

    
615
function cmp_total_bytes($a, $b) {
616
	if ($a['total_bytes'] == $b['total_bytes']) return 0;
617
	return ($a['total_bytes'] < $b['total_bytes']) ? 1 : -1;
618
}
619

    
620
function cmp_total_bytes_today($a, $b) {
621
	if ($a['total_bytes_today'] == $b['total_bytes_today']) return 0;
622
	return ($a['total_bytes_today'] < $b['total_bytes_today']) ? 1 : -1;
623
}
624

    
625
function calculate_interfaceBytesPerSecond_sinceLastChecked($interfaceName, $interfaceStats, &$in_Bps, &$out_Bps) {
626
	// calculates the average bytes-per-second (in & out) for the interface
627
	// during the interval between now and the last time this method was invoked for
628
	// the interface. So avoid invoking this method needlessly, or you'll end up
629
	// measuring meaningless periods.
630

    
631
	global $traffic_last_ugmt, $traffic_last_ifin, $traffic_last_ifout;
632

    
633
	// get the current time (code from ifstats.php)
634
	$temp = gettimeofday();
635
	$timing = (double)$temp["sec"] + (double)$temp["usec"] / 1000000.0;
636

    
637
	// calculate the traffic stats
638
	$deltatime = $timing - $traffic_last_ugmt[$interfaceName];
639
	$in_Bps  = ((double)$interfaceStats['inbytes']  - $traffic_last_ifin[$interfaceName])  / $deltatime;
640
	$out_Bps = ((double)$interfaceStats['outbytes'] - $traffic_last_ifout[$interfaceName]) / $deltatime;
641

    
642
	$traffic_last_ugmt[$interfaceName]  = $timing;
643
	$traffic_last_ifin[$interfaceName]  = (double)$interfaceStats['inbytes'];
644
	$traffic_last_ifout[$interfaceName] = (double)$interfaceStats['outbytes'];
645
}
646

    
647
function calculate_bytesToday($interfaceName, $interfaceStats, &$in_bytesToday, &$out_bytesToday) {
648
	global $traffic_last_hour, $traffic_startOfDay_ifin, $traffic_startOfDay_ifout;
649

    
650
	$hourOfDay = getdate()['hours'];
651

    
652
	if (!isset($traffic_last_hour[$interfaceName]) || ($hourOfDay < $traffic_last_hour[$interfaceName])) {
653
		$traffic_startOfDay_ifin[$interfaceName]  = (double)$interfaceStats['inbytes'];
654
		$traffic_startOfDay_ifout[$interfaceName] = (double)$interfaceStats['outbytes'];
655
	}
656
	$traffic_last_hour[$interfaceName] = $hourOfDay;
657

    
658
	$in_bytesToday  = ((double)$interfaceStats['inbytes']  - $traffic_startOfDay_ifin[$interfaceName]);
659
	$out_bytesToday = ((double)$interfaceStats['outbytes'] - $traffic_startOfDay_ifout[$interfaceName]);
660
}
661

    
662
function format_interface_string($interfaceEntry, $in_key, $out_key, $output_in_bits, $outputLength) {
663
	if ($output_in_bits) {
664
		$speed = " " . format_toSpeedInBits_shortForm($interfaceEntry[$in_key]) . "/" . format_toSpeedInBits_shortForm($interfaceEntry[$out_key]);
665
	} else {
666
		$speed = " " . format_toSizeInBytes_shortForm($interfaceEntry[$in_key]) . "/" . format_toSizeInBytes_shortForm($interfaceEntry[$out_key]);
667
	}
668

    
669
	$nameLength = $outputLength - strlen($speed);
670

    
671
	if ($nameLength < 0) {
672
		// owch - speed doesn't even fit on the lcd
673
		$speed = substr(trim($speed), 0, $outputLength);
674
		$name = '';
675
	} else {
676
		$name = substr($interfaceEntry['descr'], 0, $nameLength);
677
		$name = str_pad($name, $nameLength);
678
	}
679

    
680
	return $name . $speed;
681
}
682

    
683
function format_toSizeInBytes_shortForm($size_in_bytes) {
684
	// format a byte count into a string with two significant figures or more and a unit
685
	//
686
	// Data sizes are normally specified in KB - powers of 1024, so return KB rather than kB
687

    
688
	if ($size_in_bytes < (1024 * 1024)) {
689
		$unit = "K";
690
		$unitSize = $size_in_bytes / 1024;
691
	} else if ($size_in_bytes < (1024 * 1024 * 1024)) {
692
		$unit = "M";
693
		$unitSize = $size_in_bytes / (1024 * 1024);
694
	} else {
695
		$unit = "G";
696
		$unitSize = $size_in_bytes / (1024 * 1024 * 1024);
697
	}
698

    
699
	$showDecimalPlace = $unitSize < 10 && round($unitSize, 1) != round($unitSize);
700

    
701
	return sprintf($showDecimalPlace ? "%1.1f" : "%1.0f", $unitSize) . $unit;
702
}
703

    
704
function format_toSpeedInBits_shortForm($speed_in_bytes) {
705
	// format a byte-count into a bit-count string with two significant figures or more, and a unit.
706
	//
707
	// The decimal SI kilobot definition of 1 kbit/s = 1000 bit/s, is used uniformly in the
708
	// context of telecommunication transmission, so return kb rather than Kb
709

    
710
	if ($speed_in_bytes < 125000) {
711
		$unit = "k";
712
		$unitSpeed = $speed_in_bytes / 125;
713
	} else if ($speed_in_bytes < 125000000) {
714
		$unit = "m";
715
		$unitSpeed = $speed_in_bytes / 125000;
716
	} else {
717
		$unit = "g";
718
		$unitSpeed = $speed_in_bytes / 125000000;
719
	}
720

    
721
	$showDecimalPlace = $unitSpeed < 10 && round($unitSpeed, 1) != round($unitSpeed);
722

    
723
	return sprintf($showDecimalPlace ? "%1.1f" : "%1.0f", $unitSpeed) . $unit;
724
}
725

    
726
function format_toSpeedInBits_longForm($speed_in_bytes) {
727
	/* format speed in bits/sec, input: bytes/sec
728
	Code from: graph.php ported to PHP
729

    
730
	The decimal SI kilobot definition of 1 kbit/s = 1000 bit/s, is used uniformly in the
731
	context of telecommunication transmission, so return kb rather than Kb */
732

    
733
	if ($speed_in_bytes < 125000) {
734
		return sprintf("%5.1f kbps", $speed_in_bytes / 125);
735
	}
736
	if ($speed_in_bytes < 125000000) {
737
		return sprintf("%5.1f mbps", $speed_in_bytes / 125000);
738
	}
739

    
740
	return sprintf("%5.1f gbps", $speed_in_bytes / 125000000);
741
}
742

    
743
function get_traffic_stats($interface_traffic_list, &$in_data, &$out_data){
744
	$ifnum = config_get_path('installedpackages/lcdprocscreens/config/0/scr_traffic_interface');
745
	/* get the real interface name (code from ifstats.php)*/
746
	$realif = get_real_interface($ifnum);
747
	if (!$realif) {
748
		$realif = $ifnum; // Need for IPsec case interface.
749
	}
750

    
751
	$interfaceEntry = $interface_traffic_list[$realif];
752

    
753
	$in_data  = "IN:  " . format_toSpeedInBits_longForm($interfaceEntry['in_Bps']);
754
	$out_data = "OUT: " . format_toSpeedInBits_longForm($interfaceEntry['out_Bps']);
755
}
756

    
757
function get_top_interfaces_by_bps($interfaceTrafficList, $lcdpanel_width, $lcdpanel_height) {
758
	$result = [];
759

    
760
	if (count($interfaceTrafficList) < $lcdpanel_height) {
761
		// All the interfaces will fit on the screen, so use the same sort order as
762
		// the bytes_today screen, so that the interfaces stay in one place (much easier to read)
763
		sort_interface_list_by_total_bytes($interfaceTrafficList);
764
	} else {
765
		// We can't show all the interfaces, so show the ones with the most traffic
766
		sort_interface_list_by_bps($interfaceTrafficList);
767
	}
768

    
769
	foreach($interfaceTrafficList as $interfaceEntry) {
770
		$result[] = format_interface_string($interfaceEntry, 'in_Bps', 'out_Bps', true, $lcdpanel_width);
771
	}
772
	return $result;
773
}
774

    
775
function get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width) {
776
	$result = [];
777

    
778
	if (count($interfaceTrafficList) < $lcdpanel_height) {
779
		// All the interfaces will fit on the screen, so use the same sort order as
780
		// the bytes_today screen and the bps screen, so that the interfaces stay in
781
		// one place (much easier to read)
782
		sort_interface_list_by_total_bytes($interfaceTrafficList);
783
	} else {
784
		// We can't show all the interfaces, so show the ones with the most traffic	today
785
		sort_interface_list_by_bytes_today($interfaceTrafficList);
786
	}
787

    
788
	foreach($interfaceTrafficList as $interfaceEntry) {
789
		$result[] = format_interface_string($interfaceEntry, 'in_bytes_today', 'out_bytes_today', false, $lcdpanel_width);
790
	}
791
	return $result;
792
}
793

    
794
function get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width) {
795
	$result = [];
796

    
797
	sort_interface_list_by_total_bytes($interfaceTrafficList);
798

    
799
	foreach($interfaceTrafficList as $interfaceEntry) {
800
		$result[] = format_interface_string($interfaceEntry, 'in_bytes', 'out_bytes', false, $lcdpanel_width);
801
	}
802
	return $result;
803
}
804

    
805

    
806
function convert_bandwidth_to_shortform($bytes_string) {
807
	// Shorten values from bandwidth_by_ip.php, which have the form
808
	// "168.16k", "10.31k", "0.00".
809
	// The unit is preserved, but decimal point is dropped for 10 or
810
	// higher, and only 1 decimal place is kept for lower than 10.
811
	// So "168.16k", "10.31k", "0.00" becomes "168k", "10k", "0"
812

    
813
	if ($bytes_string == "0.00") {
814
		return "0";
815
	}
816

    
817
	$decimalPos = strpos($bytes_string, '.');
818
	if ($decimalPos == 1) {
819
		// allow 1 decimal place
820
		return substr($bytes_string, 0, 3) . substr($bytes_string, 4);
821
	} elseif ($decimalPos > 1) {
822
		// remove the decimal places
823
		return substr($bytes_string, 0, $decimalPos) . substr($bytes_string, $decimalPos + 3);
824
	} else {
825
		// Our format assumptions are wrong
826
		return $bytes_string;
827
	}
828
}
829

    
830
function get_bandwidth_by_ip() {
831
	$result       = [];
832

    
833
	/* Ideally this would use /usr/local/www/bandwidth_by_ip.php, but that requires a
834
	 * logged-in authenticated user session, so use a local copy instead that's outside
835
	 * the www directory and doesn't require an authenticated user session.
836
	 */
837

    
838
	/* Start with parameter name and '=' */
839
	$lan          = 'if=';
840
	$sort         = 'sort=';
841
	$filter       = 'filter=';
842
	$hostipformat = 'hostipformat=';
843

    
844
	/* Add config value */
845
	$lan          .= config_get_path('installedpackages/lcdprocscreens/config/0/scr_traffic_by_address_if');
846
	$sort         .= config_get_path('installedpackages/lcdprocscreens/config/0/scr_traffic_by_address_sort');
847
	$filter       .= config_get_path('installedpackages/lcdprocscreens/config/0/scr_traffic_by_address_filter');
848
	$hostipformat .= config_get_path('installedpackages/lcdprocscreens/config/0/scr_traffic_by_address_hostipformat');
849

    
850
	/* Escape before using in shell */
851
	$lan          = escapeshellarg($lan);
852
	$sort         = escapeshellarg($sort);
853
	$filter       = escapeshellarg($filter);
854
	$hostipformat = escapeshellarg($hostipformat);
855

    
856
	$output = shell_exec("/usr/local/bin/php-cgi -f /usr/local/pkg/lcdproc_bandwidth_by_ip.php {$lan} {$sort} {$filter} {$hostipformat}");
857

    
858
	$hostLines = explode("|", $output);
859
	foreach($hostLines as $hostLine) {
860
		$hostData = explode(";", $hostLine);
861
		if (count($hostData) == 3) {
862
			$host = array();
863
			$host['name']   = $hostData[0];
864
			$host['in']     = convert_bandwidth_to_shortform($hostData[1]);
865
			$host['out']    = convert_bandwidth_to_shortform($hostData[2]);
866
			$host['in/out'] = $host['in'] . '/' . $host['out'];
867
			$result[] = $host;
868
		}
869
	}
870
	if (count($result) === 0 && strlen($output) > 1) {
871
		$result['error'] = $output;
872
	}
873

    
874
	return $result;
875
}
876

    
877
function add_summary_declaration(&$lcd_cmds, $name) {
878
	$lcdpanel_height = get_lcdpanel_height();
879
	$lcdpanel_width = get_lcdpanel_width();
880
	if ($lcdpanel_height >= "4") {
881
		$lcd_cmds[] = "widget_add {$name} title_summary string";
882
		$lcd_cmds[] = "widget_add {$name} text_summary string";
883
		if ($lcdpanel_width > "16") {
884
			$lcd_cmds[] = "widget_set {$name} title_summary 1 3 \"CPU MEM STATES FREQ\"";
885
		} else {
886
			$lcd_cmds[] = "widget_set {$name} title_summary 1 3 \"CPU MEM STATES\"";
887
		}
888
	}
889
}
890

    
891
function add_summary_values(&$lcd_cmds, $name, $lcd_summary_data) {
892
	if ($lcd_summary_data != "") {
893
		$lcd_cmds[] = "widget_set {$name} text_summary 1 4 \"{$lcd_summary_data}\"";
894
	}
895
}
896

    
897
function build_interface($lcd) {
898
	$lcdproc_screens_config = config_get_path('installedpackages/lcdprocscreens/config/0', []);
899
	$lcdpanel_width  = get_lcdpanel_width();
900
	$lcdpanel_height = get_lcdpanel_height();
901
	$refresh_frequency = get_lcdpanel_refresh_frequency() * 8;
902

    
903
	$lcd_cmds = array();
904
	$lcd_cmds[] = "hello";
905
	$lcd_cmds[] = "client_set name pfSense";
906

    
907
	/* setup pfsense control menu */
908
	if (cmenu_enabled()) {
909
		$lcd_cmds[] = 'menu_add_item "" carpmaint_menu menu "CARP Maintenance"';
910
		$lcd_cmds[] = 'menu_add_item "carpmaint_menu" cm_ask_no action "Cancel" -next _close_';
911
		$lcd_cmds[] = 'menu_add_item "carpmaint_menu" cm_ask_enter action "Enter Maint. Mode" -next _quit_';
912
		$lcd_cmds[] = 'menu_add_item "carpmaint_menu" cm_ask_leave action "Leave Maint. Mode" -next _quit_';
913

    
914
		$lcd_cmds[] = 'menu_add_item "" restartphp_menu menu "Restart PHP+GUI"';
915
		$lcd_cmds[] = 'menu_add_item "restartphp_menu" p_ask_no action "No" -next _close_';
916
		$lcd_cmds[] = 'menu_add_item "restartphp_menu" p_ask_yes action "Yes" -next _quit_';
917

    
918
		$lcd_cmds[] = 'menu_add_item "" reboot_menu menu "Reboot"';
919
		$lcd_cmds[] = 'menu_add_item "reboot_menu" r_ask_no action "No" -next _close_';
920
		$lcd_cmds[] = 'menu_add_item "reboot_menu" r_ask_yes action "Yes" -next _quit_';
921

    
922
		$lcd_cmds[] = 'menu_add_item "" shutdown_menu menu "Shutdown"';
923
		$lcd_cmds[] = 'menu_add_item "shutdown_menu" s_ask_no action "No" -next _close_';
924
		$lcd_cmds[] = 'menu_add_item "shutdown_menu" s_ask_yes action "Yes" -next _quit_';
925
	}
926

    
927
	/* process screens to display */
928
	foreach ($lcdproc_screens_config as $name => $screen) {
929
		if ($screen == "on" || $screen == "yes" ) {
930
			$includeSummary = true;
931
			switch($name) {
932
				case "scr_version":
933
					$lcd_cmds[] = "screen_add {$name}";
934
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
935
					$lcd_cmds[] = "screen_set {$name} name {$name}";
936
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
937
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
938
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
939
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"Welcome to\"";
940
					break;
941
				case "scr_time":
942
					$lcd_cmds[] = "screen_add {$name}";
943
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
944
					$lcd_cmds[] = "screen_set {$name} name {$name}";
945
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
946
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
947
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
948
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"System Time\"";
949
					break;
950
				case "scr_uptime":
951
					$lcd_cmds[] = "screen_add {$name}";
952
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
953
					$lcd_cmds[] = "screen_set {$name} name {$name}";
954
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
955
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
956
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
957
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"System Uptime\"";
958
					break;
959
				case "scr_hostname":
960
					$lcd_cmds[] = "screen_add {$name}";
961
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
962
					$lcd_cmds[] = "screen_set {$name} name {$name}";
963
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
964
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
965
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
966
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"System Name\"";
967
					break;
968
				case "scr_system":
969
					$lcd_cmds[] = "screen_add {$name}";
970
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
971
					$lcd_cmds[] = "screen_set {$name} name {$name}";
972
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
973
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
974
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
975
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"System Stats\"";
976
					break;
977
				case "scr_disk":
978
					$lcd_cmds[] = "screen_add {$name}";
979
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
980
					$lcd_cmds[] = "screen_set {$name} name {$name}";
981
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
982
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
983
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
984
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"Disk Use\"";
985
					break;
986
				case "scr_load":
987
					$lcd_cmds[] = "screen_add {$name}";
988
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
989
					$lcd_cmds[] = "screen_set {$name} name {$name}";
990
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
991
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
992
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
993
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"Load Averages\"";
994
					break;
995
				case "scr_states":
996
					$lcd_cmds[] = "screen_add {$name}";
997
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
998
					$lcd_cmds[] = "screen_set {$name} name {$name}";
999
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1000
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1001
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1002
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"Traffic States\"";
1003
					break;
1004
				case "scr_carp":
1005
					$lcd_cmds[] = "screen_add {$name}";
1006
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1007
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1008
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1009
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1010
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1011
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"CARP State\"";
1012
					break;
1013
				case "scr_ipsec":
1014
					$lcd_cmds[] = "screen_add {$name}";
1015
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1016
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1017
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1018
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1019
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1020
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"IPsec Tunnels\"";
1021
					break;
1022
				case "scr_interfaces":
1023
					$lcd_cmds[] = "screen_add {$name}";
1024
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1025
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1026
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1027
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1028
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1029
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"Interfaces\"";
1030
					break;
1031
				case "scr_gwsum":
1032
					$lcd_cmds[] = "screen_add {$name}";
1033
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1034
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1035
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1036
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1037
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1038
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"GW Summary\"";
1039
					break;
1040
				case "scr_mbuf":
1041
					$lcd_cmds[] = "screen_add {$name}";
1042
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1043
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1044
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1045
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1046
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1047
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"MBuf Usage\"";
1048
					break;
1049
				case "scr_packages":
1050
					$lcd_cmds[] = "screen_add {$name}";
1051
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1052
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1053
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1054
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1055
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1056
					break;
1057
				case "scr_cpufrequency":
1058
					$lcd_cmds[] = "screen_add {$name}";
1059
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1060
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1061
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1062
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1063
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1064
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"CPU Frequency\"";
1065
					break;
1066
				case "scr_cputemperature":
1067
					$lcd_cmds[] = "screen_add {$name}";
1068
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1069
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1070
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1071
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1072
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1073
					break;
1074
				case "scr_ntp":
1075
					$lcd_cmds[] = "screen_add {$name}";
1076
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1077
					$lcd_cmds[] = "screen_set {$name} name $name";
1078
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1079
					$lcd_cmds[] = "widget_add {$name} time_st_wdgt scroller";
1080
					$lcd_cmds[] = "widget_add {$name} ref_wdgt scroller";
1081
					$lcd_cmds[] = "widget_add {$name} text_wdgt scroller";
1082
					$lcd_cmds[] = "widget_add {$name} stats_wdgt scroller";
1083
					$includeSummary = false; // this screen needs all the lines
1084
					break;
1085
				case "scr_traffic":
1086
					$lcd_cmds[] = "screen_add {$name}";
1087
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1088
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1089
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1090
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1091
					$lcd_cmds[] = "widget_add {$name} text_wdgt string";
1092
					break;
1093
				case "scr_top_interfaces_by_bps":
1094
				case "scr_top_interfaces_by_total_bytes":
1095
				case "scr_top_interfaces_by_bytes_today":
1096
					$lcd_cmds[] = "screen_add {$name}";
1097
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1098
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1099
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1100
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1101

    
1102
					for($i = 0; $i < ($lcdpanel_height - 1); $i++) {
1103
						$lcd_cmds[] = "widget_add {$name} text_wdgt{$i} string";
1104
					}
1105
					$includeSummary = false; // this screen needs all the lines
1106
					break;
1107
				case "scr_gwstatus":
1108
					$gateway_status = return_gateways_status(true);
1109
					foreach ($gateway_status as $gwname => $gw) {
1110
						if ($gw['disabled'] ||
1111
						    $gw['monitor_disable']) {
1112
							/* Disabled, no need to print anything */
1113
							continue;
1114
						}
1115
						$s_name = $name . $gwname;
1116
						$lcd_cmds[] = "screen_add {$s_name}";
1117
						$lcd_cmds[] = "screen_set {$s_name} heartbeat off";
1118
						$lcd_cmds[] = "screen_set {$s_name} name \"{$name}.{$gwname}\"";
1119
						$lcd_cmds[] = "screen_set {$s_name} duration {$refresh_frequency}";
1120
						$lcd_cmds[] = "widget_add {$s_name} gwname_wdgt string";
1121
						$lcd_cmds[] = "widget_set {$s_name} gwname_wdgt 1 1 \"{$gwname}\"";
1122
						$lcd_cmds[] = "widget_add {$s_name} stata_wdgt scroller";
1123
						$lcd_cmds[] = "widget_add {$s_name} lossl_wdgt string";
1124
						$lcd_cmds[] = "widget_set {$s_name} lossl_wdgt 1 3 \"Loss:\"";
1125
						$lcd_cmds[] = "widget_add {$s_name} lossa_wdgt scroller";
1126
						$lcd_cmds[] = "widget_add {$s_name} rttl_wdgt string";
1127
						$lcd_cmds[] = "widget_set {$s_name} rttl_wdgt 1 4 \"Delay:\"";
1128
						$lcd_cmds[] = "widget_add {$s_name} rtta_wdgt scroller";
1129
						$includeSummary = false; // this screen needs all the lines
1130
					}
1131
					break;
1132
				case "scr_interfaces_link":
1133
					$ifLinkList = build_interface_link_list();
1134
					foreach ($ifLinkList as $ifdescr => $iflink) {
1135
						$s_name = $name . $ifdescr;
1136
						$ifname = $iflink['name'] . ":";
1137
						$lcd_cmds[] = "screen_add {$s_name}";
1138
						$lcd_cmds[] = "screen_set {$s_name} heartbeat off";
1139
						$lcd_cmds[] = "screen_set {$s_name} name \"{$name}.{$ifdescr}\"";
1140
						$lcd_cmds[] = "screen_set {$s_name} duration {$refresh_frequency}";
1141
						$lcd_cmds[] = "widget_add {$s_name} ifname_wdgt string";
1142
						$lcd_cmds[] = "widget_set {$s_name} ifname_wdgt 1 1 \"{$ifname}\"";
1143
						$lcd_cmds[] = "widget_add {$s_name} link_wdgt scroller";
1144
						$lcd_cmds[] = "widget_add {$s_name} v4l_wdgt string";
1145
						$lcd_cmds[] = "widget_set {$s_name} v4l_wdgt 1 2 \"v4:\"";
1146
						$lcd_cmds[] = "widget_add {$s_name} v4a_wdgt scroller";
1147
						$lcd_cmds[] = "widget_add {$s_name} v6l_wdgt string";
1148
						$lcd_cmds[] = "widget_set {$s_name} v6l_wdgt 1 3 \"v6:\"";
1149
						$lcd_cmds[] = "widget_add {$s_name} v6a_wdgt scroller";
1150
						$lcd_cmds[] = "widget_add {$s_name} macl_wdgt string";
1151
						$lcd_cmds[] = "widget_set {$s_name} macl_wdgt 1 4 \"m:\"";
1152
						$lcd_cmds[] = "widget_add {$s_name} maca_wdgt scroller";
1153
						$includeSummary = false; // this screen needs all the lines
1154
					}
1155
					break;
1156
				case "scr_traffic_by_address":
1157
					$lcd_cmds[] = "screen_add {$name}";
1158
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1159
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1160
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1161
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1162
					$lcd_cmds[] = "widget_add {$name} heart_wdgt icon";
1163

    
1164
					for($i = 0; $i < ($lcdpanel_height - 1); $i++) {
1165
						$lcd_cmds[] = "widget_add {$name} descr_wdgt{$i} scroller";
1166
						$lcd_cmds[] = "widget_add {$name} data_wdgt{$i} string";
1167
					}
1168
					$includeSummary = false; // this screen needs all the lines
1169
					break;
1170
				case "scr_apcupsd":
1171
					if (file_exists("/usr/local/pkg/apcupsd.inc")) {
1172
						$lcd_cmds[] = "screen_add {$name}";
1173
						$lcd_cmds[] = "screen_set {$name} heartbeat off";
1174
						$lcd_cmds[] = "screen_set {$name} name {$name}";
1175
						$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1176
						$lcd_cmds[] = "widget_add {$name} apctitlel_wdgt string";
1177
						$lcd_cmds[] = "widget_set {$name} apctitlel_wdgt 1 1 \"APC UPS:\"";
1178
						$lcd_cmds[] = "widget_add {$name} apcname_wdgt scroller";
1179
						$lcd_cmds[] = "widget_add {$name} apcstatus_wdgt scroller";
1180
						$lcdpanel_height = get_lcdpanel_height();
1181
						$lcdpanel_width = get_lcdpanel_width();
1182
						if ($lcdpanel_height >= "4") {
1183
							$lcd_cmds[] = "widget_add {$name} apctitle_summary string";
1184
							$lcd_cmds[] = "widget_add {$name} apc_summary string";
1185
							if ($lcdpanel_width > "16") {
1186
								$lcd_cmds[] = "widget_set {$name} apctitle_summary 1 3 \"LINE CHRG TIMEL LOAD\"";
1187
							} else {
1188
								$lcd_cmds[] = "widget_set {$name} apctitle_summary 1 3 \"LINE CHRG TIMEL\"";
1189
							}
1190
						}
1191
					}
1192
					$includeSummary = false; // this screen needs all the lines
1193
					break;
1194
				case "scr_nutups":
1195
					if (file_exists("/usr/local/pkg/nut/nut.inc")) {
1196
						$lcd_cmds[] = "screen_add {$name}";
1197
						$lcd_cmds[] = "screen_set {$name} heartbeat off";
1198
						$lcd_cmds[] = "screen_set {$name} name {$name}";
1199
						$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1200
						$lcd_cmds[] = "widget_add {$name} nuttitlel_wdgt string";
1201
						$lcd_cmds[] = "widget_set {$name} nuttitlel_wdgt 1 1 \"NUT UPS:\"";
1202
						$lcd_cmds[] = "widget_add {$name} nutname_wdgt scroller";
1203
						$lcd_cmds[] = "widget_add {$name} nutstatus_wdgt scroller";
1204
						$lcdpanel_height = get_lcdpanel_height();
1205
						$lcdpanel_width = get_lcdpanel_width();
1206
						if ($lcdpanel_height >= "4") {
1207
							$lcd_cmds[] = "widget_add {$name} nuttitle_summary string";
1208
							$lcd_cmds[] = "widget_add {$name} nut_summary string";
1209
							if ($lcdpanel_width > "16") {
1210
								$lcd_cmds[] = "widget_set {$name} nuttitle_summary 1 3 \"LIN CHRG RUNTHMS LOD\"";
1211
							} else {
1212
								$lcd_cmds[] = "widget_set {$name} nuttitle_summary 1 3 \"LIN CHRG RUNTHMS\"";
1213
							}
1214
						}
1215
					}
1216
					$includeSummary = false; // this screen needs all the lines
1217
					break;
1218
				default:
1219
					break;
1220
			}
1221
			if ($includeSummary) add_summary_declaration($lcd_cmds, $name);
1222
		}
1223
	}
1224
	send_lcd_commands($lcd, $lcd_cmds);
1225
}
1226

    
1227
function loop_status($lcd) {
1228
	global $g;
1229
	global $lcdproc_connect_errors;
1230
	$lcdproc_screens_config = config_get_path('installedpackages/lcdprocscreens/config/0', []);
1231
	$lcdpanel_width = get_lcdpanel_width();
1232
	$lcdpanel_height = get_lcdpanel_height();
1233
	if (empty($g['product_name'])) {
1234
		$g['product_name'] = "pfSense";
1235
	}
1236

    
1237
	$refresh_frequency = get_lcdpanel_refresh_frequency();
1238
	/* keep a counter to see how many times we can loop */
1239
	$loopCounter = 1;
1240
	while ($loopCounter) {
1241
		/* prepare the summary data */
1242
		if ($lcdpanel_height >= "4") {
1243
			$summary_states = explode("/", get_pfstate());
1244
			$lcd_summary_data = sprintf("%02d%% %02d%% %6d", lcdproc_cpu_usage(), mem_usage(), $summary_states[0]);
1245
			if ($lcdpanel_width > "16") {
1246
				/* Include the CPU frequency as a percentage */
1247
				$maxfreq = get_cpu_maxfrequency();
1248
				if ($maxfreq === false || $maxfreq == 0) {
1249
					$lcd_summary_data .= "  N/A"; // powerd not available on all systems - https://redmine.pfsense.org/issues/5739
1250
				} else {
1251
					$lcd_summary_data .= sprintf(" %3d%%", get_cpu_currentfrequency() / $maxfreq * 100);
1252
				}
1253
			}
1254
		} else {
1255
			$lcd_summary_data = "";
1256
		}
1257

    
1258
		$lcd_cmds = array();
1259
		$interfaceTrafficList = null;
1260
		$ifLinkList = null;
1261
		$gateway_status = null;
1262

    
1263
		/* initializes the widget counter */
1264
		$widget_counter = 0;
1265

    
1266
		/* controls the output leds */
1267
		if (outputled_enabled_CFontzPacket()) {
1268
			$led_output_value = 0;
1269
			/* LED 1: Interface status */
1270
			if (substr_count(get_interfaces_stats(), "Down") > 0 ) {
1271
				$led_output_value = $led_output_value + pow(2, 4);
1272
			} else {
1273
				$led_output_value = $led_output_value + pow(2, 0);
1274
			}
1275
			/* LED 2: CARP status */
1276
			switch (outputled_carp()) {
1277
				/* CARP disabled */
1278
				case -1:
1279
					break;
1280
				/* CARP on Backup */
1281
				case 0:
1282
					$led_output_value = $led_output_value + pow(2, 5);
1283
					break;
1284
				/* CARP on Master */
1285
				case 1:
1286
				default:
1287
					$led_output_value = $led_output_value + pow(2, 1);
1288
			}
1289
			/* LED 3: CPU Usage */
1290
			if (lcdproc_cpu_usage() > 50) {
1291
				$led_output_value = $led_output_value + pow(2, 6);
1292
			} else {
1293
				$led_output_value = $led_output_value + pow(2, 2);
1294
			}
1295
			/* LED 4: Gateway status */
1296
			switch (outputled_gateway()) {
1297
				/* Gateways not configured */
1298
				case -1:
1299
					break;
1300
				/* Gateway down or with issues */
1301
				case 0:
1302
					$led_output_value = $led_output_value + pow(2, 7);
1303
					break;
1304
				/* All Gateways up */
1305
				case 1:
1306
					$led_output_value = $led_output_value + pow(2, 3);
1307
			}
1308
			/* Sends the command to the panel */
1309
			$lcd_cmds[] = "output {$led_output_value}";
1310
		}
1311

    
1312
		/* process screens to display */
1313
		foreach ($lcdproc_screens_config as $name => $screen) {
1314
			if (($screen != "on") && ($screen != "yes")) {
1315
				continue;
1316
			}
1317

    
1318
			$updateSummary = true;
1319

    
1320
			switch($name) {
1321
				case "scr_version":
1322
					$version = get_version();
1323
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$version}\"";
1324
					break;
1325
				case "scr_time":
1326
					$time = date("n/j/Y H:i");
1327
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$time}\"";
1328
					break;
1329
				case "scr_uptime":
1330
					$uptime = get_uptime_stats();
1331
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$uptime}\"";
1332
					break;
1333
				case "scr_hostname":
1334
					exec("/bin/hostname", $output, $ret);
1335
					$hostname = $output[0];
1336
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$hostname}\"";
1337
					break;
1338
				case "scr_system":
1339
					$processor = lcdproc_cpu_usage();
1340
					$memory = mem_usage();
1341
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"CPU {$processor}%, Mem {$memory}%\"";
1342
					break;
1343
				case "scr_disk":
1344
					$disk = disk_usage();
1345
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Disk {$disk}%\"";
1346
					break;
1347
				case "scr_load":
1348
					$loadavg = get_loadavg_stats();
1349
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$loadavg}\"";
1350
					break;
1351
				case "scr_states":
1352
					$states = get_pfstate();
1353
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Cur/Max {$states}\"";
1354
					break;
1355
				case "scr_carp":
1356
					$carp = get_carp_stats();
1357
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$carp}\"";
1358
					break;
1359
				case "scr_ipsec":
1360
					$ipsec = get_ipsec_stats();
1361
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$ipsec}\"";
1362
					break;
1363
				case "scr_interfaces":
1364
					$interfaces = get_interfaces_stats();
1365
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$interfaces}\"";
1366
					break;
1367
				case "scr_gwsum":
1368
					if ($gateway_status === null) {
1369
						$gateway_status = return_gateways_status(true);
1370
					}
1371
					$gwup = 0;
1372
					$gwdown = 0;
1373
					foreach ($gateway_status as $idx => $gw) {
1374
						if ($gw['disabled']) {
1375
							/* Disabled, no need to print anything */
1376
							continue;
1377
						}
1378
						if ($gw['status'] == 'online') {
1379
							$gwup += 1;
1380
						} else {
1381
							$gwdown += 1;
1382
						}
1383
					}
1384
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Up: {$gwup} / Down: {$gwdown}\"";
1385
					break;
1386
				case "scr_mbuf":
1387
					$mbufstats = lcdproc_get_mbuf_stats();
1388
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$mbufstats}\"";
1389
					break;
1390
				case "scr_packages":
1391
					$packages = lcdproc_get_package_summary();
1392
					$title = ($lcdpanel_width >= 20) ? "Installed Packages" : "Packages";
1393
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1394
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$packages}\"";
1395
					break;
1396
				case "scr_cpufrequency":
1397
					$cpufreq = get_cpufrequency();
1398
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cpufreq}\"";
1399
					break;
1400
				case "scr_cputemperature":
1401
					$cputemperature = lcdproc_get_cpu_temperature();
1402
					$title = ($lcdpanel_width >= 20) ? "CPU Temperature" : "CPU Temp";
1403
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1404
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cputemperature}\"";
1405
					break;
1406
				case "scr_ntp":
1407
					$ntp_hms = date("H:iT");
1408
					$ntpq_output = lcdproc_get_ntp_status();
1409
					if ($ntpq_output != false) {
1410
						$ntpq_counter = 0;
1411
						foreach ($ntpq_output as $line) {
1412
							$peersta = substr($line, 0, 1); // Status
1413
							if ($peersta == "o" || // PPS Peer
1414
								$peersta == "*") { // Active Peer
1415
									$line = substr($line, 1);
1416
									$peerinfo = preg_split("/[\s\t]+/", $line);
1417
									$peersrv = $peerinfo[0]; // Server IP
1418
									$peerref = $peerinfo[1]; // Ref ID
1419
									$peerstr = $peerinfo[2]; // Stratum
1420
									$peertyp = $peerinfo[3]; // Type
1421
									$peerdel = substr($peerinfo[7],0,5); // Delay
1422
									$peeroff = substr($peerinfo[8],0,6); // Offset
1423
									$peerjit = substr($peerinfo[9],0,5); // Jitter
1424
									// Common rows
1425
									$lcd_cmds[] = "widget_set {$name} time_st_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"NTP: {$ntp_hms} St: {$peerstr}\"";
1426
									$lcd_cmds[] = "widget_set {$name} text_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"Delay Offset Jitter\"";
1427
									$lcd_cmds[] = "widget_set {$name} stats_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"{$peerdel} {$peeroff} {$peerjit}\"";
1428
									if ($peertyp == "l" &&		// Local
1429
							   			$peerref == ".GPS.") {	// GPS
1430
											// For local GPS, display Ref ID and how many satellites are in use or in view
1431
											$gps_sat_count = lcdproc_get_ntp_gps_sat_count();
1432
											$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Src: {$peerref} " . (($gps_sat_count == false) ? "" : "{$gps_sat_count}") . "\"";
1433
									} elseif ($peertyp == "l" &&	// Local
1434
										$peerref == ".PPS.") {		// PPS
1435
											// For local PPS, display Ref ID and stability
1436
											exec('/usr/local/sbin/ntptime | /usr/bin/grep "pps freq"', $line);
1437
											$line = implode(",", $line);
1438
											$ppsinfo = preg_split("/\s+/", $line);
1439
											$ppsstb = $ppsinfo[6]; // PPS Stability
1440
											$ppsjit = $ppsinfo[9]; // PPS Jitter
1441
											$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Src: {$peerref} PPM:{$ppsstb}\"";
1442
									} elseif ($peertyp == "l") {	// Local
1443
										// For all other local, display Ref ID
1444
										$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Src: {$peerref}\"";
1445
									} else {
1446
										// For everything else, display IP of the source
1447
										$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Src: {$peersrv}\"";
1448
									}
1449
									$ntpq_counter++;
1450
								}
1451
							}
1452
						if ($ntpq_counter == 0) {
1453
							$lcd_cmds[] = "widget_set {$name} time_st_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"NTP: No active peers\"";
1454
							$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"\"";
1455
							$lcd_cmds[] = "widget_set {$name} text_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"\"";
1456
							$lcd_cmds[] = "widget_set {$name} stats_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"\"";
1457
						}
1458
					} else {
1459
						$lcd_cmds[] = "widget_set {$name} time_st_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"NTP: Server disabled\"";
1460
						$lcd_cmds[] = "widget_set {$name} ref_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"\"";
1461
						$lcd_cmds[] = "widget_set {$name} text_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"\"";
1462
						$lcd_cmds[] = "widget_set {$name} stats_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"\"";
1463
					}
1464
					$updateSummary = false;
1465
					break;
1466
				case "scr_traffic":
1467
					if ($interfaceTrafficList == null) $interfaceTrafficList = build_interface_traffic_stats_list(); // We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1468
					get_traffic_stats($interfaceTrafficList, $in_data, $out_data);
1469
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$in_data}\"";
1470
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 \"{$out_data}\"";
1471
					break;
1472
				case "scr_top_interfaces_by_bps":
1473
					if ($interfaceTrafficList == null) {
1474
						// We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1475
						$interfaceTrafficList = build_interface_traffic_stats_list();
1476
					}
1477
					$interfaceTrafficStrings = get_top_interfaces_by_bps($interfaceTrafficList, $lcdpanel_width, $lcdpanel_height);
1478

    
1479
					$title = ($lcdpanel_width >= 20) ? "Interface bps IN/OUT" : "Intf. bps IN/OUT";
1480
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1481

    
1482
					for($i = 0; $i < ($lcdpanel_height - 1) && $i < count($interfaceTrafficStrings); $i++) {
1483

    
1484
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1485
					}
1486
					$updateSummary = false;
1487
					break;
1488
				case "scr_top_interfaces_by_bytes_today":
1489
					if ($interfaceTrafficList == null) $interfaceTrafficList = build_interface_traffic_stats_list(); // We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1490
					$interfaceTrafficStrings = get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width);
1491

    
1492
					$title = ($lcdpanel_width >= 20) ? "Total today   IN/OUT" : "Today   IN / OUT";
1493
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1494

    
1495
					for($i = 0; $i < ($lcdpanel_height - 1) && $i < count($interfaceTrafficStrings); $i++) {
1496

    
1497
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1498
					}
1499
					$updateSummary = false;
1500
					break;
1501
				case "scr_top_interfaces_by_total_bytes":
1502
					if ($interfaceTrafficList == null) $interfaceTrafficList = build_interface_traffic_stats_list(); // We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1503
					$interfaceTrafficStrings = get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width);
1504

    
1505
					$title = ($lcdpanel_width >= 20) ? "Total         IN/OUT" : "Total   IN / OUT";
1506
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1507

    
1508
					for($i = 0; $i < ($lcdpanel_height - 1) && $i < count($interfaceTrafficStrings); $i++) {
1509

    
1510
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1511
					}
1512
					$updateSummary = false;
1513
					break;
1514
				case "scr_gwstatus":
1515
					if ($gateway_status === null) {
1516
						$gateway_status = return_gateways_status(true);
1517
					}
1518
					foreach ($gateway_status as $gwname => $gw) {
1519
						if ($gw['disabled'] ||
1520
						    $gw['monitor_disable']) {
1521
							/* Disabled, no need to print anything */
1522
							continue;
1523
						}
1524
						$s_name = $name . $gwname;
1525
						$lcd_cmds[] = "widget_set {$s_name} gwname_wdgt 1 1 \"{$gwname}\"";
1526
						$statstring = ucwords($gw['status']);
1527
						if (!empty($gw['substatus']) &&
1528
						    ($gw['substatus'] != "none")) {
1529
							$statstring .= " ({$gw['substatus']})";
1530
						}
1531
						$lcd_cmds[] = "widget_set $s_name stata_wdgt 1 2 " .
1532
							$lcdpanel_width . " 2 h 4 \"" .
1533
							$statstring . "\"";
1534

    
1535
						$lcd_cmds[] = "widget_set $s_name lossa_wdgt 7 3 " .
1536
							$lcdpanel_width . " 3 h 4 \"" .
1537
							$gw['loss'] . "\"";
1538

    
1539
						$lcd_cmds[] = "widget_set $s_name rtta_wdgt 8 4 " .
1540
							$lcdpanel_width . " 4 h 4 \"" .
1541
							$gw['delay'] . "\"";
1542
					}
1543
					$updateSummary = false;
1544
					break;
1545
				case "scr_interfaces_link":
1546
					// We only want build_interface_link_list() to be
1547
					// called once per loop, and only if it's needed
1548
					if ($ifLinkList == null) {
1549
						$ifLinkList = build_interface_link_list();
1550
					}
1551

    
1552
					foreach ($ifLinkList as $ifdescr => $iflink) {
1553
						$s_name = $name . $ifdescr;
1554
						$ifname = $iflink['name'] . ":";
1555
						$l_str = ($iflink['status'] == "down") ? "down" : $iflink['link'];
1556

    
1557
						$lcd_cmds[] = "widget_set $s_name ifname_wdgt 1 1 \"$ifname\"";
1558

    
1559
						$lcd_cmds[] = "widget_set $s_name link_wdgt " .
1560
							(strlen($iflink['name']) + 3) . " 1 " .
1561
							$lcdpanel_width . " 1 h 4 \"" . $l_str . "\"";
1562

    
1563
						$lcd_cmds[] = "widget_set $s_name v4a_wdgt 5 2 " .
1564
							$lcdpanel_width . " 2 h 4 \"" .
1565
							$iflink['v4addr'] . "\"";
1566

    
1567
						$lcd_cmds[] = "widget_set $s_name v6a_wdgt 5 3 " .
1568
							$lcdpanel_width . " 3 h 4 \"" .
1569
							$iflink['v6addr'] . "\"";
1570

    
1571
						$lcd_cmds[] = "widget_set $s_name maca_wdgt 4 4 " .
1572
							$lcdpanel_width . " 4 h 4 \"" .
1573
							$iflink['mac'] . "\"";
1574
					}
1575
					$updateSummary = false;
1576
					break;
1577
				case "scr_traffic_by_address":
1578
					$title = ($lcdpanel_width >= 20) ? "Host       IN / OUT" : "Host   IN / OUT";
1579
					$lcd_cmds[] = "widget_set {$name} title_wdgt 2 1 \"{$title}\"";
1580
					$lcd_cmds[] = "widget_set {$name} heart_wdgt 1 1 \"" . (($loopCounter & 1) == 0 ? "HEART_OPEN" : "HEART_FILLED") . "\""; // Indicate each time the list has been updated
1581

    
1582
					$traffic = get_bandwidth_by_ip();
1583
					$clearLinesFrom = 0;
1584

    
1585
					if (isset($traffic['error'])) {
1586
						if ($traffic['error'] === "no info") {
1587
							// not really an error - there's likely just no traffic
1588
						} else {
1589
							// traffic info not available, display the error message instead
1590
							$lcd_cmds[] = "widget_set {$name} descr_wdgt0 1 2 {$lcdpanel_width} 2 h 2 \"Error: {$traffic['error']}\"";
1591
							$lcd_cmds[] = "widget_set {$name} data_wdgt0 1 2 \"\"";
1592
							$clearLinesFrom = 1;
1593
						}
1594
					} else {
1595
						for ($i = 0; $i < ($lcdpanel_height - 1) && $i < count($traffic); $i++) {
1596
							$speeds = $traffic[$i]['in/out'];
1597
							$left = $lcdpanel_width - strlen($speeds);
1598
							$lcd_cmds[] = "widget_set {$name} data_wdgt{$i} " . ($left + 1) . " " . ($i + 2) . " \"{$speeds}\"";
1599
							$lcd_cmds[] = "widget_set {$name} descr_wdgt{$i} 1 " . ($i + 2) . " " . ($left - 1) . " " . ($i + 2) . " h 2 \"{$traffic[$i]['name']}\"";
1600
							$clearLinesFrom = $i + 1;
1601
						}
1602
					}
1603
					for($i = $clearLinesFrom; $i < ($lcdpanel_height - 1); $i++) {
1604
						$lcd_cmds[] = "widget_set {$name} descr_wdgt{$i} 1 2 1 2 h 2 \"\"";
1605
						$lcd_cmds[] = "widget_set {$name}  data_wdgt{$i} 1 2         \"\"";
1606
					}
1607
					$updateSummary = false;
1608
					break;
1609
				case "scr_apcupsd":
1610
					if (file_exists("/usr/local/pkg/apcupsd.inc")) {
1611
						require_once("/usr/local/pkg/apcupsd.inc");
1612
						$results = [];
1613
						$nis_server = check_nis_running_apcupsd();
1614
						if ($nis_server) {
1615
							$nisip = (check_nis_ip_apcupsd() != ''? check_nis_ip_apcupsd() : "localhost");
1616
							$nisport = (check_nis_port_apcupsd() != '' ? check_nis_port_apcupsd() : "3551");
1617
							$ph = popen("/usr/local/sbin/apcaccess -h " . escapeshellarg($nisip) . ":" . escapeshellarg($nisport) . " 2>&1", "r" );
1618
							while ($v = fgets($ph)) {
1619
								$results[trim(explode(': ', $v)[0])]=trim(explode(': ', $v)[1]);
1620
							}
1621
							pclose($ph);
1622
							if ($results == null) {
1623
								$results['UPSNAME'] = "Unknown";
1624
								$results['STATUS'] = "Invalid Response";
1625
							}
1626
						} else {
1627
							$results['UPSNAME'] = "Unknown";
1628
							$results['STATUS'] = "Service Stopped";
1629
						}
1630
						if (empty($results['UPSNAME'])) {
1631
							$results['UPSNAME'] = "No Name";
1632
						}
1633
						if (empty($results['STATUS'])) {
1634
							$results['STATUS'] = "Unknown";
1635
						}
1636

    
1637
						$lcdpanel_height = get_lcdpanel_height();
1638
						$lcdpanel_width = get_lcdpanel_width();
1639

    
1640
						$lcd_cmds[] = "widget_set {$name} apcname_wdgt 10 1 {$lcdpanel_width} 2 h 4 \"{$results['UPSNAME']}\"";
1641
						$lcd_cmds[] = "widget_set {$name} apcstatus_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$results['STATUS']}\"";
1642

    
1643
						if ($lcdpanel_height >= "4") {
1644
							if (!empty($results['LINEV'])) {
1645
								$results['LINEV'] = str_replace(" Percent", "", $results['LINEV']);
1646
							} else {
1647
								$results['LINEV'] = 'N/A';
1648
							}
1649
							if (!empty($results['BCHARGE'])) {
1650
								$results['BCHARGE'] = str_replace(" Percent", "", $results['BCHARGE']);
1651
							} else {
1652
								$results['BCHARGE'] = 'N/A';
1653
							}
1654
							if (!empty($results['TIMELEFT'])) {
1655
								$results['TIMELEFT'] = str_replace(" Minutes", "", $results['TIMELEFT']);
1656
							} else {
1657
								$results['TIMELEFT'] = 'N/A';
1658
							}
1659
							$ups_summary_data = sprintf("%3dV %3d%% %4dM", $results['LINEV'], $results['BCHARGE'], $results['TIMELEFT']);
1660
							if ($lcdpanel_width > "16") {
1661
								if (!empty($results['LOADPCT'])) {
1662
									$results['LOADPCT'] = str_replace(" Percent", "", $results['LOADPCT']);
1663
								} else {
1664
									$results['LOADPCT'] = 'N/A';
1665
								}
1666
								$ups_summary_data .= sprintf(" %3d%%", $results['LOADPCT']);
1667
							}
1668
							$lcd_cmds[] = "widget_set {$name} apc_summary 1 4 \"{$ups_summary_data}\"";
1669
						}
1670
					}
1671
					$updateSummary = false;
1672
					break;
1673
				case "scr_nutups":
1674
					if (file_exists("/usr/local/pkg/nut/nut.inc")) {
1675
						require_once("/usr/local/pkg/nut/nut.inc");
1676
						$results = nut_ups_status();
1677
						if (!empty($results)) {
1678
							if (empty($results['_summary'])) {
1679
								$results['_summary'] = "Invalid Response";
1680
							}
1681
						} else {
1682
							$results['_name'] = "Unknown";
1683
							$results['_summary'] = "Service Stopped";
1684
						}
1685
						if (empty($results['_name'])) {
1686
							$results['_name'] = "No Name";
1687
						} else {
1688
							[$nutupsname, $nutupshost] = explode('@', $results['_name']);
1689
							$results['_name'] = $nutupsname;
1690
						}
1691
						if (empty($results['_summary'])) {
1692
							$results['_summary'] = "Unknown";
1693
						}
1694

    
1695
						$lcdpanel_height = get_lcdpanel_height();
1696
						$lcdpanel_width = get_lcdpanel_width();
1697

    
1698
						$lcd_cmds[] = "widget_set {$name} nutname_wdgt 10 1 {$lcdpanel_width} 2 h 4 \"{$results['_name']}\"";
1699
						$lcd_cmds[] = "widget_set {$name} nutstatus_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$results['_summary']}\"";
1700

    
1701
						if ($lcdpanel_height >= "4") {
1702
							if (empty($results['input.voltage'])) {
1703
								$results['input.voltage'] = 'N/A';
1704
							}
1705
							if (empty($results['battery.charge'])) {
1706
								$results['battery.charge'] = 'N/A';
1707
							}
1708
							if (empty($results['_hms'])) {
1709
								$results['_hms'] = 'N/A';
1710
							}
1711
							$ups_summary_data = sprintf("%3d %3d%% %7s", $results['input.voltage'], $results['battery.charge'], $results['_hms']);
1712
							if ($lcdpanel_width > "16") {
1713
								if (empty($results['ups.load'])) {
1714
									$results['ups.load'] = 'N/A';
1715
								}
1716
								$ups_summary_data .= sprintf(" %2d%%", $results['ups.load']);
1717
							}
1718
							$lcd_cmds[] = "widget_set {$name} nut_summary 1 4 \"{$ups_summary_data}\"";
1719
						}
1720
					}
1721
					$updateSummary = false;
1722
					break;
1723
				default:
1724
					break;
1725
			}
1726
			if ($name != "scr_traffic_interface" && substr($name, 0, 23) != 'scr_traffic_by_address_') {	// "scr_traffic_interface" isn't a real screen, it's a parameter for the "scr_traffic" screen
1727
				$widget_counter++;
1728
				if ($updateSummary) add_summary_values($lcd_cmds, $name, $lcd_summary_data);
1729
			}
1730
		}
1731
		if (send_lcd_commands($lcd, $lcd_cmds)) {
1732
			$lcdproc_connect_errors = 0; // Reset the error counter
1733
		} else {
1734
			//an error occurred
1735
			return;
1736
		}
1737
		if (($refresh_frequency * $widget_counter) > 5) {
1738
			// If LCD is waiting 10 seconds on each screen, for example, then we can update the data of
1739
			// of a screen while its being displayed.
1740
			sleep(5);
1741
		} else {
1742
			sleep($refresh_frequency * $widget_counter);
1743
		}
1744
		$loopCounter++;
1745
	}
1746
}
1747

    
1748
/* Initialize the wan traffic counters */
1749
$traffic_last_ugmt  = array();
1750
$traffic_last_ifin  = array();
1751
$traffic_last_ifout = array();
1752

    
1753
$traffic_last_hour        = array();
1754
$traffic_startOfDay_ifin  = array();
1755
$traffic_startOfDay_ifout = array();
1756

    
1757
/* Initialize the global error counter */
1758
$lcdproc_connect_errors = 0;
1759
$lcdproc_max_connect_errors = 3;
1760
/* Connect to the LCDd port and interface with the LCD */
1761
while ($lcdproc_connect_errors <= $lcdproc_max_connect_errors) {
1762
	lcdproc_warn("Start client procedure. Error counter: ({$lcdproc_connect_errors})");
1763
	sleep(1);
1764
	$lcd = fsockopen(LCDPROC_HOST, LCDPROC_PORT, $errno, $errstr, 10);
1765
	if (!$lcd) {
1766
		lcdproc_warn("Failed to connect to LCDd process {$errstr} ({$errno})");
1767
		$lcdproc_connect_errors++;
1768
	} else {
1769
		stream_set_timeout($lcd, 0 , 25000); // Sets the socket timeout as 25ms
1770
		/* Allow the script to run forever (0) */
1771
		set_time_limit(0);
1772
		build_interface($lcd);
1773
		loop_status($lcd);
1774
		fclose($lcd);
1775
	}
1776
}
1777
if ($lcdproc_connect_errors >= $lcdproc_max_connect_errors) {
1778
	lcdproc_warn("Too many errors, stopping client.");
1779
}
1780
?>
    (1-1/1)