Project

General

Profile

Feature #14625 » lcdproc_client.php

Elvis Impersonator, 07/29/2023 03:03 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['ntpd']['enable'] == 'enabled') {
155
		if (isset($config['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 (isset($gps_ok) && isset($config['ntpd']['gps']['extstatus'])) {
170
	if (isset($config['ntpd']['gps']['extstatus'])) {
171
		//$lookfor['GPGSV'] = config_get_path('ntpd/gps/nmeaset/gpgsv');
172
		$lookfor['GPGSV'] = $config['ntpd']['gps']['nmeaset']['gpgsv'];
173
		$lookfor['GPGGA'] = !isset($gps_sat) && $config['ntpd']['gps']['nmeaset']['gpgga'];
174
		$gpsport = fopen('/dev/gps0', 'r+');
175
		while ($gpsport && ($lookfor['GPGSV'] || $lookfor['GPGGA'])) {
176
			$buffer = fgets($gpsport);
177
			if ($lookfor['GPGSV'] && substr($buffer, 0, 6) == '$GPGSV') {
178
				$gpgsv = explode(',', $buffer);
179
				$gps_satview = (int)$gpgsv[3];
180
				return ("Sats: " . $gps_satview . " in view");
181
			} elseif ($lookfor['GPGGA'] && substr($buffer, 0, 6) == '$GPGGA') {
182
				$gpgga = explode(',', $buffer);
183
				$gps_sat = (int)$gpgga[7];
184
				return ("Sats: " . $gps_sat . " in use");
185
			}
186
		}
187
	} else {
188
		return false;
189
	}
190

    
191
}
192

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

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

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

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

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

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

    
239
function get_interfaces_stats() {
240
	$ifstatus = [];
241
	$ifdescrs = get_configured_interface_with_descr();
242

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

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

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

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

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

    
342
function get_ipsec_stats() {
343
	global $sad;
344
	$sad = array();
345
	$sad = ipsec_dump_sad();
346

    
347
	$activecounter = 0;
348
	$inactivecounter = 0;
349

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

    
355
		$tun_disabled = "false";
356
		$foundsrc = false;
357
		$founddst = false;
358

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
554
		$result[$ifdescr] = $entry;
555
	}
556
	return $result;
557
}
558

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

    
564
	$result = array();
565
	$interfaceList = get_configured_interface_with_descr();
566

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

    
573
		calculate_interfaceBytesPerSecond_sinceLastChecked($interfaceName, $interfaceStats, $in_Bps, $out_Bps);
574
		calculate_bytesToday($interfaceName, $interfaceStats, $in_bytesToday, $out_bytesToday);
575

    
576
		$entry = array();
577
		$entry['descr']       = $description;
578

    
579
		$entry['in_Bps']      = $in_Bps;
580
		$entry['out_Bps']     = $out_Bps;
581
		$entry['total_Bps']   = $in_Bps + $out_Bps;
582

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

    
587
		$entry['in_bytes_today']    = $in_bytesToday;
588
		$entry['out_bytes_today']   = $out_bytesToday;
589
		$entry['total_bytes_today'] = $in_bytesToday + $out_bytesToday;
590

    
591
		$result[$interface['if']] = $entry;
592
	}
593
	return $result;
594
}
595

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

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

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

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

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

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

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

    
629
	global $traffic_last_ugmt, $traffic_last_ifin, $traffic_last_ifout;
630

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

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

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

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

    
648
	$hourOfDay = getdate()['hours'];
649

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

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

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

    
667
	$nameLength = $outputLength - strlen($speed);
668

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

    
678
	return $name . $speed;
679
}
680

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

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

    
697
	$showDecimalPlace = $unitSize < 10 && round($unitSize, 1) != round($unitSize);
698

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

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

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

    
719
	$showDecimalPlace = $unitSpeed < 10 && round($unitSpeed, 1) != round($unitSpeed);
720

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

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

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

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

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

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

    
749
	$interfaceEntry = $interface_traffic_list[$realif];
750

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

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

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

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

    
773
function get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width) {
774
	$result = [];
775

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

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

    
792
function get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width) {
793
	$result = [];
794

    
795
	sort_interface_list_by_total_bytes($interfaceTrafficList);
796

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

    
803

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

    
811
	if ($bytes_string == "0.00") {
812
		return "0";
813
	}
814

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

    
828
function get_bandwidth_by_ip() {
829
	$result       = [];
830

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

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

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

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

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

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

    
872
	return $result;
873
}
874

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

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

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

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

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

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

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

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

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

    
1089
						$includeSummary = false; // this screen needs all the lines
1090
						break;				case "scr_traffic":
1091
					$lcd_cmds[] = "screen_add {$name}";
1092
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1093
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1094
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1095
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1096
					$lcd_cmds[] = "widget_add {$name} text_wdgt string";
1097
					break;
1098
				case "scr_top_interfaces_by_bps":
1099
				case "scr_top_interfaces_by_total_bytes":
1100
				case "scr_top_interfaces_by_bytes_today":
1101
					$lcd_cmds[] = "screen_add {$name}";
1102
					$lcd_cmds[] = "screen_set {$name} heartbeat off";
1103
					$lcd_cmds[] = "screen_set {$name} name {$name}";
1104
					$lcd_cmds[] = "screen_set {$name} duration {$refresh_frequency}";
1105
					$lcd_cmds[] = "widget_add {$name} title_wdgt string";
1106

    
1107
					for($i = 0; $i < ($lcdpanel_height - 1); $i++) {
1108
						$lcd_cmds[] = "widget_add {$name} text_wdgt{$i} string";
1109
					}
1110
					$includeSummary = false; // this screen needs all the lines
1111
					break;
1112
				case "scr_gwstatus":
1113
					$gateway_status = return_gateways_status(true);
1114
					foreach ($gateway_status as $gwname => $gw) {
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['status'] == 'online') {
1375
							$gwup += 1;
1376
						} else {
1377
							$gwdown += 1;
1378
						}
1379
					}
1380
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Up: {$gwup} / Down: {$gwdown}\"";
1381
					break;
1382
				case "scr_mbuf":
1383
					$mbufstats = lcdproc_get_mbuf_stats();
1384
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$mbufstats}\"";
1385
					break;
1386
				case "scr_packages":
1387
					$packages = lcdproc_get_package_summary();
1388
					$title = ($lcdpanel_width >= 20) ? "Installed Packages" : "Packages";
1389
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1390
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$packages}\"";
1391
					break;
1392
				case "scr_cpufrequency":
1393
					$cpufreq = get_cpufrequency();
1394
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cpufreq}\"";
1395
					break;
1396
				case "scr_cputemperature":
1397
					$cputemperature = lcdproc_get_cpu_temperature();
1398
					$title = ($lcdpanel_width >= 20) ? "CPU Temperature" : "CPU Temp";
1399
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1400
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cputemperature}\"";
1401
					break;
1402
				case "scr_ntp":
1403
					$ntpq_output = lcdproc_get_ntp_status();
1404
					
1405
					if ($ntpq_output != false) {
1406
						$ntpq_counter = 0;
1407
						foreach ($ntpq_output as $line) {
1408
							if (substr($line, 0, 1) == "*") {
1409
								//Active NTP Peer
1410
								$line = substr($line, 1);
1411
								$peerinfo = preg_split("/[\s\t]+/", $line);
1412
								if ($peerinfo[2] == "0") {
1413
									// When local GPS is used. Show the IP of the source and the stratum. Also append how many satellites are in use or in view
1414
									$gps_sat_count = lcdproc_get_ntp_gps_sat_count();
1415
									$lcd_cmds[] = "widget_set $name source_wdgt 1 1 $lcdpanel_width 2 h 4 \"{$peerinfo[1]} (stratum {$peerinfo[2]}) " . (($gps_sat_count == false) ? "" : "{$gps_sat_count}") . "\"";
1416
									$lcd_cmds[] = "widget_set $name delay_wdgt 1 2 $lcdpanel_width 2 h 4 \"Delay: {$peerinfo[7]}\"";
1417
									$lcd_cmds[] = "widget_set $name offset_wdgt 1 3 $lcdpanel_width 2 h 4 \"Offset: {$peerinfo[8]}\"";
1418
									$lcd_cmds[] = "widget_set $name jitter_wdgt 1 4 $lcdpanel_width 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1419
								} else {
1420
									// Show IP of the source and the stratum
1421
									$lcd_cmds[] = "widget_set $name source_wdgt 1 1 $lcdpanel_width 2 h 4 \"{$peerinfo[0]} (stratum {$peerinfo[2]})\"";
1422
									$lcd_cmds[] = "widget_set $name delay_wdgt 1 2 $lcdpanel_width 2 h 4 \"Delay: {$peerinfo[7]}\"";
1423
									$lcd_cmds[] = "widget_set $name offset_wdgt 1 3 $lcdpanel_width 2 h 4 \"Offset: {$peerinfo[8]}\"";
1424
									$lcd_cmds[] = "widget_set $name jitter_wdgt 1 4 $lcdpanel_width 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1425
								}
1426
								$ntpq_counter++;
1427
							} elseif (substr($line, 0, 1) == "o") {
1428
								//Local PPS Peer
1429
								$line = substr($line, 1);
1430
								$peerinfo = preg_split("/[\s\t]+/", $line);
1431
								$lcd_cmds[] = "widget_set $name source_wdgt 1 1 $lcdpanel_width 2 h 4 \"{$peerinfo[1]} (stratum {$peerinfo[2]}, PPS)\"";
1432
								$lcd_cmds[] = "widget_set $name delay_wdgt 1 2 $lcdpanel_width 2 h 4 \"Delay: {$peerinfo[7]}\"";
1433
								$lcd_cmds[] = "widget_set $name offset_wdgt 1 3 $lcdpanel_width 2 h 4 \"Offset: {$peerinfo[8]}\"";
1434
								$lcd_cmds[] = "widget_set $name jitter_wdgt 1 4 $lcdpanel_width 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1435
								$ntpq_counter++;
1436
							}
1437
						}
1438
						if ($ntpq_counter == 0) {
1439
							$lcd_cmds[] = "widget_set $name source_wdgt 1 1 $lcdpanel_width 2 h 4 \"No active peers available\"";
1440
							$lcd_cmds[] = "widget_set $name delay_wdgt 1 2 $lcdpanel_width 2 h 4 \"\"";
1441
							$lcd_cmds[] = "widget_set $name offset_wdgt 1 3 $lcdpanel_width 2 h 4 \"\"";
1442
							$lcd_cmds[] = "widget_set $name jitter_wdgt 1 4 $lcdpanel_width 2 h 4 \"\"";
1443
						} 
1444
					} else {
1445
						$lcd_cmds[] = "widget_set $name source_wdgt 1 1 $lcdpanel_width 2 h 4 \"NTP Server is Disabled\"";
1446
						$lcd_cmds[] = "widget_set $name delay_wdgt 1 2 $lcdpanel_width 2 h 4 \"\"";
1447
						$lcd_cmds[] = "widget_set $name offset_wdgt 1 3 $lcdpanel_width 2 h 4 \"\"";
1448
						$lcd_cmds[] = "widget_set $name jitter_wdgt 1 4 $lcdpanel_width 2 h 4 \"\"";
1449
					}
1450

    
1451
					$updateSummary = false;
1452
					break;				case "scr_traffic":
1453
					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
1454
					get_traffic_stats($interfaceTrafficList, $in_data, $out_data);
1455
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$in_data}\"";
1456
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 \"{$out_data}\"";
1457
					break;
1458
				case "scr_top_interfaces_by_bps":
1459
					if ($interfaceTrafficList == null) {
1460
						// We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1461
						$interfaceTrafficList = build_interface_traffic_stats_list();
1462
					}
1463
					$interfaceTrafficStrings = get_top_interfaces_by_bps($interfaceTrafficList, $lcdpanel_width, $lcdpanel_height);
1464

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

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

    
1470
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1471
					}
1472
					$updateSummary = false;
1473
					break;
1474
				case "scr_top_interfaces_by_bytes_today":
1475
					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
1476
					$interfaceTrafficStrings = get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width);
1477

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

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

    
1483
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1484
					}
1485
					$updateSummary = false;
1486
					break;
1487
				case "scr_top_interfaces_by_total_bytes":
1488
					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
1489
					$interfaceTrafficStrings = get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width);
1490

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

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

    
1496
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1497
					}
1498
					$updateSummary = false;
1499
					break;
1500
				case "scr_gwstatus":
1501
					if ($gateway_status === null) {
1502
						$gateway_status = return_gateways_status(true);
1503
					}
1504
					foreach ($gateway_status as $gwname => $gw) {
1505
						$s_name = $name . $gwname;
1506
						$lcd_cmds[] = "widget_set {$s_name} gwname_wdgt 1 1 \"{$gwname}\"";
1507

    
1508
						if ($gw['monitor_disable']) {
1509
							$gw['substatus'] = 'assumed';
1510
							$gw['loss'] = 'Disabled';
1511
							$gw['delay'] = 'Disabled';
1512
						}
1513
						$statstring = ucwords($gw['status']);
1514
						if (!empty($gw['substatus']) &&
1515
						    ($gw['substatus'] != "none")) {
1516
							$statstring .= " ({$gw['substatus']})";
1517
						}
1518
						$lcd_cmds[] = "widget_set $s_name stata_wdgt 1 2 " .
1519
							$lcdpanel_width . " 2 h 4 \"" .
1520
							$statstring . "\"";
1521

    
1522
						$lcd_cmds[] = "widget_set $s_name lossa_wdgt 7 3 " .
1523
							$lcdpanel_width . " 3 h 4 \"" .
1524
							$gw['loss'] . "\"";
1525

    
1526
						$lcd_cmds[] = "widget_set $s_name rtta_wdgt 8 4 " .
1527
							$lcdpanel_width . " 4 h 4 \"" .
1528
							$gw['delay'] . "\"";
1529
					}
1530
					$updateSummary = false;
1531
					break;
1532
				case "scr_interfaces_link":
1533
					// We only want build_interface_link_list() to be
1534
					// called once per loop, and only if it's needed
1535
					if ($ifLinkList == null) {
1536
						$ifLinkList = build_interface_link_list();
1537
					}
1538

    
1539
					foreach ($ifLinkList as $ifdescr => $iflink) {
1540
						$s_name = $name . $ifdescr;
1541
						$ifname = $iflink['name'] . ":";
1542
						$l_str = ($iflink['status'] == "down") ? "down" : $iflink['link'];
1543

    
1544
						$lcd_cmds[] = "widget_set $s_name ifname_wdgt 1 1 \"$ifname\"";
1545

    
1546
						$lcd_cmds[] = "widget_set $s_name link_wdgt " .
1547
							(strlen($iflink['name']) + 3) . " 1 " .
1548
							$lcdpanel_width . " 1 h 4 \"" . $l_str . "\"";
1549

    
1550
						$lcd_cmds[] = "widget_set $s_name v4a_wdgt 5 2 " .
1551
							$lcdpanel_width . " 2 h 4 \"" .
1552
							$iflink['v4addr'] . "\"";
1553

    
1554
						$lcd_cmds[] = "widget_set $s_name v6a_wdgt 5 3 " .
1555
							$lcdpanel_width . " 3 h 4 \"" .
1556
							$iflink['v6addr'] . "\"";
1557

    
1558
						$lcd_cmds[] = "widget_set $s_name maca_wdgt 4 4 " .
1559
							$lcdpanel_width . " 4 h 4 \"" .
1560
							$iflink['mac'] . "\"";
1561
					}
1562
					$updateSummary = false;
1563
					break;
1564
				case "scr_traffic_by_address":
1565
					$title = ($lcdpanel_width >= 20) ? "Host       IN / OUT" : "Host   IN / OUT";
1566
					$lcd_cmds[] = "widget_set {$name} title_wdgt 2 1 \"{$title}\"";
1567
					$lcd_cmds[] = "widget_set {$name} heart_wdgt 1 1 \"" . (($loopCounter & 1) == 0 ? "HEART_OPEN" : "HEART_FILLED") . "\""; // Indicate each time the list has been updated
1568

    
1569
					$traffic = get_bandwidth_by_ip();
1570
					$clearLinesFrom = 0;
1571

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

    
1624
						$lcdpanel_height = get_lcdpanel_height();
1625
						$lcdpanel_width = get_lcdpanel_width();
1626

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

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

    
1682
						$lcdpanel_height = get_lcdpanel_height();
1683
						$lcdpanel_width = get_lcdpanel_width();
1684

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

    
1688
						if ($lcdpanel_height >= "4") {
1689
							if (empty($results['input.voltage'])) {
1690
								$results['input.voltage'] = 'N/A';
1691
							}
1692
							if (empty($results['battery.charge'])) {
1693
								$results['battery.charge'] = 'N/A';
1694
							}
1695
							if (empty($results['_hms'])) {
1696
								$results['_hms'] = 'N/A';
1697
							}
1698
							$ups_summary_data = sprintf("%3d %3d%% %7s", $results['input.voltage'], $results['battery.charge'], $results['_hms']);
1699
							if ($lcdpanel_width > "16") {
1700
								if (empty($results['ups.load'])) {
1701
									$results['ups.load'] = 'N/A';
1702
								}
1703
								$ups_summary_data .= sprintf(" %2d%%", $results['ups.load']);
1704
							}
1705
							$lcd_cmds[] = "widget_set {$name} nut_summary 1 4 \"{$ups_summary_data}\"";
1706
						}
1707
					}
1708
					$updateSummary = false;
1709
					break;
1710
				default:
1711
					break;
1712
			}
1713
			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
1714
				$widget_counter++;
1715
				if ($updateSummary) add_summary_values($lcd_cmds, $name, $lcd_summary_data);
1716
			}
1717
		}
1718
		if (send_lcd_commands($lcd, $lcd_cmds)) {
1719
			$lcdproc_connect_errors = 0; // Reset the error counter
1720
		} else {
1721
			//an error occurred
1722
			return;
1723
		}
1724
		if (($refresh_frequency * $widget_counter) > 5) {
1725
			// If LCD is waiting 10 seconds on each screen, for example, then we can update the data of
1726
			// of a screen while its being displayed.
1727
			sleep(5);
1728
		} else {
1729
			sleep($refresh_frequency * $widget_counter);
1730
		}
1731
		$loopCounter++;
1732
	}
1733
}
1734

    
1735
/* Initialize the wan traffic counters */
1736
$traffic_last_ugmt  = array();
1737
$traffic_last_ifin  = array();
1738
$traffic_last_ifout = array();
1739

    
1740
$traffic_last_hour        = array();
1741
$traffic_startOfDay_ifin  = array();
1742
$traffic_startOfDay_ifout = array();
1743

    
1744
/* Initialize the global error counter */
1745
$lcdproc_connect_errors = 0;
1746
$lcdproc_max_connect_errors = 3;
1747
/* Connect to the LCDd port and interface with the LCD */
1748
while ($lcdproc_connect_errors <= $lcdproc_max_connect_errors) {
1749
	lcdproc_warn("Start client procedure. Error counter: ({$lcdproc_connect_errors})");
1750
	sleep(1);
1751
	$lcd = fsockopen(LCDPROC_HOST, LCDPROC_PORT, $errno, $errstr, 10);
1752
	if (!$lcd) {
1753
		lcdproc_warn("Failed to connect to LCDd process {$errstr} ({$errno})");
1754
		$lcdproc_connect_errors++;
1755
	} else {
1756
		stream_set_timeout($lcd, 0 , 25000); // Sets the socket timeout as 25ms
1757
		/* Allow the script to run forever (0) */
1758
		set_time_limit(0);
1759
		build_interface($lcd);
1760
		loop_status($lcd);
1761
		fclose($lcd);
1762
	}
1763
}
1764
if ($lcdproc_connect_errors >= $lcdproc_max_connect_errors) {
1765
	lcdproc_warn("Too many errors, stopping client.");
1766
}
1767
?>
(1-1/7)