Project

General

Profile

Feature #14625 » lcdproc_client.php

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

    
189
}
190

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

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

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

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

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

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

    
237
function get_interfaces_stats() {
238
	$ifstatus = [];
239
	$ifdescrs = get_configured_interface_with_descr();
240

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

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

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

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

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

    
340
function get_ipsec_stats() {
341
	global $sad;
342
	$sad = array();
343
	$sad = ipsec_dump_sad();
344

    
345
	$activecounter = 0;
346
	$inactivecounter = 0;
347

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

    
353
		$tun_disabled = "false";
354
		$foundsrc = false;
355
		$founddst = false;
356

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
552
		$result[$ifdescr] = $entry;
553
	}
554
	return $result;
555
}
556

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

    
562
	$result = array();
563
	$interfaceList = get_configured_interface_with_descr();
564

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

    
571
		calculate_interfaceBytesPerSecond_sinceLastChecked($interfaceName, $interfaceStats, $in_Bps, $out_Bps);
572
		calculate_bytesToday($interfaceName, $interfaceStats, $in_bytesToday, $out_bytesToday);
573

    
574
		$entry = array();
575
		$entry['descr']       = $description;
576

    
577
		$entry['in_Bps']      = $in_Bps;
578
		$entry['out_Bps']     = $out_Bps;
579
		$entry['total_Bps']   = $in_Bps + $out_Bps;
580

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

    
585
		$entry['in_bytes_today']    = $in_bytesToday;
586
		$entry['out_bytes_today']   = $out_bytesToday;
587
		$entry['total_bytes_today'] = $in_bytesToday + $out_bytesToday;
588

    
589
		$result[$interface['if']] = $entry;
590
	}
591
	return $result;
592
}
593

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

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

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

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

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

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

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

    
627
	global $traffic_last_ugmt, $traffic_last_ifin, $traffic_last_ifout;
628

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

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

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

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

    
646
	$hourOfDay = getdate()['hours'];
647

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

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

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

    
665
	$nameLength = $outputLength - strlen($speed);
666

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

    
676
	return $name . $speed;
677
}
678

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

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

    
695
	$showDecimalPlace = $unitSize < 10 && round($unitSize, 1) != round($unitSize);
696

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

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

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

    
717
	$showDecimalPlace = $unitSpeed < 10 && round($unitSpeed, 1) != round($unitSpeed);
718

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

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

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

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

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

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

    
747
	$interfaceEntry = $interface_traffic_list[$realif];
748

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

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

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

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

    
771
function get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width) {
772
	$result = [];
773

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

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

    
790
function get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width) {
791
	$result = [];
792

    
793
	sort_interface_list_by_total_bytes($interfaceTrafficList);
794

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

    
801

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

    
809
	if ($bytes_string == "0.00") {
810
		return "0";
811
	}
812

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

    
826
function get_bandwidth_by_ip() {
827
	$result       = [];
828

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

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

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

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

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

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

    
870
	return $result;
871
}
872

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

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

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

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

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

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

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

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

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

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

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

    
1218
function loop_status($lcd) {
1219
	global $g;
1220
	global $lcdproc_connect_errors;
1221
	$lcdproc_screens_config = config_get_path('installedpackages/lcdprocscreens/config/0', []);
1222
	$lcdpanel_width = get_lcdpanel_width();
1223
	$lcdpanel_height = get_lcdpanel_height();
1224
	if (empty($g['product_name'])) {
1225
		$g['product_name'] = "pfSense";
1226
	}
1227

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

    
1249
		$lcd_cmds = array();
1250
		$interfaceTrafficList = null;
1251
		$ifLinkList = null;
1252
		$gateway_status = null;
1253

    
1254
		/* initializes the widget counter */
1255
		$widget_counter = 0;
1256

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

    
1303
		/* process screens to display */
1304
		foreach ($lcdproc_screens_config as $name => $screen) {
1305
			if (($screen != "on") && ($screen != "yes")) {
1306
				continue;
1307
			}
1308

    
1309
			$updateSummary = true;
1310

    
1311
			switch($name) {
1312
				case "scr_version":
1313
					$version = get_version();
1314
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$version}\"";
1315
					break;
1316
				case "scr_time":
1317
					$time = date("n/j/Y H:i");
1318
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$time}\"";
1319
					break;
1320
				case "scr_uptime":
1321
					$uptime = get_uptime_stats();
1322
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$uptime}\"";
1323
					break;
1324
				case "scr_hostname":
1325
					exec("/bin/hostname", $output, $ret);
1326
					$hostname = $output[0];
1327
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$hostname}\"";
1328
					break;
1329
				case "scr_system":
1330
					$processor = lcdproc_cpu_usage();
1331
					$memory = mem_usage();
1332
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"CPU {$processor}%, Mem {$memory}%\"";
1333
					break;
1334
				case "scr_disk":
1335
					$disk = disk_usage();
1336
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Disk {$disk}%\"";
1337
					break;
1338
				case "scr_load":
1339
					$loadavg = get_loadavg_stats();
1340
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$loadavg}\"";
1341
					break;
1342
				case "scr_states":
1343
					$states = get_pfstate();
1344
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Cur/Max {$states}\"";
1345
					break;
1346
				case "scr_carp":
1347
					$carp = get_carp_stats();
1348
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$carp}\"";
1349
					break;
1350
				case "scr_ipsec":
1351
					$ipsec = get_ipsec_stats();
1352
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$ipsec}\"";
1353
					break;
1354
				case "scr_interfaces":
1355
					$interfaces = get_interfaces_stats();
1356
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$interfaces}\"";
1357
					break;
1358
				case "scr_gwsum":
1359
					if ($gateway_status === null) {
1360
						$gateway_status = return_gateways_status(true);
1361
					}
1362
					$gwup = 0;
1363
					$gwdown = 0;
1364
					foreach ($gateway_status as $idx => $gw) {
1365
						if ($gw['status'] == 'online') {
1366
							$gwup += 1;
1367
						} else {
1368
							$gwdown += 1;
1369
						}
1370
					}
1371
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Up: {$gwup} / Down: {$gwdown}\"";
1372
					break;
1373
				case "scr_mbuf":
1374
					$mbufstats = lcdproc_get_mbuf_stats();
1375
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$mbufstats}\"";
1376
					break;
1377
				case "scr_packages":
1378
					$packages = lcdproc_get_package_summary();
1379
					$title = ($lcdpanel_width >= 20) ? "Installed Packages" : "Packages";
1380
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1381
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$packages}\"";
1382
					break;
1383
				case "scr_cpufrequency":
1384
					$cpufreq = get_cpufrequency();
1385
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cpufreq}\"";
1386
					break;
1387
				case "scr_cputemperature":
1388
					$cputemperature = lcdproc_get_cpu_temperature();
1389
					$title = ($lcdpanel_width >= 20) ? "CPU Temperature" : "CPU Temp";
1390
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$title}\"";
1391
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"{$cputemperature}\"";
1392
					break;
1393
				case "scr_ntp":
1394
					$ntpq_output = lcdproc_get_ntp_status();
1395
					
1396
					if ($ntpq_output != false) {
1397
						$ntpq_counter = 0;
1398
						foreach ($ntpq_output as $line) {
1399
							if (substr($line, 0, 1) == "*") {
1400
								//Active NTP Peer
1401
								$line = substr($line, 1);
1402
								$peerinfo = preg_split("/[\s\t]+/", $line);
1403
								if ($peerinfo[2] == "0") {
1404
									// 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
1405
									$gps_sat_count = lcdproc_get_ntp_gps_sat_count();
1406
									$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}") . "\"";
1407
									$lcd_cmds[] = "widget_set {$name} delay_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Delay: {$peerinfo[7]}\"";
1408
									$lcd_cmds[] = "widget_set {$name} offset_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"Offset: {$peerinfo[8]}\"";
1409
									$lcd_cmds[] = "widget_set {$name} jitter_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1410
								} else {
1411
									// Show IP of the source and the stratum
1412
									$lcd_cmds[] = "widget_set {$name} source_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"{$peerinfo[0]} (stratum {$peerinfo[2]})\"";
1413
									$lcd_cmds[] = "widget_set {$name} delay_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Delay: {$peerinfo[7]}\"";
1414
									$lcd_cmds[] = "widget_set {$name} offset_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"Offset: {$peerinfo[8]}\"";
1415
									$lcd_cmds[] = "widget_set {$name} jitter_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1416
								}
1417
								$ntpq_counter++;
1418
							} elseif (substr($line, 0, 1) == "o") {
1419
								//Local PPS Peer
1420
								$line = substr($line, 1);
1421
								$peerinfo = preg_split("/[\s\t]+/", $line);
1422
								$lcd_cmds[] = "widget_set {$name} source_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"{$peerinfo[1]} (stratum {$peerinfo[2]}, PPS)\"";
1423
								$lcd_cmds[] = "widget_set {$name} delay_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"Delay: {$peerinfo[7]}\"";
1424
								$lcd_cmds[] = "widget_set {$name} offset_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"Offset: {$peerinfo[8]}\"";
1425
								$lcd_cmds[] = "widget_set {$name} jitter_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"Jitter: {$peerinfo[9]}\"";
1426
								$ntpq_counter++;
1427
							}
1428
						}
1429
						if ($ntpq_counter == 0) {
1430
							$lcd_cmds[] = "widget_set {$name} source_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"No active peers available\"";
1431
							$lcd_cmds[] = "widget_set {$name} delay_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"\"";
1432
							$lcd_cmds[] = "widget_set {$name} offset_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"\"";
1433
							$lcd_cmds[] = "widget_set {$name} jitter_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"\"";
1434
						} 
1435
					} else {
1436
						$lcd_cmds[] = "widget_set {$name} source_wdgt 1 1 {$lcdpanel_width} 2 h 4 \"NTP Server is Disabled\"";
1437
						$lcd_cmds[] = "widget_set {$name} delay_wdgt 1 2 {$lcdpanel_width} 2 h 4 \"\"";
1438
						$lcd_cmds[] = "widget_set {$name} offset_wdgt 1 3 {$lcdpanel_width} 2 h 4 \"\"";
1439
						$lcd_cmds[] = "widget_set {$name} jitter_wdgt 1 4 {$lcdpanel_width} 2 h 4 \"\"";
1440
					}
1441

    
1442
					$updateSummary = false;
1443
					break;				
1444
				case "scr_traffic":
1445
					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
1446
					get_traffic_stats($interfaceTrafficList, $in_data, $out_data);
1447
					$lcd_cmds[] = "widget_set {$name} title_wdgt 1 1 \"{$in_data}\"";
1448
					$lcd_cmds[] = "widget_set {$name} text_wdgt 1 2 \"{$out_data}\"";
1449
					break;
1450
				case "scr_top_interfaces_by_bps":
1451
					if ($interfaceTrafficList == null) {
1452
						// We only want build_interface_traffic_stats_list() to be called once per loop, and only if it's needed
1453
						$interfaceTrafficList = build_interface_traffic_stats_list();
1454
					}
1455
					$interfaceTrafficStrings = get_top_interfaces_by_bps($interfaceTrafficList, $lcdpanel_width, $lcdpanel_height);
1456

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

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

    
1462
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1463
					}
1464
					$updateSummary = false;
1465
					break;
1466
				case "scr_top_interfaces_by_bytes_today":
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
					$interfaceTrafficStrings = get_top_interfaces_by_bytes_today($interfaceTrafficList, $lcdpanel_width);
1469

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

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

    
1475
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1476
					}
1477
					$updateSummary = false;
1478
					break;
1479
				case "scr_top_interfaces_by_total_bytes":
1480
					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
1481
					$interfaceTrafficStrings = get_top_interfaces_by_total_bytes($interfaceTrafficList, $lcdpanel_width);
1482

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

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

    
1488
						$lcd_cmds[] = "widget_set {$name} text_wdgt{$i} 1 " . ($i + 2) . " \"{$interfaceTrafficStrings[$i]}\"";
1489
					}
1490
					$updateSummary = false;
1491
					break;
1492
				case "scr_gwstatus":
1493
					if ($gateway_status === null) {
1494
						$gateway_status = return_gateways_status(true);
1495
					}
1496
					foreach ($gateway_status as $gwname => $gw) {
1497
						$s_name = $name . $gwname;
1498
						$lcd_cmds[] = "widget_set {$s_name} gwname_wdgt 1 1 \"{$gwname}\"";
1499

    
1500
						if ($gw['monitor_disable']) {
1501
							$gw['substatus'] = 'assumed';
1502
							$gw['loss'] = 'Disabled';
1503
							$gw['delay'] = 'Disabled';
1504
						}
1505
						$statstring = ucwords($gw['status']);
1506
						if (!empty($gw['substatus']) &&
1507
						    ($gw['substatus'] != "none")) {
1508
							$statstring .= " ({$gw['substatus']})";
1509
						}
1510
						$lcd_cmds[] = "widget_set $s_name stata_wdgt 1 2 " .
1511
							$lcdpanel_width . " 2 h 4 \"" .
1512
							$statstring . "\"";
1513

    
1514
						$lcd_cmds[] = "widget_set $s_name lossa_wdgt 7 3 " .
1515
							$lcdpanel_width . " 3 h 4 \"" .
1516
							$gw['loss'] . "\"";
1517

    
1518
						$lcd_cmds[] = "widget_set $s_name rtta_wdgt 8 4 " .
1519
							$lcdpanel_width . " 4 h 4 \"" .
1520
							$gw['delay'] . "\"";
1521
					}
1522
					$updateSummary = false;
1523
					break;
1524
				case "scr_interfaces_link":
1525
					// We only want build_interface_link_list() to be
1526
					// called once per loop, and only if it's needed
1527
					if ($ifLinkList == null) {
1528
						$ifLinkList = build_interface_link_list();
1529
					}
1530

    
1531
					foreach ($ifLinkList as $ifdescr => $iflink) {
1532
						$s_name = $name . $ifdescr;
1533
						$ifname = $iflink['name'] . ":";
1534
						$l_str = ($iflink['status'] == "down") ? "down" : $iflink['link'];
1535

    
1536
						$lcd_cmds[] = "widget_set $s_name ifname_wdgt 1 1 \"$ifname\"";
1537

    
1538
						$lcd_cmds[] = "widget_set $s_name link_wdgt " .
1539
							(strlen($iflink['name']) + 3) . " 1 " .
1540
							$lcdpanel_width . " 1 h 4 \"" . $l_str . "\"";
1541

    
1542
						$lcd_cmds[] = "widget_set $s_name v4a_wdgt 5 2 " .
1543
							$lcdpanel_width . " 2 h 4 \"" .
1544
							$iflink['v4addr'] . "\"";
1545

    
1546
						$lcd_cmds[] = "widget_set $s_name v6a_wdgt 5 3 " .
1547
							$lcdpanel_width . " 3 h 4 \"" .
1548
							$iflink['v6addr'] . "\"";
1549

    
1550
						$lcd_cmds[] = "widget_set $s_name maca_wdgt 4 4 " .
1551
							$lcdpanel_width . " 4 h 4 \"" .
1552
							$iflink['mac'] . "\"";
1553
					}
1554
					$updateSummary = false;
1555
					break;
1556
				case "scr_traffic_by_address":
1557
					$title = ($lcdpanel_width >= 20) ? "Host       IN / OUT" : "Host   IN / OUT";
1558
					$lcd_cmds[] = "widget_set {$name} title_wdgt 2 1 \"{$title}\"";
1559
					$lcd_cmds[] = "widget_set {$name} heart_wdgt 1 1 \"" . (($loopCounter & 1) == 0 ? "HEART_OPEN" : "HEART_FILLED") . "\""; // Indicate each time the list has been updated
1560

    
1561
					$traffic = get_bandwidth_by_ip();
1562
					$clearLinesFrom = 0;
1563

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

    
1616
						$lcdpanel_height = get_lcdpanel_height();
1617
						$lcdpanel_width = get_lcdpanel_width();
1618

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

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

    
1674
						$lcdpanel_height = get_lcdpanel_height();
1675
						$lcdpanel_width = get_lcdpanel_width();
1676

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

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

    
1727
/* Initialize the wan traffic counters */
1728
$traffic_last_ugmt  = array();
1729
$traffic_last_ifin  = array();
1730
$traffic_last_ifout = array();
1731

    
1732
$traffic_last_hour        = array();
1733
$traffic_startOfDay_ifin  = array();
1734
$traffic_startOfDay_ifout = array();
1735

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