#!c:/perl/bin/perl.exe
#!c:/xampp/perl/bin/perl.exe
#!/usr/bin/perl

use DBI;
use POSIX;
use Digest::MD5 qw(md5 md5_hex md5_base64);
use Time::Local;
use strict;

# get current datetime

my ($cursec,$curmin,$curhour,$curday,$curmon,$curyear) = (localtime)[0,1,2,3,4,5];
my $loadtime = time();
$curmon ++;
$curday = sprintf("%02d",$curday);
$curmon = sprintf("%02d",$curmon);
$cursec = sprintf("%02d",$cursec);
$curmin = sprintf("%02d",$curmin);
$curhour = sprintf("%02d",$curhour);
$curyear += 1900;
my $curdatetime = "$curyear-$curmon-$curday $curhour:$curmin:$cursec";
my $curampm = 1;
if ($curhour > 11) {
	$curampm ++;	# 1 - AM, 2 - PM
}

# Get data from memory

my %FORM = ();
my $submeth = "post";
my $forlog = "";
unless (exists($FORM{"testnoenv"})) {
	my $bufer = "";
	if ($ENV{'REQUEST_METHOD'} eq "POST") {
		read(STDIN, $bufer, $ENV{'CONTENT_LENGTH'});
		$submeth = "post";
	} else {
		$bufer=$ENV{'QUERY_STRING'};
		$submeth = "get";
	}

	my @pairs = split(/&/, $bufer);

	foreach my $pair (@pairs)
	{
		if ($pair =~ m/^key\=([0-9A-Za-z\/\+\=]+)$/) {			# inject session
			$FORM{"key"} = $1;
			next;
		}
		my ($name, $value) = split(/=/, $pair);
		$name =~ tr/+/ /;
		$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ tr/+/ /;
		$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ s/[\\\'\"\`\%]/\ /g;
		if (($name =~ m/^multi/) && (exists $FORM{$name})) {		# fix for multiple selections
			$FORM{$name} .= ",".$value;
		} else {
			$FORM{$name} = $value;
		}
		$forlog .= "$curdatetime : $name - $value<br>\n";
	}
}

# get server data

my $selfpath = $ENV{'PATH_TRANSLATED'};
$selfpath =~ s/\\[^\\]*$/\\/;
if ($selfpath eq "") {
	$selfpath = $ENV{'SCRIPT_FILENAME'};
	$selfpath =~ s/\/[^\/]*$/\//;
}
my $templateweb = $selfpath."template.html";
my $loginweb = $selfpath."login.html";
my $eloginweb = $selfpath."elogin.html";
my $policyweb = $selfpath."policy.html";
my $upfolder = $selfpath."updates";
my $repfolder = $selfpath."connector/charts";
my $nrepfolder = $selfpath."charts";

# read config

my %config = ();
my $confile = $selfpath."settings.cnf";
if (-e $confile) {
	open(INF,$confile);
	while(<INF>) {
		my $inline = $_;
		chomp($inline);
		if ($inline =~ m/^[a-zA-Z]+/) {
			my ($name,$value) = split(/\=/,$inline);
			$name =~ s/^[\s\t]*//;
			$value =~ s/^[\s\t]*//;
			$name =~ s/[\s\t]*$//;
			$value =~ s/[\s\t]*$//;
			$config{lc($name)} = $value;
		}
	}
	close(INF);
}

# constants from config

my $version = (exists $config{version})?$config{version}:"16.10.28.0";
my $debugmode = (exists $config{debug})?$config{debug}:0;		# simulation mode off by default
my $advmode = (exists $config{advanced})?$config{advanced}:1;		# corrections allowed
my $logpath = (exists $config{logpath})?$config{logpath}:"./";		# path for storing logs and private files
my $eccc = (exists $config{eccc})?$config{eccc}:0;			# eccc govt server

# hardcoded constants and moar

my $top1class = "Top1";
my @dayofweek = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday");
my @weekofmonth = ("Ololo", "First", "Second", "Third", "Fourth", "Fifth", "Last");
my @weeksofmonth = ("Ololo", "1st", "2nd", "3rd", "4th", "5th", "last");
my @lunardates = ("Easter (Gregorian)", "Easter (Orthodox)", "Easter (Julian)");
my @months = ("Ololo","January","February","March","April","May","June","July","August","September","October","November","December");
my @smonths = ("Ololo","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
my @monthtxt = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
my @sdayofweek = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
my @ampms = ("USSR","AM","PM");
my $exitstatus = 0;				# status to exit to login page
our $rreptype = "";
my $sessid = -1;
my $myrepkey = '0hMyKey)';
my $clientip = $ENV{'REMOTE_ADDR'};
my $clientie = $ENV{'HTTP_USER_AGENT'};
my $username = $FORM{user};
my $password = $FORM{pass};
my $userhash = md5_hex($clientip."azze2014".$clientie);
my $cookname = "";
my $rcvd_cookies = $ENV{'HTTP_COOKIE'};
my @cookies = split /;/, $rcvd_cookies;
my $saveduser = "";
my $cusermode = 0;
my @cooknames = ("cloudsession2014", "clouduser2014", "cloudmode2014", "cicsession2014", "cichomeid2014");
if ($eccc) {
	@cooknames = ("ecccsession2014", "ecccuser2014", "ecccmode2014", "ecicsession2014", "ecichomeid2014");
}
foreach my $cookie (@cookies) {
	if ($cookie =~ $cooknames[0]) {
		($cookname,$sessid) = split(/\=/,$cookie);
	}
	if ($cookie =~ $cooknames[1]) {
		($cookname,$saveduser) = split(/\=/,$cookie);
	}
	if ($cookie =~ $cooknames[2]) {
		($cookname,$cusermode) = split(/\=/,$cookie);
	}
}
my $signtime = 60;		# time in minutes to stay logged in
my $forkme = 0;
my $contents = "";
my $bodyadd = "";
my $bottomadd = "";
my $headadd = "";
my $debug = "";
my ($message, $messsage) = ("", "");
my ($policymsg, $fpolicymsg) = ("", "");
my $servname = $ENV{'SERVER_NAME'};
my $servport = $ENV{'SERVER_PORT'};
my $servprot = (($ENV{'HTTPS'} eq "on") || ($ENV{"REQUEST_SCHEME"} eq "https"))?"https":"http";
if (($servprot eq "http") && !($clientip =~ m/^192\.168/)) {		# http for local only
	print "Content-type: text/html\n\n";
	print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=https://$servname/\"></HEAD>\n";
	exit;
}
unless (($servport eq "80") || ($servport eq "443")) {
	$servname .= ":".$servport;
}
my $foldname = "";
if ($ENV{'SCRIPT_NAME'} =~ /^\/(.+\/)*(.+)\.(.+)$/) {
	$foldname = $1;	
}
$forlog .= "$curdatetime : $clientip - $clientie\n";
my $connweb = $servprot."://".$servname."/connector/engine.pl";

# connect to mysql
 
my $dsn = 'DBI:mysql:'.$config{dbname}.":".$config{dbhost};
my $db_user_name = $config{dbuser};
my $db_password = $config{dbpass};
my $db = DBI->connect($dsn, $db_user_name, $db_password);
if (! $db) {
	($username, $password, $FORM{mode}, $FORM{submode}) = ("", "", "", "");
	$exitstatus = 7;
}

# get mode and action

my $savelogin = ($FORM{save_login} eq "yes")?"yes":"no";
my $uimode = (exists $FORM{mode})?$FORM{mode}:"";
my $uismode = (exists $FORM{submode})?$FORM{submode}:"";
my $action = (exists $FORM{action})?$FORM{action}:"";
my $subact = (exists $FORM{subact})?$FORM{subact}:"";
my $airdamper = (exists $FORM{airdamper})?$FORM{airdamper}:"";
my $pagetitle = "Building Automation System";
if ($servname =~ m/^residential/) {
	$airdamper = "yes";
} elsif ($servname =~ m/^commercial/) {
	$airdamper = "";
}
$airdamper = "";
if ($airdamper eq "yes") {
	$pagetitle = "Cello Forced Air Damper Control";
}

# version control

if ($eccc) {
	my ($clover) = $db->selectrow_array("SELECT current FROM cloud2014.versions WHERE module = 'server'");
	if ($clover ne "") {
		$version = $clover;
	}
}

# policy checker

if (($action eq "policy") && ($FORM{"session"} ne "")) {
	my $session = $FORM{"session"};
	($username, $password) = $db->selectrow_array("SELECT guser, gpass FROM gusers WHERE ghash = '$session'");
	$db->do("DELETE FROM gusers WHERE ghash = '$session'");
	if ((exists $FORM{"iagree"}) || (exists $FORM{"fagree"})) {
		if ($username ne "") {
			$db->do("INSERT INTO gusers VALUES (NULL, '$username', NULL, NULL, 1)");			# insert permanent record
		}
	} else {
		$policymsg = "You must accept policy to continue";
		$fpolicymsg = "Vous devez accepter les termes et conditions avant de continuer";
	}
	$submeth = "post";
	$action = "login";
}

# password reset for damper customers

if (($uimode eq "password") && ($uismode eq "reset")) {
	my %hiders = ("preset", "0");
	my $button = "<input name=\"return\" value=\"Return to login page\" class=\"stdbutton\" onclick=\"window.location.href='./engine.pl?airdamper=$airdamper';\" type=\"button\">";
	my $message = "Invalid request!<br><br>";
	my $ureq = (exists $FORM{"request"})?$FORM{"request"}:"";
	if ($action eq "complete") {
		my $upass = (exists $FORM{"upass"})?$FORM{"upass"}:"";
		if (length($upass) < 6) {
			my ($email) = $db->selectrow_array("SELECT email FROM esp_users WHERE password = '$ureq'");
			$message = "New password too short!<br><br>Password reset for customer <b>$email</b><br>New password must be at least 6 characters long<br><br>";
			$hiders{'preset'} = 1;
			$button = "<input name=\"login\" value=\"Complete\" class=\"stdbutton\" onclick=\"this.submit();\" type=\"SUBMIT\">";
		} else {
			my ($email) = $db->selectrow_array("SELECT email FROM esp_users WHERE password = '$ureq'");
			$message = "Password reset complete for customer <b>$email</b><br><br>";
			$db->do("UPDATE esp_users SET updated = NOW(), password = MD5('$upass') WHERE password = '$ureq'");
		}
	} else {
		if ($ureq =~ m/^[a-z0-9A-Z]{32}$/) {
			my ($email) = $db->selectrow_array("SELECT email FROM esp_users WHERE password = '$ureq'");
			$message = "Password reset for customer <b>$email</b><br>New password must be at least 6 characters long<br><br>";
			$hiders{'preset'} = 1;
			$button = "<input name=\"login\" value=\"Complete\" class=\"stdbutton\" onclick=\"this.submit();\" type=\"SUBMIT\">";
		}
	}
	print "Content-type: text/html\n\n";
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	my $hidenow = 0;
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--airdamper--/$airdamper/g;
		$inline =~ s/--title--/$pagetitle/g;
		$inline =~ s/--request--/$ureq/g;
		$inline =~ s/--button--/$button/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$inline =~ s/--version--/$version/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			print $inline."\n";
		}
	}
	close(INF);
	$db->disconnect();
	exit;
}

# password recovery

if (($uimode eq "password") && ($uismode eq "recovery")) {
	my $ulogin = (exists $FORM{"ulogin"})?$FORM{"ulogin"}:"";
	my ($message, $button) = ("", "");
	print "Content-type: text/html\n\n";
	if ($action eq "start") {				# start recovery
		if ($airdamper eq "yes") {
			if ($ulogin =~ m/^\w[\w\.\-]*\w\@\w[\w\.\-]*\w(\.\w{2,4})$/) {					# email only
				$db->do("INSERT INTO gusers (id, guser, status) VALUES (NULL, '$ulogin', 8)");		# recover air customer pass
				$message = "Request pending. Please check your mailbox in a minute<br>&nbsp;";
				$button = "<input name=\"return\" value=\"Return to login page\" class=\"stdbutton\" onclick=\"window.location.href='./engine.pl?airdamper=yes';\" type=\"button\">";
			}
		} else {
			if (($ulogin =~ m/^(.+)\@(\d+)$/) || ($ulogin =~ m/^\w[\w\.\-]*\w\@\w[\w\.\-]*\w(\.\w{2,4})$/)) {		# user or email
				$db->do("INSERT INTO gusers (id, guser, status) VALUES (NULL, '$ulogin', 4)");		# recover cloud user pass
				$message = "Request pending. Please check your mailbox in a minute<br>&nbsp;";
				$button = "<input name=\"return\" value=\"Return to login page\" class=\"stdbutton\" onclick=\"window.location.href='./engine.pl';\" type=\"button\">";
			} else {
				my ($uid) = $db->selectrow_array("SELECT id FROM users WHERE login='$ulogin' AND access IN (1,2)");
				if ($uid) {
					$db->do("INSERT INTO gusers (id, guser, status) VALUES (NULL, '$ulogin', 4)");		# recover admin user pass
					$message = "Request pending. Please check your mailbox in a minute<br>&nbsp;";
					$button = "<input name=\"return\" value=\"Return to login page\" class=\"stdbutton\" onclick=\"window.location.href='./engine.pl';\" type=\"button\">";
				} else {
					$message = "Username or email not found or account inactive<br>&nbsp;";
					$button = "<input name=\"return\" value=\"Return to login page\" class=\"stdbutton\" onclick=\"window.location.href='./engine.pl';\" type=\"button\">";
				}
			}
		}
	}
	if ($message eq "") {
		if ($airdamper eq "yes") {
			$message = "Enter your email address in form below.<br>Password will be sent to your registration email<br>&nbsp;";
		} else {
			$message = "Enter your username or email address in form below.<br>Password will be sent to email associated with username<br>&nbsp;";
		}
		$button = "<input name=\"login\" value=\"Proceed\" class=\"stdbutton\" onclick=\"this.submit();\" type=\"SUBMIT\">";
	}
	my $prompt = ($airdamper eq "yes")?"Registration email":"Username or email";
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--airdamper--/$airdamper/g;
		$inline =~ s/--prompt--/$prompt/g;
		$inline =~ s/--title--/$pagetitle/g;
		$inline =~ s/--button--/$button/g;
		$inline =~ s/--ulogin--/$ulogin/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$inline =~ s/--version--/$version/g;
		print $inline."\n";
	}
	close(INF);
	$db->disconnect();
	exit;
}

# Session creator

our $clientid = -1;
my $clientacc = 0;
my $tempdbid = 0;
if (($username ne "") && ($password ne "") && ($submeth eq "post") && ($action eq "login")) {
	my $apolicy = 0;
	{
		my $sth = $db->prepare("SELECT status FROM gusers WHERE guser = '$username' AND status > 0");
		$sth->execute;
		($apolicy) = $sth->fetchrow_array();
		$sth->finish;
		$apolicy += 0;
	}
	if (($apolicy == 1) && ($username =~ m/^\w[\w\.\-]*\w\@\w[\w\.\-]*\w(\.\w{2,4})$/) && ($airdamper eq "yes")) {		# email only for damper customer
		my $pss = md5_hex($password);
		my $sth = $db->prepare("SELECT id, flags FROM esp_users WHERE email = '$username' and password = '$pss'");
		$sth->execute;
		unless ($sth->rows == 0) {
			my ($id, $flags) = $sth->fetchrow_array();
			if ($flags > 0) {
				$clientid = $id;
			}
		}
		$sth->finish;

		if ($clientid >= 0) {
			$db->do("INSERT INTO sessions VALUES (NULL, $clientid, '$userhash', NOW(), DATE_ADD(NOW(),INTERVAL $signtime MINUTE), 3, 0)");		# 3 = air damper cust
			$sth = $db->prepare("SELECT last_insert_id() FROM sessions");
			$sth->execute;
			($sessid) = $sth->fetchrow_array();
			$sth->finish;
		} else {
			$exitstatus = 1;
		}

		my $fut_time = gmtime(time() + (60 * 60 * 24 * 30))." GMT";  	# cookie expires in 30 days
		my $cookie = $cooknames[0]."=$sessid; path=/; expires=$fut_time;";
		print "Set-Cookie: " . $cookie . "\n";
		if (exists $FORM{savelogin}) {
			$cookie = $cooknames[1]."=$username; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";
		}
	} elsif (($apolicy == 1) && ($username =~ m/^(.+)\@(\d+)$/)) {					# check if domain entered & policy accepted
		my $rusername = $1;				# remote user
		my $homeid = sprintf("%05d",$2);	# remote homeID
		my $rdsn = "DBI:mysql:smart".$homeid.":".$config{dbhost};
		my $rdbuser = "dbuser".$homeid;
		my $rdbpass = "dbpass".$homeid;
		my $rdb = DBI->connect($rdsn, $rdbuser, $rdbpass);
		if (! $rdb) {
			($username, $password, $FORM{mode}, $FORM{submode}) = ("", "", "", "");
			$exitstatus = 7;
		} else {
			my $sth = $rdb->prepare("SELECT id,access,login FROM users WHERE login='$rusername' and password LIKE BINARY '$password' AND id > 1");
			$sth->execute;
			unless ($sth->rows == 0) {
				my ($id,$access,$login) = $sth->fetchrow_array();
				if (($access == 1) || ($access == 0)) {			# simple user or integrator
					$clientid = $id;
					$clientacc = $access;
				} elsif ($access == 2) {				# system super admin
					$clientid = $id;
					$clientacc = $access;
				}
				$sth->finish;
			} else {
				$sth->finish;
			}

			if ($clientid >= 0) {
				$rdb->do("INSERT INTO sessions VALUES(NULL,$clientid,'$userhash',now(),date_add(now(),interval $signtime minute),$clientacc,0)");
				my $sth = $rdb->prepare("SELECT last_insert_id() FROM sessions");
				$sth->execute;
				($sessid) = $sth->fetchrow_array();
				$sth->finish;
			} else {
				$exitstatus = 1;
			}

			my $fut_time = gmtime(time() + (60 * 60 * 24 * 30))." GMT";  	# cookie expires in 30 days
			my $cookie = $cooknames[3]."=$sessid; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";
			$cookie = $cooknames[4]."=$homeid; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";

			print "Content-type: text/html\n\n";
			print "<HEAD>\n";
			print "<META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$connweb\">\n";
			print "</HEAD>\n";
			$rdb->disconnect();
			$db->disconnect();
			exit;
		}
	} elsif ($apolicy == 1) {
		my $sth = $db->prepare("select id,access,login from users where login='$username' and password LIKE BINARY '$password' AND id > 1");
		$sth->execute;
		unless ($sth->rows == 0) {
			my ($id,$access,$login) = $sth->fetchrow_array();
			if (($access == 1) || ($access == 0)) {			# simple user or integrator
				$clientid = $id;
				$clientacc = $access;
			} elsif ($access == 2) {				# system super admin
				$clientid = $id;
				$clientacc = $access;
			}
			$sth->finish;
		} else {
			$sth->finish;
		}

		if ($clientid >= 0) {
			$db->do("INSERT INTO sessions VALUES(NULL,$clientid,'$userhash',now(),date_add(now(),interval $signtime minute),$clientacc,0)");
			$sth = $db->prepare("SELECT last_insert_id() FROM sessions");
			$sth->execute;
			($sessid) = $sth->fetchrow_array();
			$sth->finish;
		} else {
			$exitstatus = 1;
		}

		my $fut_time = gmtime(time() + (60 * 60 * 24 * 30))." GMT";  	# cookie expires in 30 days
		my $cookie = $cooknames[0]."=$sessid; path=/; expires=$fut_time;";
		print "Set-Cookie: " . $cookie . "\n";
		if (exists $FORM{savelogin}) {
			$cookie = $cooknames[1]."=$username; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";
		}
	} else {
		my $session = md5_hex($username."policy2016".$password);
		$db->do("DELETE FROM gusers WHERE guser = '$username' OR ghash = '$session'");
		$db->do("INSERT INTO gusers VALUES (NULL, '$username', '$password', '$session', 2)");
		print "Content-type: text/html\n\n";
		open(INF,$policyweb);
		while (<INF>) {
			my $inline = $_;
			chomp ($inline);
			$inline =~ s/--error--/$policymsg/g;
			$inline =~ s/--ferror--/$fpolicymsg/g;
			$inline =~ s/--session--/$session/g;
			$inline =~ s/--airdamper--/$airdamper/g;
			$inline =~ s/--version--/$version/g;
			$inline =~ s/--title--/$pagetitle/g;
			print $inline."\n";
		}
		close(INF);
		$db->disconnect();
		exit;
	}
}

# Reports tool fix

if (($uimode eq "reports") && ($uismode eq "access")) {
	my $makesess = 0;
	if ($FORM{"key"} ne "") {
#		$debug = $FORM{"key"};
		my ($decoded) = $db->selectrow_array("SELECT AES_DECRYPT(FROM_BASE64('".$FORM{"key"}."'), '$myrepkey')");
		if (($decoded ne "") && ($decoded ne "NULL")) {
			my @data = split(/\&/, $decoded);
			foreach my $dd (@data) {
				my ($key, $val) = split(/\=/, $dd);
				$FORM{$key} = $val;			# session injection
			}
			$uimode = $FORM{"mode"};
			$uismode = $FORM{"submode"};
			$action = $FORM{"action"};
			$subact = $FORM{"subact"};
			if ((($uimode eq "reports") && ($uismode eq "graph")) || (($uimode eq "reports") && ($uismode eq "zones") && ($action eq "download"))) {
				$makesess = 1;
			}
		}
	}
	if ($makesess) {		# create quick session for some action
		$db->do("INSERT INTO sessions VALUES (NULL, 1, '$userhash', NOW(), DATE_ADD(NOW(), INTERVAL 1 MINUTE), 1, 0)");
		($sessid) = $db->selectrow_array("SELECT last_insert_id() FROM sessions");
	}
}

# Partner tool fix

my $onestage = 0;
if (($username ne "") && ($password ne "") && ($submeth eq "get") && ($uimode eq "partners") && ($uismode eq "advreport")) {
	my $sth = $db->prepare("select id,access,login from users where login='$username' and password LIKE BINARY '$password' AND id > 1");
	$sth->execute;
	unless ($sth->rows == 0) {
		my ($id,$access,$login) = $sth->fetchrow_array();
		if (($access == 1) || ($access == 0)) {			# simple user or integrator
			$clientid = $id;
			$clientacc = $access;
		} elsif ($access == 2) {				# system super admin
			$clientid = $id;
			$clientacc = $access;
		}
		$sth->finish;
	} else {
		$sth->finish;
	}
	if ($clientid >= 0) {
		$db->do("INSERT INTO sessions VALUES(NULL,$clientid,'$userhash',now(),date_add(now(),interval $signtime minute),$clientacc,0)");
		$sth = $db->prepare("SELECT last_insert_id() FROM sessions");
		$sth->execute;
		($sessid) = $sth->fetchrow_array();
		$sth->finish;
		$onestage = 1;		# one stage auth allowed
	}
}

# Session checker

my $ulogin = "";
my $uaccess = 0;
my $sessionnow = 0;
my $housemask = "0";
my $uimenutab = "ui_menu";
my $utimezone = 33;		# UTC zone
my $sth = $db->prepare("SELECT id_session,id_client,type,dbid FROM sessions WHERE id_session=$sessid AND hash='$userhash' AND expires>NOW()");
$sth->execute;
unless ($sth->rows == 0) {
	my ($sessid,$clid,$clientacc,$odbid) = $sth->fetchrow_array();
	$sth->finish;
	$db->do("UPDATE sessions SET expires=DATE_ADD(expires,INTERVAL $signtime MINUTE) WHERE id_session=$sessid");
	$sessionnow = $sessid;

	if ($clientacc == 3) {					# air damper cust
		$airdamper = "yes";
		$pagetitle = "Cello Forced Air Damper Control";
		$uimenutab = "esp_ui_menu";
		$sth = $db->prepare("SELECT email, flags FROM esp_users WHERE id = $clid");
		$sth->execute;
		unless ($sth->rows == 0) {
			my ($login, $flags) = $sth->fetchrow_array();
			if ($flags > 0) {			# active account only
				$ulogin = $login;
				$uaccess = 0;
				$clientid = $clid;
			}
		}
		$sth->finish;
	} elsif ($clid == 1) {					# reports user
		$uaccess = 1;
		$ulogin = "reports";
		$clientid = $clid;
#		$onestage = 1;
#		$message = "Download complete";
	} else {
		$sth = $db->prepare("select login,access,houses,timezone from users where id=$clid");
		$sth->execute;
		unless ($sth->rows == 0) {
			my ($login,$access,$hmask,$tzone) = $sth->fetchrow_array();
			if ($access == 1) {
				$ulogin = $login;
				$uaccess = $access;
				$clientid = $clid;
				$housemask = $hmask;
			} elsif ($access == 2) {
				$ulogin = $login;
#				$uaccess = 1;			# granting admin access to system
				$uaccess = $access;
				$clientid = $clid;
			} elsif ($access == 0) {
				$ulogin = $login;
				$uaccess = $access;
				$clientid = $clid;
			}
			$utimezone = $tzone;
		}
		$sth->finish;
	}
} else {
	$clientid = -1;
	$sth->finish;
}

if ($clientid < 0) {
	($password, $uimode, $uismode) = ("", "", "");
	unless ($exitstatus > 0) {
		$exitstatus = 3;
	}
}
my ($uidefault, $uiallowed) = $db->selectrow_array("SELECT ui_default, ui_list FROM ui_access WHERE user_id = $clientid");
if (($clientid >= 0) && (($uimode eq "") || ($uismode eq ""))) {
	if ($airdamper eq "yes") {
		($uimode, $uismode) = ("customer", "customer");
		($uidefault, $uiallowed) = (1, "");			# allow all menu items
	} else {
		($uimode, $uismode) = $db->selectrow_array("SELECT menu, submenu FROM ui_menu WHERE id = $uidefault");
	}
} elsif (($clientid >= 0) && ($uimode ne "logout") && ($uiallowed =~ m/^\+(.+)$/)) {
	my $uifilter = "id IN ($1)";
	my ($alcnt) = $db->selectrow_array("SELECT COUNT(id) FROM ui_menu WHERE menu = '$uimode' AND submenu = '$uismode' AND level > 0 AND $uifilter");
	if ($alcnt == 0) {
		($uismode) = $db->selectrow_array("SELECT submenu FROM ui_menu WHERE menu = '$uimode' AND level > 0 AND $uifilter ORDER BY id DESC LIMIT 1");
	}
}

# read config for cloud

my %HVAC = ();
{	
	my $all = $db->selectall_arrayref("SELECT option_,value_ FROM cloud WHERE submenu > 0");		# read HVAC config for system only
	foreach my $row (@$all) {
		my ($opt, $val) = @$row;
		$HVAC{$opt} = $val;
	}
}

# read session data

my %SDATA = ();
$SDATA{save} = 0;
{
	my $all = $db->selectall_arrayref("SELECT id, data FROM session_data WHERE session_id = $sessid");		# read HVAC config for system only
	foreach my $row (@$all) {
		my ($sid, $sdat) = @$row;
		$SDATA{sid} = $sid;
		my @values = split(/\;\;/, $sdat);
		foreach my $vv (@values) {
			if ($vv ne "") {
				my @vpair = split(/\=\=/, $vv);
				$SDATA{$vpair[0]} = $vpair[1];
			}
		}
	}
}

# menu & submenu processing

my $mainmenu = "";
my $submenu = "";
my %alevel = ();
my $pageatitle = $pagetitle;
if ($uimode ne "") {
	my $uifilter = "1 = 1";
	if ($uiallowed =~ m/^\-(.+)$/) {
		$uifilter = "id NOT IN ($1)";
	} elsif ($uiallowed =~ m/^\+(.+)$/) {
		$uifilter = "id IN ($1)";
	}
	if (($clientid >= 0) && ($uimode eq "reports") && ($uismode eq "graph")) {
		if (exists $FORM{"repid"}) {
			$uifilter .= " OR id IN (94)";
		} else {
			$uismode = "zones";
			$uifilter .= " AND id NOT IN (94)";
		}
	} else {
		$uifilter .= " AND id NOT IN (94)";
	}
	my $all = $db->selectall_arrayref("SELECT id, menu, submenu, description, access, level FROM $uimenutab WHERE (level = 0 OR (menu = '$uimode' AND level = 1)) AND ($uifilter) ORDER BY id");	# get all main + current sub
	foreach my $row (@$all) {
		my ($meid, $imenu, $isubm, $idesc, $iacc, $mlevel) = @$row;
		$alevel{$imenu.$isubm} = $iacc;
		if ($uaccess >= $iacc) {				# show only if access allowed
			if ($mlevel == 0) {
				if ($imenu eq $uimode) {
					$mainmenu .= "<td nowrap=\"nowrap\"><div id=\"div_maintab_".$meid."\" class=\"MainTab\"><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL10\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL11\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL12\"></div></a><a class=\"MenuTabLink\" href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL13 ShadowText\">".$idesc."</div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL14\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL15\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL16\"></div></a></div></td>\n";
					$idesc =~ s/\<br\>//gi;
					$pagetitle .= " : $idesc";
				} else {
					$mainmenu .= "<td nowrap=\"nowrap\"><div id=\"div_maintab_".$meid."\" class=\"MainTab\" onmouseover=\"main_cap('div_maintab_".$meid."');\" onmouseout=\"main_uncap('div_maintab_".$meid."');\"><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL30\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL31\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL32\"></div></a><a class=\"MenuTabLink\" href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL33 ShadowText\">".$idesc."</div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL34\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL35\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"MainTabL36\"></div></a></div></td>\n";
				}
			} else {
				if ($isubm eq $uismode) {
					$submenu .= "<td nowrap=\"nowrap\"><div id=\"div_subtab_".$meid."\"><div class=\"SubTabL10\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL11\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL12\"></div></a><a class=\"MenuTabLink\" href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL13\">".$idesc."</div></a></div></td>\n";
					$idesc =~ s/\<br\>//gi;
					$pagetitle .= " : $idesc";
				} else {
					$submenu .= "<td nowrap=\"nowrap\"><div id=\"div_subtab_".$meid."\" class=\"SubTab\" onmouseover=\"sub_cap('div_subtab_".$meid."');\" onmouseout=\"sub_uncap('div_subtab_".$meid."');\"><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL30\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL31\"></div></a><a href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL32\"></div></a><a class=\"MenuTabLink\" href=\"./engine.pl?mode=$imenu&submode=$isubm\"><div class=\"SubTabL33\">".$idesc."</div></a></div></td>\n";
				}
			}
		}
	}
	$sth->finish;
}

# local timestamp with offsets

my $lcuryear = $curyear;
my $lcurmon = $curmon;
my $lcurday = $curday;
{
	my $tzone = getoffset();
	my $ttzone = sprintf("%+05d", $tzone);
	$ttzone =~ s/(...)(..)$/$1\:$2/;
	($lcuryear, $lcurmon, $lcurday) = $db->selectrow_array("SELECT YEAR(CONVERT_TZ(NOW(), '+00:00', '$ttzone')), MONTH(CONVERT_TZ(NOW(), '+00:00', '$ttzone')), DAY(CONVERT_TZ(NOW(), '+00:00', '$ttzone'))");
}

# database maintenance page OBSOLETE

if (($uimode eq "userinfo") && ($uismode eq "settings") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $syncmin = (exists $HVAC{"system.sync_min"})?$HVAC{"system.sync_min"}:1;
	my $syncpref = (exists $HVAC{"system.sync_pref"})?$HVAC{"system.sync_pref"}:0;
	my @tsyncpref = ("", "");

	if (($action eq "save") && (exists $FORM{sync_min}) && (exists $FORM{sync_pref})) {
		my $newsyncpref = $FORM{sync_pref} + 0;
		if ($syncpref != $newsyncpref) {
			$syncpref = $newsyncpref;
			$db->do("UPDATE cloud SET value_ = $syncpref WHERE option_ = 'system.sync_pref';");
		}
		my $newsyncmin = $FORM{sync_min} + 0;
		if (($syncmin != $newsyncmin) && ($newsyncmin > 0)) {
			$syncmin = $newsyncmin;
			$db->do("UPDATE cloud SET value_ = $syncmin WHERE option_ = 'system.sync_min';");
		}
	}
	$tsyncpref[$syncpref] = " checked=\"checked\"";

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--sync_min--/$syncmin/g;
		$inline =~ s/--sync_pref0--/$tsyncpref[0]/g;
		$inline =~ s/--sync_pref1--/$tsyncpref[1]/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# server status page

if (($uimode eq "userinfo") && ($uismode eq "status") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %tconv = ("00:00", "12am", "01:00", "1am", "02:00", "2am", "03:00", "3am", "04:00", "4am", "05:00", "5am", "06:00", "6am", "07:00", "7am", "08:00", "8am", "09:00", "9am", "10:00", "10am", "11:00", "11am", "12:00", "12pm", "13:00", "1pm", "14:00", "2pm", "15:00", "3pm", "16:00", "4pm", "17:00", "5pm", "18:00", "6pm", "19:00", "7pm", "20:00", "8pm", "21:00", "9pm", "22:00", "10pm", "23:00", "11pm");
	my ($dbstat, $upsstat, $hwstat, $ipstat, $swstat) = ("", "", "", "", "");
	my $tmpfold = $selfpath."/tmp/";
	if ($servport eq "8080") {		# local debug run
		$tmpfold = "E:/filebase/design/essi/ase-energy/git-2014/soft/webui/dnd cloud/tmp/";
	}
	my $dbfile = $tmpfold."mysql.status";
	my $hwfile = $tmpfold."system.status";
	my $ntpfile = $tmpfold."ntp.status";
	my $upsfile = $tmpfold."apc.status";

	my ($tback) = $db->selectrow_array("SELECT value_ FROM sysprop WHERE house_id = 0 AND name_ = 'db.backup'");
	my ($apcsvc) = $db->selectrow_array("SELECT value_ FROM sysprop WHERE house_id = 0 AND name_ = 'apcups.service'");
	my $dbblist = "";
	my $apcups = "";
	if ($action eq "save") {
		if (exists $FORM{dbback}) {
			$tback = $FORM{dbback};
			$db->do("UPDATE sysprop SET value_ = '$tback' WHERE house_id = 0 AND name_ = 'db.backup'");
		}
		if (exists $FORM{apcups}) {
			$apcsvc = $FORM{apcups};
			$db->do("UPDATE sysprop SET value_ = '$apcsvc' WHERE house_id = 0 AND name_ = 'apcups.service'");
		}
	} elsif (($action eq "upgrade") && (exists $FORM{upmod})) {
		my $upmod = $FORM{upmod};
		$db->do("UPDATE versions SET status = 1, updated = NOW() WHERE module = '$upmod'");
	} elsif (($action eq "clean") && (exists $FORM{upmod})) {
		my $upmod = $FORM{upmod};
		$db->do("UPDATE versions SET status = 0, updated = NOW() WHERE module = '$upmod'");
	}
	foreach my $tt (sort keys %tconv) {
		$dbblist .= "<option value=\"$tt\" ".(($tt eq $tback)?"selected=\"selected\"":"").">After ".$tconv{$tt}."</option>";
	}
	my @apcvals = ("Disabled", "Enabled");
	$apcsvc += 0;
	for my $ii (0 .. $#apcvals) {
		$apcups .= "<option value=\"$ii\" ".(($ii == $apcsvc)?"selected=\"selected\"":"").">$apcvals[$ii]</option>";
	}

	my %apcdata = ();
	if (-e "$upsfile") {
		open(INF, "<$upsfile");
		while(<INF>) {
			my $inline = $_;
			chomp($inline);
			my @aa = split(/ \: /, $inline);
			$aa[0] =~ s/\s+$//;
			$apcdata{$aa[0]} = $aa[1];
		}
		close(INF);
	}
	$upsstat .= "<tr><td nowrap=\"nowrap\" width=\"158\">Model:</td><td><b>".((exists $apcdata{"MODEL"})?$apcdata{"MODEL"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Status:</td><td><b>".((exists $apcdata{"STATUS"})?$apcdata{"STATUS"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Battery voltage:</td><td><b>".((exists $apcdata{"BATTV"})?$apcdata{"BATTV"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Battery charge:</td><td><b>".((exists $apcdata{"BCHARGE"})?$apcdata{"BCHARGE"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Time left on battery:</td><td><b>".((exists $apcdata{"TIMELEFT"})?$apcdata{"TIMELEFT"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Last status update:</td><td><b>".((exists $apcdata{"DATE"})?$apcdata{"DATE"}:"N/A")."</td></tr>\n";

	my %dbdata = ();
	if (-e $dbfile) {
		open(INF, "<$dbfile");
		while(<INF>) {
			my $inline = $_;
			chomp($inline);
			if ($inline =~ m/Active\: (.*)$/) {
				$dbdata{active} = ucfirst($1);
			} elsif ($inline =~ m/Tasks\: (.*)$/) {
				$dbdata{tasks} = $1;
			} elsif ($inline =~ m/service \- (.*)$/) {
				$dbdata{server} = $1;
			}
		}
		close(INF);
	}
	$dbstat .= "<tr><td nowrap=\"nowrap\" width=\"158\">Server:</td><td><b>".((exists $dbdata{"server"})?$dbdata{"server"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Status:</td><td><b>".((exists $dbdata{"active"})?$dbdata{"active"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Tasks:</td><td><b>".((exists $dbdata{"tasks"})?$dbdata{"tasks"}:"N/A")."</td></tr>\n";

	my %ipdata = ();
	my %hwdata = ();
	if (-e $ntpfile) {
		open(INF, "<$ntpfile");
		while(<INF>) {
			my $inline = $_;
			chomp($inline);
			if ($inline =~ m/Active\: (.*)$/) {
				$ipdata{ntpstat} = ucfirst($1);
			} elsif ($inline =~ m/ntpd\[(\d+)\]\: (\d+)\.(\d+)\.(\d+)\.(\d+)/) {
				$ipdata{ntpsrv} = $2.".".$3.".".$4.".".$5;
			}
		}
		close(INF);
	}
	if (-e $hwfile) {
		open(INF, "<$hwfile");
		while(<INF>) {
			my $inline = $_;
			chomp($inline);
			if ($inline =~ m/^nameserver (.*)$/) {
				if (exists $ipdata{dns}) {
					$ipdata{dns} .= ", ".$1;
				} else {
					$ipdata{dns} = $1;
				}
			} elsif ($inline =~ m/^\s+inet (\d+)\.(\d+)\.(\d+)\.(\d+)\s+netmask (\d+)\.(\d+)\.(\d+)\.(\d+)\s+broadcast (\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
				unless (exists $ipdata{ip}) {
					$ipdata{ip} = $1.".".$2.".".$3.".".$4;
					$ipdata{mask} = $5.".".$6.".".$7.".".$8;
				}
			} elsif ($inline =~ m/^0\.0\.0\.0\s+(\d+)\.(\d+)\.(\d+)\.(\d+)\s+0\.0\.0\.0/) {
				$ipdata{gw} = $1.".".$2.".".$3.".".$4;
			} elsif ($inline =~ m/has address (\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
				$ipdata{ipp} = $1.".".$2.".".$3.".".$4;
#			} elsif ($inline =~ m/^(.*)load average\: ([\d\.]+)\, ([\d\.]+), ([\d\.]+)$/) {
#				$hwdata{cpu} = $2.", ".$3.", ".$4;
			} elsif ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
				$hwdata{uptime} = $1;
				$hwdata{cpu} = $3;
			} elsif ($inline =~ m/^Mem\:\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)$/) {
				$hwdata{ram} = "&nbsp;&nbsp;(".$1."Mb total, ".$2."Mb used, ".$6."Mb available)";
				if ($1 > 0) {
					$hwdata{raml} = 100 - floor(($6 / $1) * 100);
				}
			} elsif ($inline =~ m/^([a-z0-9\/]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\%\s+\/$/) {
				$hwdata{disk} = $5."%&nbsp;&nbsp;&nbsp;&nbsp;(".sprintf("%.1f", ($2 / (1024 * 1024)))."Gb total, ".sprintf("%.1f", ($3 / (1024 * 1024)))."Gb used ".sprintf("%.1f", ($4 / (1024 * 1024)))."Gb available at ".$1." )";
			}
		}
		close(INF);
	}
	my %verdata = ();
	my %upddata = ();
	{
		my $all = $db->selectall_arrayref("SELECT module, current, local, remote, status, description FROM versions");		# read version data
		foreach my $row (@$all) {
			my ($mod, $cver, $lver, $rver, $stat, $desc) = @$row;
			$verdata{$mod} = $cver;
			my $updtxt = "Up to date";
			my ($llver, $rrver, $ccver) = (0, 0, 0);
			if ($lver =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
				$llver = sprintf("%02d%02d%02d%02d", $1, $2, $3, $4);
			}
			if ($cver =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
				$ccver = sprintf("%02d%02d%02d%02d", $1, $2, $3, $4);
			}
			if ($rver =~ m/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
				$rrver = sprintf("%02d%02d%02d%02d", $1, $2, $3, $4);
			}
			if ($rrver > $llver) {
				$updtxt = "Downloading <span style=\"cursor:pointer;\" data-tooltip=\"$desc\">update $rver</span>";
			} elsif (($rrver == $llver) && ($llver > $ccver)) {
				$updtxt = "<span style=\"cursor:pointer;\" data-tooltip=\"$desc\">Update $lver</span> available. <a href=\"#\" onClick=\"document.IRForm.upmod.value='$mod';document.IRForm.action.value='upgrade';document.IRForm.submit();\" class=redlink>Apply now</a>";
			}
			if ($stat == 1) {		# in progress
				$updtxt = "Update to $lver pending. <a href=\"#\" onClick=\"document.IRForm.upmod.value='$mod';document.IRForm.action.value='clean';document.IRForm.submit();\" class=redlink>Cancel</a>";
			} elsif ($stat == 2) {		# success
				$updtxt = "Update to $lver in progress";
			} elsif ($stat == 3) {		# success
				$updtxt = "Successfully updated to $lver. <a href=\"#\" onClick=\"document.IRForm.upmod.value='$mod';document.IRForm.action.value='clean';document.IRForm.submit();\" class=redlink>Dismiss</a>";
			} elsif ($stat == 4) {		# error
				$updtxt = "Error updating to $lver. <a href=\"#\" onClick=\"document.IRForm.upmod.value='$mod';document.IRForm.action.value='clean';document.IRForm.submit();\" class=redlink>Dismiss</a>";
			}
			$upddata{$mod} = $updtxt;
		}
		undef $all;
	}
	$ipstat .= "<tr><td nowrap=\"nowrap\" width=\"158\">Ethernet IP address:</td><td><b>".((exists $ipdata{"ip"})?$ipdata{"ip"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Ethernet netmask:</td><td><b>".((exists $ipdata{"mask"})?$ipdata{"mask"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Main gateway:</td><td><b>".((exists $ipdata{"gw"})?$ipdata{"gw"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">DNS servers:</td><td><b>".((exists $ipdata{"dns"})?$ipdata{"dns"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Public IP address:</td><td><b>".((exists $ipdata{"ipp"})?$ipdata{"ipp"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">NTP status:</td><td><b>".((exists $ipdata{"ntpstat"})?$ipdata{"ntpstat"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">NTP server:</td><td><b>".((exists $ipdata{"ntpsrv"})?$ipdata{"ntpsrv"}:"N/A")."</td></tr>\n";
	$hwstat .= "<tr><td nowrap=\"nowrap\" width=\"158\">CPU load:</td><td><b>".((exists $hwdata{"cpu"})?$hwdata{"cpu"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Memory load:</td><td><b>".((exists $hwdata{"raml"})?$hwdata{"raml"}."% ":"").((exists $hwdata{"ram"})?$hwdata{"ram"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Disk load:</td><td><b>".((exists $hwdata{"disk"})?$hwdata{"disk"}:"N/A")."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">System uptime:</td><td><b>".((exists $hwdata{"uptime"})?$hwdata{"uptime"}:"N/A")."</td></tr>\n";
	$swstat .= "<tr><td nowrap=\"nowrap\" width=\"158\">Server version:</td><td width=\"98\"><b>".$verdata{"server"}."</td><td align=left><b>".$upddata{"server"}."</td></tr>\n
		<tr><td nowrap=\"nowrap\" width=\"158\">Virtual core version:</td><td width=\"98\"><b>".$verdata{"vcore"}."</td><td align=left><b>".$upddata{"vcore"}."</td></tr>\n";

	$headadd .= "<meta http-equiv=\"refresh\" content=\"60;URL=./engine.pl?mode=$uimode&submode=$uismode\">\n";
	$headadd .= <<EOF;
		<style>
		.tooltip {
			position: fixed;
			padding: 10px 20px;
			border: 1px solid #b3c9ce;
			border-radius: 4px;
			text-align: center;
			font: italic 14px/1.3 sans-serif;
			color: #333;
			background: #fff;
			box-shadow: 3px 3px 3px rgba(0, 0, 0, .3);
		}
		</style>
EOF
	$bottomadd .= <<EOF;
		<script>
			let tooltipElem;
			document.onmouseover = function(event) {
				let target = event.target;
				let tooltipHtml = target.dataset.tooltip;
				if (!tooltipHtml) return;
				tooltipElem = document.createElement('div');
				tooltipElem.className = 'tooltip';
				tooltipElem.innerHTML = tooltipHtml;
				document.body.append(tooltipElem);
				let coords = target.getBoundingClientRect();
				let left = coords.left + (target.offsetWidth - tooltipElem.offsetWidth) / 2;
				if (left < 0) left = 0;
				let top = coords.top - tooltipElem.offsetHeight - 5;
				if (top < 0) {
					top = coords.top + target.offsetHeight + 5;
				}
				tooltipElem.style.left = left + 'px';
				tooltipElem.style.top = top + 'px';
			};
			document.onmouseout = function(e) {
				if (tooltipElem) {
					tooltipElem.remove();
					tooltipElem = null;
				}
			};
		</script>
EOF
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--db--/$dbstat/g;
		$inline =~ s/--ip--/$ipstat/g;
		$inline =~ s/--hw--/$hwstat/g;
		$inline =~ s/--sw--/$swstat/g;
		$inline =~ s/--ups--/$upsstat/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--dbback--/$dbblist/g;
		$inline =~ s/--apcups--/$apcups/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# submeters page

if (($uimode eq "userinfo") && ($uismode eq "submeters") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("parameters", "0", "submeters", "0", "iserials", "0");
	my ($brandsel, $modelsel) = (0, 0);
	my ($brandlist, $modellist, $brandname, $newmodel, $newbrand, $sublist, $iserlist, $userlist) = ("", "", "", "", "", "", "", "");
	my @lsubunits = ("mWh", "kWh", "Cubic feet", "Cubic meters", "US Gallons");
	my @lsubtype = ("Electricity", "Water", "Gas");
	my @typeunit = ("0,,1", "2,,3,,4", "2,,3");
	my @subactv = ("", "", "");
	my ($isserial, $isalias, $ispass, $ishost, $isport, $ispoll, $errmsg, $isublist, $isubdel) = ("", "", "", "", "50000", "1", "", "", "");
	my ($ispart, $isactive) = (0, 1);

	my $subid = $FORM{"sub_id"} + 0;
	if (($action eq "isubdel") && ($subid > 0)) {
		$db->do("DELETE FROM sub_iserial WHERE id = $subid");
		$subid = 0;
	}

	my ($subidmax) = $db->selectrow_array("SELECT MAX(id) FROM sub_iserial");
	$subidmax ++;
	if ($subid == 0) {
		$subid = $subidmax;
	}
	if ($uaccess > 1) {
		$isublist .= "<option value=\"$subidmax\" ".(($subid == $subidmax)?"selected=\"selected\"":"").">Add new iSerial gateway</option>";
	}
	if (($subid > 0) && ($subid < $subidmax)) {
		($isalias, $ispart, $isport, $ishost) = $db->selectrow_array("SELECT description, user_id, port, hostname FROM sub_iserial WHERE id = $subid");
		if ($uaccess > 1) {
			$isubdel = "&nbsp;&nbsp;&nbsp;<input name=\"isubdel\" value=\"Delete Gateway\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&sub_id=$subid&action=isubdel'\" type=\"button\">";
		} else {
			$isubdel = "&nbsp;&nbsp;&nbsp;";
		}
	}
	{
		my $all = $db->selectall_arrayref("SELECT id, login FROM users ".(($uaccess > 1)?"":"WHERE id = $clientid ")."ORDER BY id");
		foreach my $row (@$all) {
			my $uid = @$row[0];
			$userlist .= "<option value=\"$uid\" ".(($ispart == $uid)?"selected=\"selected\"":"").">".@$row[1]."</option>";
		}
		undef $all;
	}

	if ($action eq "save") {
		$modelsel = $FORM{model} + 0;
		$brandsel = $FORM{brand} + 0;
	} else {
		if ((exists $FORM{modelsel}) && (exists $FORM{brandsel})) {
			$modelsel = $FORM{modelsel} + 0;
			$brandsel = $FORM{brandsel} + 0;
		}
	}
	{
		if ($brandsel == 0) {
			$brandsel = -1;
		}
		$brandlist = "<option value=\"-1\"".(($modelsel == -1)?" selected=\"selected\"":"").">-- ADD NEW BRAND --</option>";
		if ($brandsel == -1) {		# add edit field
			$newbrand = "&nbsp;<input size=15 maxlength=50 value=\"\" type=text name=\"newbrand\">&nbsp;<input name=\"SaveBrand\" value=\"Save\" onclick=\"document.IRForm.submit();\" type=\"button\">";
		} elsif ($brandsel > 0) {
			if ($FORM{delbrand} == 1) {		# delete custom model
				my ($brname) = $db->selectrow_array("SELECT brand FROM sub_devices WHERE id = $brandsel");
				$db->do("DELETE FROM sub_devices WHERE UPPER(brand) = '".uc($brname)."'");
				$brandsel = -1;
				$newbrand = "&nbsp;<input size=15 maxlength=50 value=\"\" type=text name=\"newbrand\">&nbsp;<input name=\"SaveBrand\" value=\"Save\" onclick=\"document.IRForm.submit();\" type=\"button\">";
			} else {
				$newbrand = "&nbsp;<a href=\"#\" onClick=\"document.IRForm.delbrand.value='1';document.IRForm.submit();\">Delete</a>";
                        }
		}
		my %allbrands = ();
		my $all = $db->selectall_arrayref("SELECT id, brand FROM sub_devices WHERE (flags & 1) = 1 GROUP BY brand");
		foreach my $row (@$all) {
			my ($brid, $brdesc) = @$row;
			$brandlist .= "<option value=\"$brid\"".(($brid == $brandsel)?" selected=\"selected\"":"").">".$brdesc."</option>";
			if ($brid == $brandsel) {
				$brandname = $brdesc;
			}
			$allbrands{$brdesc} = $brid;
		}
		undef $all;
		if (exists $FORM{newbrand}) {
			my $unewbrand = $FORM{newbrand};
			unless (($unewbrand eq "") || (exists $allbrands{$unewbrand})) {
				$brandname = $FORM{newbrand};
				$db->do("INSERT INTO sub_devices VALUES (NULL, '$brandname', NULL, 1, 0, 0, 0)");	# use defaults for now and model = NULL
				($brandsel) = $db->selectrow_array("SELECT MAX(id) FROM sub_devices");
				$brandlist .= "<option value=\"$brandsel\" selected=\"selected\">".$brandname."</option>";
				$newbrand = "&nbsp;<a href=\"#\" onClick=\"document.IRForm.delbrand.value='1';document.IRForm.submit();\">Delete</a>";
			}
		}
	}
	my ($stype, $spulses, $sunits) = (0, 1, 0);
	my ($csubunits, $csubtype) = ("", "");
	{
		my ($isbr) = $db->selectrow_array("SELECT COUNT(id) FROM sub_devices WHERE id = $modelsel AND brand = '$brandname'");
		if ((($modelsel == 0) && ($brandsel > 0)) || ($isbr == 0)) {
			$modelsel = -1;
		}
		if (($brandsel == 0) || ($brandname eq "")) {
			$modellist = "<option value=\"0\" selected=\"selected\">-- NONE SELECTED --</option>";
			$modelsel = 0;
		} else {
			$modellist = "<option value=\"-1\"".(($modelsel == -1)?" selected=\"selected\"":"").">-- ADD NEW MODEL --</option>";
		}
		if ($modelsel == -1) {		# add edit field
			$newmodel = "&nbsp;<input size=15 maxlength=50 value=\"\" type=text name=\"newmodel\">&nbsp;<input name=\"SaveModel\" value=\"Save\" onclick=\"document.IRForm.submit();\" type=\"button\">";
		} elsif ($modelsel > 0) {
			if ($FORM{delmodel} == 1) {		# delete custom model
				$db->do("DELETE FROM sub_devices WHERE id = $modelsel");
				$modelsel = -1;
				$newmodel = "&nbsp;<input size=15 maxlength=50 value=\"\" type=text name=\"newmodel\">&nbsp;<input name=\"SaveModel\" value=\"Save\" onclick=\"document.IRForm.submit();\" type=\"button\">";
			} else {
				$newmodel = "&nbsp;<a href=\"#\" onClick=\"document.IRForm.delmodel.value='1';document.IRForm.submit();\">Delete</a>";
                        }
		}
		my %allmodels = ();
		my $all = $db->selectall_arrayref("SELECT id, model, type_, pulses, units FROM sub_devices WHERE (flags & 1) = 1 AND model IS NOT NULL AND UPPER(brand) = '".uc($brandname)."' ORDER BY model");
		foreach my $row (@$all) {
			my ($moid, $modesc, $ttype, $tpulses, $tunits) = @$row;
			$modellist .= "<option value=\"$moid\"".(($moid == $modelsel)?" selected=\"selected\"":"").">".$modesc."</option>";
			if ($moid == $modelsel) {
				$stype = $ttype + 0;
				$spulses = $tpulses + 0;
				$sunits = $tunits + 0;
			}
			$allmodels{$modesc} = $moid;
		}
		undef $all;
		if (exists $FORM{newmodel}) {
			my $unewmodel = $FORM{newmodel};
			unless (($unewmodel eq "") || (exists $allmodels{$unewmodel})) {
				$db->do("INSERT INTO sub_devices VALUES (NULL, '$brandname', '$unewmodel', 1, 0, 0, 0)");	# use defaults for now
				($modelsel) = $db->selectrow_array("SELECT MAX(id) FROM sub_devices");
				$modellist .= "<option value=\"$modelsel\" selected=\"selected\">".$unewmodel."</option>";
				$newmodel = "&nbsp;<a href=\"#\" onClick=\"document.IRForm.delmodel.value='1';document.IRForm.submit();\">Delete</a>";
			}
		}
	}
	if ($modelsel > 0) {
		$hiders{"parameters"} = 1;
		if (($action eq "save") && (exists $FORM{"subtype"}) && (exists $FORM{"subunits"}) && (exists $FORM{"pulses"}) && ($FORM{"lastsel"} == $modelsel)) {
			$stype = $FORM{"subtype"} + 0;
			$sunits = $FORM{"subunits"} + 0;
			$spulses = (($FORM{"pulses"} + 0) < 0)?$spulses:(floor($FORM{"pulses"} + 0));
			$db->do("UPDATE sub_devices SET type_ = $stype, pulses = $spulses, units = $sunits WHERE id = $modelsel");
		}
		for my $dt (0 .. $#lsubtype) {
			$csubtype .= "<option value=\"$dt\"".(($dt eq $stype)?" selected=\"selected\"":"").">".$lsubtype[$dt]."</option>";
		}
		my %susel = split(/\,/, $typeunit[$stype]);
		for my $dt (0 .. $#lsubunits) {
			if (exists $susel{$dt}) {
				$csubunits .= "<option value=\"$dt\"".(($dt eq $sunits)?" selected=\"selected\"":"").">".$lsubunits[$dt]."</option>";
			}
		}
	}

	{
		my $all = $db->selectall_arrayref("SELECT sub_connected.id, sub_connected.core_id, sub_connected.device_id, sub_devices.brand, sub_devices.model FROM sub_connected LEFT JOIN sub_devices ON sub_devices.id = sub_connected.sub_id WHERE (sub_connected.flags & 1) = 1 ORDER BY sub_connected.core_id");
		foreach my $row (@$all) {
			my $cid = sprintf("%05d", @$row[1]);
			my $did = @$row[2];
			my $desc = @$row[3]." ".@$row[4];
			my $dbname = "smart$cid";
			my ($type, $mac, $ip, $pulses, $stamp) = $db->selectrow_array("SELECT ip_ase.device_type, ip_ase.mac_addr, ip_ase.ip_addr, deviceadvanced.realvar1, deviceadvanced.realvar2 FROM $dbname.ip_ase LEFT JOIN $dbname.deviceadvanced ON deviceadvanced.device_id = ip_ase.device_id AND deviceadvanced.type_ = 3 WHERE ip_ase.device_id = $did");
			my $conn = "CDGS1-MD: ";
			$pulses += 0;		# could be null
			$stamp += 0;
			if ($type & 0x1000) {
				$conn = "iSerial: ";
			}
			$sublist .= "<tr><td><b>$cid</td><td nowrap=\"nowrap\"><b>$desc</b></td><td nowrap=\"nowrap\">$conn$mac</td><td>$ip</td><td>$pulses</td></tr>\n";
		}
		undef $all;
	}

	if ($errmsg ne "") {
		$errmsg = "<tr><td colspan=2><br><b><font color=red>$errmsg</font></b></td></tr>";
	}
	if (($sublist eq "") && ($iserlist eq "")) {
		$sublist = "<tr><td><b>No meters currently connected</b></td></tr>";
	} else {
		if ($iserlist ne "") {
			$hiders{iserials} = 1;
		}
		if ($sublist ne "") {
			$hiders{submeters} = 1;
		}
	}
	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--hostname--/$ishost/g;
		$inline =~ s/--port--/$isport/g;
		$inline =~ s/--alias--/$isalias/g;
		$inline =~ s/--isublist--/$isublist/g;
		$inline =~ s/--iserlist--/$iserlist/g;
		$inline =~ s/--isubdel--/$isubdel/g;
		$inline =~ s/--subunits--/$csubunits/g;
		$inline =~ s/--subtype--/$csubtype/g;
		$inline =~ s/--pulses--/$spulses/g;
		$inline =~ s/--sublist--/$sublist/g;
		$inline =~ s/--brandsel--/$brandsel/g;
		$inline =~ s/--modelsel--/$modelsel/g;
		$inline =~ s/--lastsel--/$modelsel/g;
		$inline =~ s/--errmsg--/$errmsg/g;
		$inline =~ s/--brand--/$brandlist/g;
		$inline =~ s/--model--/$modellist/g;
		$inline =~ s/--newmodel--/$newmodel/g;
		$inline =~ s/--newbrand--/$newbrand/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# holidays page

if (($uimode eq "userinfo") && ($uismode eq "holidays") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("states", "0", "holidays", "0");
	my ($holsel, $stacnt, $statemode, $rulesmode) = (0, 0, 0, 0);
	my ($cntlist, $hollist, $cntsel, $htitle, $stalist, $message) = ("", "", "", "", "", "");
	my @stamode = (1, 0, 0);
	my @rulemode = (1, 0, 0, 0, 0, 0);
	my @selmodes = ("", ' checked="checked"');
	my %multistate = ();

	if (exists $FORM{holsel}) {
		$holsel = $FORM{holsel} + 0;
	} else {
		$holsel = $FORM{lastsel} + 0;
	}

	if ($FORM{delhol} > 0) {
		my $dh = $FORM{delhol} + 0;
		$db->do("DELETE FROM holidays WHERE id = $dh");
		$holsel = 0;
	}

	if ($action eq "save") {
		$htitle = $FORM{"htitle"};
		$cntsel = $FORM{"country"};
		$db->do("REPLACE INTO user_params (user_id, name_, value_) VALUES ($clientid, 'cntsel', '$cntsel')");
	} else {
		if (exists $FORM{country}) {
			$cntsel = $FORM{country};
		} else {
			($cntsel) = $db->selectrow_array("SELECT value_ FROM user_params WHERE user_id = $clientid AND name_ = 'cntsel'");
			if ($cntsel eq "") {
				$cntsel = "CA";
			}
		}
	}

	{
		my $all = $db->selectall_arrayref("SELECT country_code, country_name FROM country WHERE country_code IN ('CA', 'US')");
		foreach my $row (@$all) {
			my ($cc, $cn) = @$row;
			$cntlist .= "<option value=\"$cc\"".(($cc eq $cntsel)?" selected=\"selected\"":"").">".$cn."</option>";
		}
		undef $all;
		my $all = $db->selectall_arrayref("SELECT country_code, country_name FROM country WHERE country_code NOT IN ('CA', 'US') ORDER BY country_name");
		foreach my $row (@$all) {
			my ($cc, $cn) = @$row;
			$cntlist .= "<option value=\"$cc\"".(($cc eq $cntsel)?" selected=\"selected\"":"").">".$cn."</option>";
		}
		undef $all;
	}

	my $titexist = 0;
	{
		my $all = $db->selectall_arrayref("SELECT id, description FROM holidays WHERE country = '$cntsel'");
		foreach my $row (@$all) {
			my ($id, $desc) = @$row;
			if ($desc eq $htitle) {
				$titexist ++;
			}
		}
		undef $all;
	}

	my ($vmonthA, $vdomA) = (1, 1);		# defaults
	my ($vmonthB, $vdowB, $vdacB) = (1 ,0, 1);
	my ($vmonthC, $vdomC, $vdowC) = (1, 1, 0);
	my ($vmonthD, $vdomD, $vdowD) = (1, 1, 0);
	my ($vlunarE, $vdowE) = (0 ,0);
	my ($vlunarF, $vdowF) = (0 ,0);

	if ($holsel > 0) {
		my ($tit, $reg, $rul) = $db->selectrow_array("SELECT description, region, rule FROM holidays WHERE id = $holsel AND country = '$cntsel'");
		if ($tit) {
			$htitle = $tit;
			my @rrul = split(/\,/, $rul);
			$rul = $rrul[0];
			if ($rul == 0) {
				($rulesmode, $vmonthA, $vdomA) = @rrul;
			} elsif ($rul == 1) {
				($rulesmode, $vmonthB, $vdacB, $vdowB) = @rrul;
			} elsif ($rul == 2) {
				($rulesmode, $vdowC, $vmonthC, $vdomC) = @rrul;
			} elsif ($rul == 3) {
				($rulesmode, $vdowD, $vmonthD, $vdomD) = @rrul;
			} elsif ($rul == 4) {
				($rulesmode, $vdowE, $vlunarE) = @rrul;
			} elsif ($rul == 5) {
				($rulesmode, $vdowF, $vlunarF) = @rrul;
			}
			my @regs = split(/\,/, $reg);
			$statemode = $regs[0];
			if (($statemode == 1) || ($statemode == 2)) {
				for my $ii (1 .. $#regs) {
					$multistate{$regs[$ii]} = $ii;
				}
			}
		}
	}

	if ($cntsel ne "") {
		if ($action eq "save") {
			$statemode = $FORM{state} + 0;
			$rulesmode = $FORM{rules} + 0;
			my $mst = $FORM{multistate};
			%multistate = ();
			if ($mst ne "") {
				my @mmst = split(/\,/, $mst);
				foreach my $mm (@mmst) {
					$multistate{$mm} = $mm;
				}
			}
		}
		my $all = $db->selectall_arrayref("SELECT state_code, state_name FROM states WHERE country_code = '$cntsel' ORDER BY state_name");
		foreach my $row (@$all) {
			my ($sc, $sn) = @$row;
			$stalist .= "<option value=\"$sc\"".((exists $multistate{$sc})?' selected="selected"':"").">".$sn."</option>";
			if ($sn ne "Not Applicable") {
				$stacnt ++;
			}
		}
		undef $all;
	}

	if ($action eq "save") {
		my $err = 0;
		$htitle = $FORM{"htitle"};
		$vmonthA = $FORM{"month0"} + 0;
		$vmonthB = $FORM{"month1"} + 0;
		$vmonthC = $FORM{"month2"} + 0;
		$vmonthD = $FORM{"month3"} + 0;
		$vdomA = $FORM{"dom0"} + 0;
		$vdomC = $FORM{"dom2"} + 0;
		$vdomD = $FORM{"dom3"} + 0;
		$vdowB = $FORM{"dow1"} + 0;
		$vdowC = $FORM{"dow2"} + 0;
		$vdowD = $FORM{"dow3"} + 0;
		$vdowE = $FORM{"dow4"} + 0;
		$vdowF = $FORM{"dow5"} + 0;
		$vdacB = $FORM{"dac1"} + 0;
		$vlunarE = $FORM{"lunar4"} + 0;
		$vlunarF = $FORM{"lunar5"} + 0;
		my $drule = "";
		if ($rulesmode == 0) {
			$drule = "$rulesmode,$vmonthA,$vdomA";
		} elsif ($rulesmode == 1) {
			$drule = "$rulesmode,$vmonthB,$vdacB,$vdowB";
		} elsif ($rulesmode == 2) {
			$drule = "$rulesmode,$vdowC,$vmonthC,$vdomC";
		} elsif ($rulesmode == 3) {
			$drule = "$rulesmode,$vdowD,$vmonthD,$vdomD";
		} elsif ($rulesmode == 4) {
			$drule = "$rulesmode,$vdowE,$vlunarE";
		} elsif ($rulesmode == 5) {
			$drule = "$rulesmode,$vdowF,$vlunarF";
		}
		my $rrule = "";
		my $regs = ($FORM{multistate} eq "")?"-":$FORM{multistate};
		if ($statemode == 0) {
			$rrule = "$statemode";
		} elsif ($statemode == 1) {
			$rrule = "$statemode,$regs";
		} elsif ($statemode == 2) {
			if ($regs eq "-") {
				$err = 3;
			}
			$rrule = "$statemode,$regs";
		}
		if (($titexist) && ($holsel == 0)) {
			$err = 1;
		} elsif ($htitle eq "") {
			$err = 2;
		}
		if ($err == 0) {
			$db->do("REPLACE INTO holidays (id, updated, type_, description, country, region, rule, flags) VALUES ($holsel, NOW(), 0, '$htitle', '$cntsel', '$rrule', '$drule', 1)");
		} elsif ($err == 1) {
			$message = "Holiday title must be unique";
		} elsif ($err == 2) {
#			$message = "Holiday title cannot be empty";
		} elsif ($err == 3) {
			$message = "At least one state or province must be selected";
		}
	}

	my ($lmonthA, $ldomA) = ("", "");
	for my $ii (1 .. 31) {
		$ldomA .= "<option value=\"$ii\"".(($ii == $vdomA)?' selected="selected"':"").">".$ii."</option>";
	}
	for my $ii (1 .. 12) {
		$lmonthA .= "<option value=\"$ii\"".(($ii == $vmonthA)?' selected="selected"':"").">".$months[$ii]."</option>";
	}

	my ($lmonthB, $ldowB, $ldacB) = ("", "", "");
	for my $ii (0 .. 6) {
		$ldowB .= "<option value=\"$ii\"".(($ii == $vdowB)?' selected="selected"':"").">".$dayofweek[$ii]."</option>";
	}
	for my $ii (1 .. 6) {
		$ldacB .= "<option value=\"$ii\"".(($ii == $vdacB)?' selected="selected"':"").">".$weeksofmonth[$ii]."</option>";
	}
	for my $ii (1 .. 12) {
		$lmonthB .= "<option value=\"$ii\"".(($ii == $vmonthB)?' selected="selected"':"").">".$months[$ii]."</option>";
	}

	my ($lmonthC, $ldomC, $ldowC) = ("", "", "");
	for my $ii (1 .. 31) {
		$ldomC .= "<option value=\"$ii\"".(($ii == $vdomC)?' selected="selected"':"").">".$ii."</option>";
	}
	for my $ii (1 .. 12) {
		$lmonthC .= "<option value=\"$ii\"".(($ii == $vmonthC)?' selected="selected"':"").">".$smonths[$ii]."</option>";
	}
	for my $ii (0 .. 6) {
		$ldowC .= "<option value=\"$ii\"".(($ii == $vdowC)?' selected="selected"':"").">".$dayofweek[$ii]."</option>";
	}

	my ($lmonthD, $ldomD, $ldowD) = ("", "", "");
	for my $ii (1 .. 31) {
		$ldomD .= "<option value=\"$ii\"".(($ii == $vdomD)?' selected="selected"':"").">".$ii."</option>";
	}
	for my $ii (1 .. 12) {
		$lmonthD .= "<option value=\"$ii\"".(($ii == $vmonthD)?' selected="selected"':"").">".$smonths[$ii]."</option>";
	}
	for my $ii (0 .. 6) {
		$ldowD .= "<option value=\"$ii\"".(($ii == $vdowD)?' selected="selected"':"").">".$dayofweek[$ii]."</option>";
	}

	my ($llunarE, $ldowE) = ("", "");
	for my $ii (0 .. 6) {
		$ldowE .= "<option value=\"$ii\"".(($ii == $vdowE)?' selected="selected"':"").">".$dayofweek[$ii]."</option>";
	}
	for my $ii (0 .. 2) {
		$llunarE .= "<option value=\"$ii\"".(($ii == $vlunarE)?' selected="selected"':"").">".$lunardates[$ii]."</option>";
	}

	my ($llunarF, $ldowF) = ("", "");
	for my $ii (0 .. 6) {
		$ldowF .= "<option value=\"$ii\"".(($ii == $vdowF)?' selected="selected"':"").">".$dayofweek[$ii]."</option>";
	}
	for my $ii (0 .. 2) {
		$llunarF .= "<option value=\"$ii\"".(($ii == $vlunarF)?' selected="selected"':"").">".$lunardates[$ii]."</option>";
	}

	if ($stacnt) {
		$hiders{"states"} ++;
	}
	my $ruletitle = ($holsel == 0)?"Add new holiday":"Modify selected";

	for my $ii (0 .. $#stamode) {
		$stamode[$ii] = ($ii == $statemode)?1:0;
	}
	for my $ii (0 .. $#rulemode) {
		$rulemode[$ii] = ($ii == $rulesmode)?1:0;
	}

	{
		my $bgc = 1;
		my $all = $db->selectall_arrayref("SELECT id, description, country, region, rule FROM holidays WHERE country = '$cntsel' AND (flags & 1) = 1 ORDER BY description");
		foreach my $row (@$all) {
			my ($id, $desc, $cnt, $reg, $rule) = @$row;
			my $treg = "Nationwide";
			if ($reg =~ m/^1\,/) {
				$treg = "Nationwide excl. selected states";
			} elsif ($reg =~ m/^2\,/) {
				$treg = "For selected states only";
			}
			my $orule = "";
			my @rrule = split(/\,/, $rule);
			if ($rrule[0] == 0) {		# fixed date
				$orule = $months[$rrule[1]].", ".$rrule[2];
			} elsif ($rrule[0] == 1) {	# floating
				$orule = $weekofmonth[$rrule[2]]." ".$dayofweek[$rrule[3]]." of ".$months[$rrule[1]];
			} elsif ($rrule[0] == 2) {	# dow before date
				$orule = $dayofweek[$rrule[1]]." after ".$months[$rrule[2]].", ".$rrule[3];
			} elsif ($rrule[0] == 3) {	# dow after date
				$orule = $dayofweek[$rrule[1]]." before ".$months[$rrule[2]].", ".$rrule[3];
			} elsif ($rrule[0] == 4) {	# dow before lunar
				$orule = $dayofweek[$rrule[1]]." after ".$lunardates[$rrule[2]];
			} elsif ($rrule[0] == 5) {	# dow after lunar
				$orule = $dayofweek[$rrule[1]]." before ".$lunardates[$rrule[2]];
			}
			$hollist .= "<tr style=\"background:".(($bgc & 1)?"#EEE":"#FFF").";\">
				<td nowrap=\"nowrap\"><a href=\"./engine.pl?mode=$uimode&submode=$uismode&cntsel=$cntsel&holsel=$id\" class=blacklink>$desc</a></td>
				<td nowrap=\"nowrap\">$treg</td>
				<td nowrap=\"nowrap\">$orule</td>
				<td><a class=redlink href=\"#\" onClick=\"DelHol($id,'$desc');\">[x]</a></td></tr>";
			$bgc ++;
		}
		undef $all;
		$headadd .= <<EOF;
			<script language="JavaScript">
			function DelHol(hol,name) {
				var answer = confirm ("Are you sure to permanently DELETE holiday "+name+" ?");
				if (answer) {
					document.IRForm.action.value="delete";
					document.IRForm.delhol.value=hol;
					document.IRForm.submit();
				}
				return false;
			}
			</script>
EOF
	}

	if ($hollist eq "") {
		$hollist = "<tr><td><b>No holidays defined for selected country</b></td></tr>";
	} else {
		$hiders{holidays} = 1;
	}

	if ($message ne "") {
		$message = "<tr><td colspan=4><br><b>$message</td></tr>";
	}
	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--rules--/$ruletitle/g;
		$inline =~ s/--htitle--/$htitle/g;
		$inline =~ s/--country--/$cntlist/g;
		$inline =~ s/--cntsel--/$cntsel/g;
		$inline =~ s/--states--/$stalist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--state0--/$selmodes[$stamode[0]]/g;
		$inline =~ s/--state1--/$selmodes[$stamode[1]]/g;
		$inline =~ s/--state2--/$selmodes[$stamode[2]]/g;
		$inline =~ s/--rules0--/$selmodes[$rulemode[0]]/g;
		$inline =~ s/--rules1--/$selmodes[$rulemode[1]]/g;
		$inline =~ s/--rules2--/$selmodes[$rulemode[2]]/g;
		$inline =~ s/--rules3--/$selmodes[$rulemode[3]]/g;
		$inline =~ s/--rules4--/$selmodes[$rulemode[4]]/g;
		$inline =~ s/--rules5--/$selmodes[$rulemode[5]]/g;
		$inline =~ s/--month0--/$lmonthA/g;
		$inline =~ s/--dom0--/$ldomA/g;
		$inline =~ s/--month2--/$lmonthC/g;
		$inline =~ s/--dom2--/$ldomC/g;
		$inline =~ s/--dow2--/$ldowC/g;
		$inline =~ s/--month3--/$lmonthD/g;
		$inline =~ s/--dom3--/$ldomD/g;
		$inline =~ s/--dow3--/$ldowD/g;
		$inline =~ s/--dow4--/$ldowE/g;
		$inline =~ s/--lunar4--/$llunarE/g;
		$inline =~ s/--dow5--/$ldowF/g;
		$inline =~ s/--lunar5--/$llunarF/g;
		$inline =~ s/--month1--/$lmonthB/g;
		$inline =~ s/--dow1--/$ldowB/g;
		$inline =~ s/--dac1--/$ldacB/g;
		$inline =~ s/--hollist--/$hollist/g;
		$inline =~ s/--lastsel--/$holsel/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# zones report

if (($uimode eq "reports") && ($uismode eq "zones") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
#	my $timezone = (exists $FORM{timezone})?$FORM{timezone}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
	my $maxrec = $perpage;
	my $coresel = $FORM{coresel} + 0;
	my $fromrec = $maxrec * ($curpage - 1);
	my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
	$allrec += 0;
	my $maxpage = floor($allrec / $maxrec) + 1;
	if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
		$maxpage --;
	}
	my $homelist = "";
	my $stylecnt = 0;
	my @rfiles = ("Occupancy", "Temp_setpoints", "Energy_mode", "Temperature", "Humidity", "Lux", "CO", "CO2", "Setpoint_recovery", "Fan_cycles", "Env_conditions");
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my @rsel = ();
		my ($zscnt, $rscnt, $crcnt) = (0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 0 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		$homelist .= "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>";		# zones part
		my ($ii, $iii) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT id, description FROM smart".$homeid.".zones WHERE id > 2");		# all except temp+master
		my $allzones = "";
		my %zonames = ("0", "<i>All zones at core</i>");
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $zdesc = @$row[1];
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			if (length($zdesc) > 30) {
				$zdesc = substr($zdesc, 0, 30)." ..";
			}
			$zonames{$zid} = $zdesc;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$zid\"".((exists $FORM{"z$zid"})?" checked=\"checked\"":"")."></td><td width=180 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 4) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$zid"}) {
				$zsel[$zscnt] = $zid;
				$zscnt ++;
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no zones
			$allzones = "<tr><td><br><b>No zones defined on Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=180><b>Select all zones</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=180><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones .= "</table></td></tr>";
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		my $reports = "";
		my @repnshort = ("Occupancy", "Temp setpoints", "Energy mode", "Temperature", "Humidity", "Lux", "CO", "CO2", "Setpoint recovery", "Fan cycles", "Env conditions");
		my @repstatus = (1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1);
		if ($iszones) {
			my @reps = ("Occupancy", "Temperature setpoints", "Energy mode", "Temperature", "Humidity", "Lux", "CO", "CO2", "Setpoint recovery", "Fan cycles", "Environmental conditions");
			my $replist = "";
			my ($ii, $iii, $iiii) = (0, 0, 0);
			foreach my $rname (@reps) {
				if ($repstatus[$iiii]) {		# report not hidden
					if ($ii == 0) {
						$replist .= "</tr>";
					}
					$replist .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"r$iiii\"".((exists $FORM{"r$iiii"})?" checked=\"checked\"":"")."></td><td width=366 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$rname</td>";
					$ii ++;
					$iii ++;
					if ($ii == 2) {
						$ii = 0;
						$replist .= "</tr>";
						$iii ++;
					}
				}
				if (exists $FORM{"r$iiii"}) {
					$rsel[$rscnt] = $iiii;
					$rscnt ++;
					if (($iiii == 0) || ($iiii == 1) || ($iiii == 2) || ($iiii == 3)) {
						$crcnt ++;		# reports critical to zone sel
					}
				}
				$iiii ++;
			}
			$reports = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr><td width=10><input name=\"rchk[]\" type=\"checkbox\" onChange=\"checkRAll()\"></td><td width=180><b>Select all reports</td><td width=10><input name=\"runchk[]\" type=\"checkbox\" onChange=\"uncheckRAll();\"></td><td width=180><b>Select none</td></tr>
				$replist
				</table></td></tr>
EOF
		}
		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if (($zscnt == 0) && ($crcnt)) {
				$progmsg .= "<font color=red><b>At least one zone must be selected";
			} elsif ($rscnt == 0) {
				$progmsg .= "<font color=red><b>At least one report must be selected";
			} else {
				for my $rr (0 .. ($rscnt - 1)) {
					my $rid = $rsel[$rr];
					for my $zz (0 .. ($zscnt - 1)) {
						my $zid = $zsel[$zz];
						$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, NULL, '$datef', '$datet', $timezone, $rid, 0, 0, 0, 0, 0)");
					}
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $zid, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, zone_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = $rfiles[$rtype]."_$sftime-$sttime\_Core$cid\_Zone$zid\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
#			print "Content-Type:application/x-download\n";
#			print "Content-Disposition:attachment;filename=$outname\n\n";
#			print $tabdata;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my $tzoff = gettzsecoff();
#		$debug = $tzoff." ".$clientid." ".$utimezone;
		{
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, report_id, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 0 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $rid = @$row[6];
				my $sts = @$row[7];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=$id\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">".$zonames{$zid}."</td>
						<td nowrap=\"nowrap\">".$repnshort[$rid]."</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"140\"><small>Zone</td>
						<td width=\"140\"><small>Report type</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $allzones.$timesel.$reports.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# BAFcon report

if (($uimode eq "reports") && ($uismode eq "hvls") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
	my $maxrec = $perpage;
	my $coresel = $FORM{coresel} + 0;
	my $fromrec = $maxrec * ($curpage - 1);
	my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
	$allrec += 0;
	my $maxpage = floor($allrec / $maxrec) + 1;
	if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
		$maxpage --;
	}
	my $homelist = "";
	my $stylecnt = 0;
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my ($zscnt, $rscnt, $crcnt) = (0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 5 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		$homelist .= "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>";
		my ($ii, $iii) = (0, 0);
		my %bafdata = ();
		{
			my $all = $db->selectall_arrayref("SELECT cots_id, name_, value_ FROM smart".$homeid.".bac_list WHERE name_ IN ('name', 'alias', 'loc')");
			foreach my $row (@$all) {
				$bafdata{@$row[0]}{@$row[1]} = @$row[2];
			}
			undef $all;
		}
		my $all = $db->selectall_arrayref("SELECT xbee_addr64,description FROM smart".$homeid.".devices WHERE hardware_type = 7 AND device_type = 84");		# BAFcon only
		my $allzones = "";
		my %zonames = ("0", "<i>All BAFcon at core</i>");
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $zdesc = "<b>".@$row[1]."</b> @ ".$bafdata{$zid}{loc};
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			$zonames{$zid} = $zdesc;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$zid\"".((exists $FORM{"z$zid"})?" checked=\"checked\"":"")."></td><td width=180 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 4) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$zid"}) {
				$zsel[$zscnt] = $zid;
				$zscnt ++;
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no bafcon
			$allzones = "<tr><td><br><b>No BAFcon defined on Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=180><b>Select all controllers</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=180><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones .= "</table></td></tr>";
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		$timesel = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$timesel</table></td></tr>";
		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if (($zscnt == 0) && ($crcnt)) {
				$progmsg .= "<font color=red><b>At least one controller must be selected";
			} else {
				for my $zz (0 .. ($zscnt - 1)) {
					my $zid = $zsel[$zz];
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, NULL, '$datef', '$datet', $timezone, 0, 5, 0, 0, 0, 0)");
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $zid, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, zone_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = "HVLS_$sftime-$sttime\_Core$cid\_BAFcon$zid\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my $tzoff = gettzsecoff();
		{
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 5 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $sts = @$row[6];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=$id\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">".$zonames{$zid}."</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"280\"><small>BAF Controller</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $timesel.$allzones.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# uptime report

if (($uimode eq "reports") && ($uismode eq "uptime") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
#	my $timezone = (exists $FORM{timezone})?$FORM{timezone}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
        my $maxrec = $perpage;
        my $coresel = $FORM{coresel} + 0;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $homelist = "";
	my $stylecnt = 0;
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my @ssel = ();
		my @dsel = ();
		my @tsel = ();
		my @isel = ();
		my ($zscnt, $rscnt, $crcnt, $sscnt, $dscnt, $tscnt, $iscnt) = (0, 0, 0, 0, 0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 4 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		my %znames = ();
		{
			my $all = $db->selectall_arrayref("SELECT id, description FROM smart".$homeid.".zones WHERE id > 2");
			foreach my $row (@$all) {
				$znames{@$row[0]} = @$row[1];
			}
			undef $all;
		}

		my %allnames = ();
		my %allzones = ();
		my ($ii, $iii) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, devices.zone_id FROM smart".$homeid.".devices LEFT JOIN smart".$homeid.".ip_ase ON ip_ase.device_id = devices.id WHERE (ip_ase.device_type & 0x2000) = 0x2000 ORDER BY devices.id");
		my $allzones = "";
		my %zonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			$zonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$did\"".((exists $FORM{"z$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 2) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$did"}) {
				$zsel[$zscnt] = $did;
				$zscnt ++;
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no AFC
			$allzones = "<tr><td><br><b>No AFC-Core devices connected to Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=360><b>Select all AFC-Core devices</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=360><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allzones</table></td></tr>";

		my $allsones = "";
		my ($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, devices.zone_id FROM smart".$homeid.".devices LEFT JOIN smart".$homeid.".ip_ase ON ip_ase.device_id = devices.id WHERE (ip_ase.device_type & 0x100) = 0x100 ORDER BY devices.id");
		my %sonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$allsones .= "</tr>";
			}
			$sonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$allsones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"s$did\"".((exists $FORM{"s$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$allsones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"s$did"}) {
				$ssel[$sscnt] = $did;
				$sscnt ++;
			}
		}
		undef $all;
		if ($allsones eq "") {		# no Sensor-POE
			$allsones = "<tr><td><br><b>No Sensor-POE devices connected to Core $hid</td></tr>";
		} else {
			$allsones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"schk[]\" type=\"checkbox\" onChange=\"checkSAll()\"></td><td width=360><b>Select all Sensor-POE</td><td width=10><input name=\"sunchk[]\" type=\"checkbox\" onChange=\"uncheckSAll();\"></td><td width=360><b>Select none</td></tr>".$allsones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allsones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allsones</table></td></tr>";
		
		my $alldones = "";
		($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, (SELECT value_ FROM smart".$homeid.".vens_list WHERE vens_list.cots_id = devices.xbee_addr64 AND vens_list.name_ = 'thermostat.venstar_zones' LIMIT 1) FROM smart".$homeid.".devices WHERE device_type = 83");
		my %donames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			$desc =~ s/\%20/ /gi;
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$alldones .= "</tr>";
			}
			$donames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$alldones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"d$did\"".((exists $FORM{"d$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$alldones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"d$did"}) {
				$dsel[$dscnt] = $did;
				$dscnt ++;
			}
		}
		undef $all;
		if ($alldones eq "") {		# no Venstars
			$alldones = "<tr><td><br><b>No Venstar thermostats connected to Core $hid</td></tr>";
		} else {
			$alldones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"dchk[]\" type=\"checkbox\" onChange=\"checkDAll()\"></td><td width=360><b>Select all Venstar thermostats</td><td width=10><input name=\"dunchk[]\" type=\"checkbox\" onChange=\"uncheckDAll();\"></td><td width=360><b>Select none</td></tr>".$alldones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$alldones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$alldones</table></td></tr>";

		my %sinzone = ();
		{
			my $all = $db->selectall_arrayref("SELECT zone_id, value_ FROM smart".$homeid.".hvac_zones WHERE option_ = 'baseboards.sinope'");
			foreach my $row (@$all) {
				my @zid = split(/\,/, @$row[1]);
				foreach my $sid (@zid) {
					$sinzone{$sid} = @$row[0];
				}
			}
			undef $all;
		}
		my $alltones = "";
		($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, CONV(CONCAT(SUBSTR(xbee_addr64,7,2),SUBSTR(xbee_addr64,5,2),SUBSTR(xbee_addr64,3,2),(SUBSTR(xbee_addr64,1,2))), 16, 10) AS sid FROM smart".$homeid.".devices WHERE device_type = 82");
		my %tonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = $sinzone{@$row[2]} + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$alltones .= "</tr>";
			}
			$tonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$alltones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"t$did\"".((exists $FORM{"t$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$alldones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"t$did"}) {
				$tsel[$tscnt] = $did;
				$tscnt ++;
			}
		}
		undef $all;
		if ($alltones eq "") {		# no Sinope
			$alltones = "<tr><td><br><b>No Sinope thermostats connected to Core $hid</td></tr>";
		} else {
			$alltones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"tchk[]\" type=\"checkbox\" onChange=\"checkTAll()\"></td><td width=360><b>Select all Sinope thermostats</td><td width=10><input name=\"tunchk[]\" type=\"checkbox\" onChange=\"uncheckTAll();\"></td><td width=360><b>Select none</td></tr>".$alltones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$alltones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$alltones</table></td></tr>";

		my $coredesc = 	"<b>Core $hid</b> : <b>$desc</b>";
		my $allcones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr>
				<tr><td width=10 style=\"background-color: #eef;\"><input type=\"checkbox\" name=\"c1\"".((exists $FORM{"c1"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #eef;\">$coredesc : System uptime</td>
				<td width=10 style=\"background-color: #efe;\"><input type=\"checkbox\" name=\"c2\"".((exists $FORM{"c2"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #efe;\">$coredesc : Tunnel uptime</td></tr>
				<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr>
				</table></td></tr>";
		my $cscnt = 0;
		{
			$iszones ++;
			$hiders{iszones} ++;
			if ((exists $FORM{"c1"}) || (exists $FORM{"c2"})) {
				$cscnt ++;
			}
		}

		my %isers = ();
		my $iserh = "";
		{
			my $all = $db->selectall_arrayref("SELECT cots_id, name_, value_ FROM smart".$homeid.".vens_list WHERE name_ IN ('iserial.serial', 'iserial.name', 'iserial.timestamp', 'iserial.pulsea', 'iserial.pulseb', 'iserial.pulsec')");
			foreach my $row (@$all) {
				$isers{@$row[0]}{@$row[1]} = @$row[2];
			}
			undef $all;
			($iserh) = $db->selectrow_array("SELECT value_ FROM smart".$homeid.".hvac WHERE option_ = 'iserial.host'");
		}
		my %subdevs = ();
		{
			my $all = $db->selectall_arrayref("SELECT id, brand, model FROM sub_devices WHERE model IS NOT NULL");
			foreach my $row (@$all) {
				$subdevs{@$row[0]} = @$row[1]." ".@$row[2];
			}
			undef $all;
		}
		my $all = $db->selectall_arrayref("SELECT cots_id FROM smart".$homeid.".vens_list WHERE name_ = 'iserial.serial'");
		my $alliones = "";
		my %ionames = ();
		my %iionames = ();
		($ii, $iii) = (0, 0);
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $zdesc = "<b>".$isers{$zid}{"iserial.name"}."</b>, s/n: ".$zid." @ ".$iserh;
			if ($ii == 0) {
				$alliones .= "</tr>";
			}
			$ionames{$zid} = $zdesc;
			$iionames{$zid} = $isers{$zid}{"iserial.name"};
			$alliones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"i$zid\"".((exists $FORM{"i$zid"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 2) {
				$ii = 0;
				$alliones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"i$zid"}) {
				$isel[$iscnt] = $zid;
				$iscnt ++;
			}
			my @pinp = ("a", "b", "c");
			my $pcnt = 1;
			foreach my $pnp (@pinp) {
				if ($isers{$zid}{"iserial.pulse".$pnp} > 0) {
					if ($ii == 0) {
						$alliones .= "</tr>";
					}
					my $zzid = $zid.$pnp;
					my $sdev = $isers{$zid}{"iserial.pulse".$pnp};
					my $zzdesc = "<b>".$subdevs{$sdev}."</b> @ ".$isers{$zid}{"iserial.name"}.", Pulse input $pcnt";
					$ionames{$zzid} = "<b>".$subdevs{$sdev}."</b> @ ".$isers{$zid}{"iserial.name"}.", #".$pcnt;
					$iionames{$zzid} = $subdevs{$sdev};
					$alliones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"i$zzid\"".((exists $FORM{"i$zzid"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zzdesc</td>";
					$pcnt ++;
					$ii ++;
					$iii ++;
					if ($ii == 2) {
						$ii = 0;
						$alliones .= "</tr>";
						$iii ++;
					}
					if (exists $FORM{"i$zzid"}) {
						$isel[$iscnt] = $zzid;
						$iscnt ++;
					}
				}
			}
		}
		undef $all;
		if ($alliones eq "") {		# no iSerial
			$alliones = "<tr><td><br><b>No iSerial submeters defined on Core $hid</td></tr>";
		} else {
			$alliones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"ichk[]\" type=\"checkbox\" onChange=\"checkIAll()\"></td><td width=360><b>Select all iSerial submeters</td><td width=10><input name=\"iunchk[]\" type=\"checkbox\" onChange=\"uncheckIAll();\"></td><td width=360><b>Select none</td></tr>".$alliones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$alliones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$alliones</table></td></tr>";
		
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		$timesel = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$timesel</table></td></tr>";

		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if (($zscnt == 0) && ($sscnt == 0) && ($dscnt == 0) && ($tscnt == 0) && ($cscnt == 0) && ($iscnt == 0)) {
				$progmsg .= "<font color=red><b>At least one report must be selected";
			} else {
				for my $zz (0 .. ($zscnt - 1)) {
					my $did = $zsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 0, 4, 0, 0, 0, 0)");
				}
				for my $zz (0 .. ($sscnt - 1)) {
					my $did = $ssel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 1, 4, 0, 0, 0, 0)");
				}
				for my $zz (0 .. ($dscnt - 1)) {
					my $did = $dsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 2, 4, 0, 0, 0, 0)");
				}
				for my $zz (0 .. ($tscnt - 1)) {
					my $did = $tsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 3, 4, 0, 0, 0, 0)");
				}
				if (exists $FORM{"c1"}) {		# Core uptime
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, 1, 1, '$datef', '$datet', $timezone, 4, 4, 0, 0, 0, 0)");
				}
				if (exists $FORM{"c2"}) {		# Core tunnel uptime
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, 2, 2, '$datef', '$datet', $timezone, 4, 4, 0, 0, 0, 0)");
				}
				{
					my %bc = ("a", 1, "b", 2, "c", 3);
					my $zid = 0;		# iserial meters
					for my $zz (0 .. ($iscnt - 1)) {
						my $did = $isel[$zz];
						if ($did =~ m/^(\d+)([a-z])$/) {
							$did = $1;
							$zid = $bc{$2};
						}
						$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 5, 4, 0, 0, 0, 0)");
					}
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my @ridlist = ("AFC", "Sensor", "Venstar", "Sinope", "Core", "iSerial");
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = "uptime\_".$ridlist[$rtype]."\_$sftime-$sttime\_Core$cid".(($rtype == 4)?"":"\_Device$did")."\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
#			print "Content-Type:application/x-download\n";
#			print "Content-Disposition:attachment;filename=$outname\n\n";
#			print $tabdata;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my @devtypes = ("iLoVAC", "CDGS1", "Venstar", "Sinope", "Core", "iSerial");
		my @crtypes = ("", $desc, "$desc Tunnel");
		my @idevtypes = ("iSerial", "Meter 1", "Meter 2", "Meter 3");
		my $tzoff = gettzsecoff();
		{
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, device_id, report_id, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 4 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $did = @$row[6];
				my $rid = @$row[7] + 0;
				my $dtype = $devtypes[$rid];
				my $sts = @$row[8];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=$id\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				my $dname = $allnames{$did};
				if ($rid == 5) {			# iserial					
					my @cb = ("", "a", "b", "c");
					$did .= $cb[$zid];
					$dname = $iionames{$did};
					$dtype = $idevtypes[$zid];
				} elsif ($rid == 4) {			# core reports
					$dname = $crtypes[$zid];
				} else {
					if ($zid > 0) {
						$dname .= " @ ".$znames{$zid};
					}
				}
				if (length($dname) >= 40) {
					$dname = substr($dname, 0, 35)."..";
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">$dtype</td>
						<td nowrap=\"nowrap\">$dname</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"70\"><small>Device type</td>
						<td width=\"210\"><small>Device alias and Zone</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $timesel.$allcones.$allzones.$allsones.$alldones.$alltones.$alliones.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkDAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('d')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckDAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('d')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkTAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('t')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckTAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('t')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkIAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('i')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckIAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('i')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# peak demand events report

if (($uimode eq "reports") && ($uismode eq "peak") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
#	my $timezone = (exists $FORM{timezone})?$FORM{timezone}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
        my $maxrec = $perpage;
        my $coresel = $FORM{coresel} + 0;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $homelist = "";
	my $stylecnt = 0;
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my @rsel = ();
		my ($zscnt, $rscnt, $crcnt) = (0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 3 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		$homelist .= "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>";		# zones part
		my ($ii, $iii) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT id, description FROM smart".$homeid.".zones WHERE id > 2");		# all except temp+master
		my $allzones = "";
		my %zonames = ("0", "<i>All zones at core</i>");
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $zdesc = @$row[1];
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			if (length($zdesc) > 30) {
				$zdesc = substr($zdesc, 0, 30)." ..";
			}
			$zonames{$zid} = $zdesc;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$zid\"".((exists $FORM{"z$zid"})?" checked=\"checked\"":"")."></td><td width=180 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 4) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$zid"}) {
				$zsel[$zscnt] = $zid;
				$zscnt ++;
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no zones
			$allzones = "<tr><td><br><b>No zones defined on Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=180><b>Select all zones</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=180><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones .= "</table></td></tr>";
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		my $reports = "<tr><td colspan=4 height=3><img src=\"./blank.gif\" height=3 width=1></td></tr>";
		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if ($zscnt == 0) {
				$progmsg .= "<font color=red><b>At least one zone must be selected";
			} else {
				for my $zz (0 .. ($zscnt - 1)) {
					my $zid = $zsel[$zz];
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, NULL, '$datef', '$datet', $timezone, 0, 3, 0, 0, 0, 0)");
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $zid, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, zone_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = "peakdemand_$sftime-$sttime\_Core$cid\_Zone$zid\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
#			print "Content-Type:application/x-download\n";
#			print "Content-Disposition:attachment;filename=$outname\n\n";
#			print $tabdata;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my $tzoff = gettzsecoff();
		{
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, report_id, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 3 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $rid = @$row[6];
				my $sts = @$row[7];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=$id\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
#					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Download</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">".$zonames{$zid}."</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"280\"><small>Zone</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $allzones.$timesel.$reports.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckRAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('r')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# devices report

if (($uimode eq "reports") && ($uismode eq "devices") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
#	my $timezone = (exists $FORM{timezone})?$FORM{timezone}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
        my $maxrec = $perpage;
        my $coresel = $FORM{coresel} + 0;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $homelist = "";
	my $stylecnt = 0;
	my @rfiles = ("AFC", "Sensor", "Venstar", "Sinope", "AFC_Heat", "Ven_Runtime");
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my @ssel = ();
		my @dsel = ();
		my @tsel = ();
		my ($zscnt, $rscnt, $crcnt, $sscnt, $dscnt, $tscnt) = (0, 0, 0, 0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 2 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		my %znames = ();
		{
			my $all = $db->selectall_arrayref("SELECT id, description FROM smart".$homeid.".zones WHERE id > 2");
			foreach my $row (@$all) {
				$znames{@$row[0]} = @$row[1];
			}
			undef $all;
		}

		my %allnames = ();
		my %allzones = ();
		my ($ii, $iii) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, devices.zone_id FROM smart".$homeid.".devices LEFT JOIN smart".$homeid.".ip_ase ON ip_ase.device_id = devices.id WHERE (ip_ase.device_type & 0x2000) = 0x2000 ORDER BY devices.id");
		my $allzones = "";
		my %zonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			$zonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$did\"".((exists $FORM{"z$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 2) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$did"}) {
				$zsel[$zscnt] = $did;
				$zscnt ++;
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no AFC
			$allzones = "<tr><td><br><b>No AFC-Core devices connected to Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=360><b>Select all AFC-Core devices</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=360><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allzones</table></td></tr>";

		my $allsones = "";
		my ($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, devices.zone_id FROM smart".$homeid.".devices LEFT JOIN smart".$homeid.".ip_ase ON ip_ase.device_id = devices.id WHERE (ip_ase.device_type & 0x100) = 0x100 ORDER BY devices.id");
		my %sonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$allsones .= "</tr>";
			}
			$sonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$allsones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"s$did\"".((exists $FORM{"s$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$allsones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"s$did"}) {
				$ssel[$sscnt] = $did;
				$sscnt ++;
			}
		}
		undef $all;
		if ($allsones eq "") {		# no Sensor-POE
			$allsones = "<tr><td><br><b>No Sensor-POE devices connected to Core $hid</td></tr>";
		} else {
			$allsones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"schk[]\" type=\"checkbox\" onChange=\"checkSAll()\"></td><td width=360><b>Select all Sensor-POE</td><td width=10><input name=\"sunchk[]\" type=\"checkbox\" onChange=\"uncheckSAll();\"></td><td width=360><b>Select none</td></tr>".$allsones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allsones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allsones</table></td></tr>";
		
		my %vnames = ();
		{
			my $all = $db->selectall_arrayref("SELECT cots_id, value_ FROM smart".$homeid.".vens_list WHERE cots_id > 0 AND name_ = 'name'");
			foreach my $row (@$all) {
				my $desc = @$row[1];
				$desc =~ s/\%20/ /gi;
				$vnames{@$row[0]} = $desc;
			}
			undef $all;
		}
		my $alldones = "";
		($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, (SELECT value_ FROM smart".$homeid.".vens_list WHERE vens_list.cots_id = devices.xbee_addr64 AND vens_list.name_ = 'thermostat.venstar_zones' LIMIT 1), devices.xbee_addr64 FROM smart".$homeid.".devices WHERE device_type = 83");
		my %donames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			$desc =~ s/\%20/ /gi;
			if ($desc ne $vnames{@$row[3]}) {
				$desc = $vnames{@$row[3]};
				$db->do("UPDATE smart".$homeid.".devices SET description = '$desc' WHERE id = $did");		# fix venstar name
			}
			my $zid = @$row[2] + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$alldones .= "</tr>";
			}
			$donames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$alldones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"d$did\"".((exists $FORM{"d$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$alldones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"d$did"}) {
				$dsel[$dscnt] = $did;
				$dscnt ++;
			}
		}
		undef $all;
		if ($alldones eq "") {		# no Venstars
			$alldones = "<tr><td><br><b>No Venstar thermostats connected to Core $hid</td></tr>";
		} else {
			$alldones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"dchk[]\" type=\"checkbox\" onChange=\"checkDAll()\"></td><td width=360><b>Select all Venstar thermostats</td><td width=10><input name=\"dunchk[]\" type=\"checkbox\" onChange=\"uncheckDAll();\"></td><td width=360><b>Select none</td></tr>".$alldones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$alldones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$alldones</table></td></tr>";

		my %sinzone = ();
		{
			my $all = $db->selectall_arrayref("SELECT zone_id, value_ FROM smart".$homeid.".hvac_zones WHERE option_ = 'baseboards.sinope'");
			foreach my $row (@$all) {
				my @zid = split(/\,/, @$row[1]);
				foreach my $sid (@zid) {
					$sinzone{$sid} = @$row[0];
				}
			}
			undef $all;
		}
		my $alltones = "";
		($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT devices.id, devices.description, CONV(CONCAT(SUBSTR(xbee_addr64,7,2),SUBSTR(xbee_addr64,5,2),SUBSTR(xbee_addr64,3,2),(SUBSTR(xbee_addr64,1,2))), 16, 10) AS sid FROM smart".$homeid.".devices WHERE device_type = 82 AND hardware_type = 4");
		my %tonames = ();
		foreach my $row (@$all) {
			my $did = @$row[0];
			my $desc = @$row[1];
			my $zid = $sinzone{@$row[2]} + 0;
			my $zdesc = "<b>$desc</b>".(($zid <= 2)?"":" @ ".$znames{$zid});
			if ($jj == 0) {
				$alltones .= "</tr>";
			}
			$tonames{$zid} = $zdesc;
			$allnames{$did} = $desc;
			$allzones{$did} = $zid;
			$alltones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"t$did\"".((exists $FORM{"t$did"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
			$jj ++;
			$jjj ++;
			if ($jj == 2) {
				$jj = 0;
				$alldones .= "</tr>";
				$jjj ++;
			}
			if (exists $FORM{"t$did"}) {
				$tsel[$tscnt] = $did;
				$tscnt ++;
			}
		}
		undef $all;
		if ($alltones eq "") {		# no Sinope
			$alltones = "<tr><td><br><b>No Sinope thermostats connected to Core $hid</td></tr>";
		} else {
			$alltones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"tchk[]\" type=\"checkbox\" onChange=\"checkTAll()\"></td><td width=360><b>Select all Sinope thermostats</td><td width=10><input name=\"tunchk[]\" type=\"checkbox\" onChange=\"uncheckTAll();\"></td><td width=360><b>Select none</td></tr>".$alltones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$alltones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$alltones</table></td></tr>";
		
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		$timesel = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$timesel</table></td></tr>";

		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if (($zscnt == 0) && ($sscnt == 0) && ($dscnt == 0) && ($tscnt == 0)) {
				$progmsg .= "<font color=red><b>At least one device must be selected";
			} else {
				for my $zz (0 .. ($zscnt - 1)) {
					my $did = $zsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 0, 2, 0, 0, 0, 0)");
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 4, 2, 0, 0, 0, 0)");	# AFC heat load report
				}
				for my $zz (0 .. ($sscnt - 1)) {
					my $did = $ssel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 1, 2, 0, 0, 0, 0)");
				}
				for my $zz (0 .. ($dscnt - 1)) {
					my $did = $dsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 2, 2, 0, 0, 0, 0)");
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 5, 2, 0, 0, 0, 0)");	# Venstar runtime report
				}
				for my $zz (0 .. ($tscnt - 1)) {
					my $did = $tsel[$zz];
					my $zid = $allzones{$did} + 0;
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, 3, 2, 0, 0, 0, 0)");
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = "devices_".$rfiles[$rtype]."\_$sftime-$sttime\_Core$cid\_Device$did\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
#			print "Content-Type:application/x-download\n";
#			print "Content-Disposition:attachment;filename=$outname\n\n";
#			print $tabdata;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my @devtypes = ("iLoVAC", "CDGS1", "Venstar", "Sinope", "Heat Load", "Ven.runtime");
		my $tzoff = gettzsecoff();
		{
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, device_id, report_id, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 2 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $did = @$row[6];
				my $rid = @$row[7] + 0;
				my $dtype = $devtypes[$rid];
				my $sts = @$row[8];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=$id\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				my $dname = $allnames{$did};
				if ($zid > 0) {
					$dname .= " @ ".$znames{$zid};
				}
				if (length($dname) >= 40) {
					$dname = substr($dname, 0, 35)."..";
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">$dtype</td>
						<td nowrap=\"nowrap\">$dname</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"70\"><small>Device type</td>
						<td width=\"210\"><small>Device alias and Zone</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $timesel.$allzones.$allsones.$alldones.$alltones.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkDAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('d')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckDAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('d')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkTAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('t')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckTAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('t')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# submeters report

if (($uimode eq "reports") && ($uismode eq "submeters") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $pencnt = 0;
	my %hiders = ("iscore", "1", "nocore", "0", "iszones", "0");
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:10) + 0;
#	my $timezone = (exists $FORM{timezone})?$FORM{timezone}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	my $hidfilter = ($uaccess < 2)?"systems.house_id IN ($housemask)":"systems.house_id > 0";
	my $sfilter = ($search eq "")?$hidfilter:"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
        my $maxrec = $perpage;
        my $coresel = $FORM{coresel} + 0;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $homelist = "";
	my $stylecnt = 0;
	if (($allrec == 1) || ($coresel)) {		# core selected
		$hiders{"iscore"} = 0;
		$hiders{"nocore"} = 1;
		my @zsel = ();
		my @ssel = ();
		my ($zscnt, $rscnt, $crcnt, $sscnt) = (0, 0, 0, 0);
		if ($coresel) {
			$sfilter = " systems.house_id = $coresel";
		}
		my ($hid, $conn, $desc, $namea, $nameb, $company, $sysip) = $db->selectrow_array("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company, systems.ip_address FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter");
		$coresel = $hid;
		my $homeid = sprintf("%05d", $hid);
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		$maxrec = $perpage;
		$fromrec = $maxrec * ($curpage - 1);
		($allrec) = $db->selectrow_array("SELECT COUNT(id) FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 1 AND status IN (0,1,2,3,4)");
		$maxpage = floor($allrec / $maxrec) + 1;
		if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
			$maxpage --;
		}		
		if ($sysip eq "127.0.0.1") {
			my $hwfile = $selfpath."/tmp/system.status";
			if (-e $hwfile) {
				open(INF, "<$hwfile");
				while(<INF>) {
					my $inline = $_;
					chomp($inline);
					if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\,  (.+)\,  load average: (.+)$/) {		# cpu and uptime
						$uptime = $1;
					}
				}
				close(INF);
			}
			my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
			$tstamp = gettstamp();
		}
		my $owname = "";
		if (($namea ne "") || ($nameb ne "")) {
			$owname = $namea." ".$nameb;
		}
		if ($company ne "") {
			if ($owname eq "") {
				$owname = $company;
			} else {
				$owname = $company." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Core <b>$hid</b></td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$desc</b></td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Site Administrator</td>
				<td nowrap=\"nowrap\" width=\"270\"><b>$owname</b></td>
			</tr>";
		if ($sysip ne "127.0.0.1") {
			$homelist .= "<tr style=\"background-color: #f0fff0;\">
					<td nowrap=\"nowrap\" width=\"100\">Last connected</td>
					<td nowrap=\"nowrap\" width=\"270\">$conn</td>
				</tr>";
		}
		$homelist .= "<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">Local timestamp</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($tstamp ne "")?$tstamp:"Unavailable")."</td>
			</tr>
			<tr style=\"background-color: #f0fff0;\">
				<td nowrap=\"nowrap\" width=\"100\">System uptime</td>
				<td nowrap=\"nowrap\" width=\"270\">".(($uptime ne "")?$uptime:"Unavailable")."</td>
			</tr>
			<tr><td nowrap=\"nowrap\" colspan=4 width=770><div class=in2></div></td></tr>\n";
		my %isers = ();
		my $iserh = "";
		{
			my $all = $db->selectall_arrayref("SELECT cots_id, name_, value_ FROM smart".$homeid.".vens_list WHERE name_ IN ('iserial.serial', 'iserial.name', 'iserial.timestamp', 'iserial.pulsea', 'iserial.pulseb', 'iserial.pulsec')");
			foreach my $row (@$all) {
				$isers{@$row[0]}{@$row[1]} = @$row[2];
			}
			undef $all;
			($iserh) = $db->selectrow_array("SELECT value_ FROM smart".$homeid.".hvac WHERE option_ = 'iserial.host'");
		}
		my %subdevs = ();
		{
			my $all = $db->selectall_arrayref("SELECT id, brand, model FROM sub_devices WHERE model IS NOT NULL");
			foreach my $row (@$all) {
				$subdevs{@$row[0]} = @$row[1]." ".@$row[2];
			}
			undef $all;
		}
		my ($ii, $iii) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT cots_id FROM smart".$homeid.".vens_list WHERE name_ = 'iserial.serial'");
		my $allzones = "";
		my %zonames = ();
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $zdesc = "<b>".$isers{$zid}{"iserial.name"}."</b>, s/n: ".$zid." @ ".$iserh;
			if ($ii == 0) {
				$allzones .= "</tr>";
			}
			$zonames{$zid} = $zdesc;
			$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$zid\"".((exists $FORM{"z$zid"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zdesc</td>";
			$ii ++;
			$iii ++;
			if ($ii == 2) {
				$ii = 0;
				$allzones .= "</tr>";
				$iii ++;
			}
			if (exists $FORM{"z$zid"}) {
				$zsel[$zscnt] = $zid;
				$zscnt ++;
			}
			my @pinp = ("a", "b", "c");
			my $pcnt = 1;
			foreach my $pnp (@pinp) {
				if ($isers{$zid}{"iserial.pulse".$pnp} > 0) {
					if ($ii == 0) {
						$allzones .= "</tr>";
					}
					my $zzid = $zid.$pnp;
					my $sdev = $isers{$zid}{"iserial.pulse".$pnp};
					my $zzdesc = "<b>".$subdevs{$sdev}."</b> @ ".$isers{$zid}{"iserial.name"}.", Pulse input $pcnt";
					$zonames{$zzid} = "<b>".$subdevs{$sdev}."</b> @ ".$isers{$zid}{"iserial.name"}.", #".$pcnt;
					$allzones .= "<td width=10 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"z$zzid\"".((exists $FORM{"z$zzid"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($iii & 1)?"eef":"efe").";\">$zzdesc</td>";
					$pcnt ++;
					$ii ++;
					$iii ++;
					if ($ii == 2) {
						$ii = 0;
						$allzones .= "</tr>";
						$iii ++;
					}
					if (exists $FORM{"z$zzid"}) {
						$zsel[$zscnt] = $zzid;
						$zscnt ++;
					}
				}
			}
		}
		undef $all;
		my $iszones = 0;
		if ($allzones eq "") {		# no iSerial
			$allzones = "<tr><td><br><b>No iSerial submeters defined on Core $hid</td></tr>";
		} else {
			$allzones = "<tr><td width=10><input name=\"zchk[]\" type=\"checkbox\" onChange=\"checkAll()\"></td><td width=360><b>Select all iSerial submeters</td><td width=10><input name=\"zunchk[]\" type=\"checkbox\" onChange=\"uncheckAll();\"></td><td width=360><b>Select none</td></tr>".$allzones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allzones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allzones</table></td></tr>";

		my $allsones = "";
		my ($jj, $jjj) = (0, 0);
		my $all = $db->selectall_arrayref("SELECT sub_connected.id, devices.description, sub_devices.brand, sub_devices.model, devices.zone_id as zid, (SELECT description FROM smart".$homeid.".zones WHERE id = zid), (SELECT hvac_zones.value_ FROM smart".$homeid.".hvac_zones WHERE hvac_zones.option_ = 'afc_poe.sub_meter' AND hvac_zones.zone_id = sub_connected.device_id) FROM smart".$homeid.".sub_connected LEFT JOIN smart".$homeid.".devices ON devices.id = sub_connected.device_id LEFT JOIN smart".$homeid.".sub_devices ON sub_devices.id = sub_connected.sub_id WHERE devices.id IS NOT NULL");
		my %sonames = ();
		foreach my $row (@$all) {
			my $zid = @$row[0];
			my $sub = @$row[6];
			if ($sub == 1) {		# AFC must have submeter enabled
				my $zdesc = "<b>".@$row[2]." ".@$row[3]."</b> @ ".@$row[1];
				if ($jj == 0) {
					$allsones .= "</tr>";
				}
				$sonames{$zid} = $zdesc;
				$allsones .= "<td width=10 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\"><input type=\"checkbox\" name=\"s$zid\"".((exists $FORM{"s$zid"})?" checked=\"checked\"":"")."></td><td width=360 style=\"background-color: #".(($jjj & 1)?"eef":"efe").";\">$zdesc</td>";
				$jj ++;
				$jjj ++;
				if ($jj == 2) {
					$jj = 0;
					$allsones .= "</tr>";
					$jjj ++;
				}
				if (exists $FORM{"s$zid"}) {
					$ssel[$sscnt] = $zid;
					$sscnt ++;
				}
			}
		}
		undef $all;
		if ($allsones eq "") {		# no AFC-Core
			$allsones = "<tr><td><br><b>No AFC-Core submeters defined on Core $hid</td></tr>";
		} else {
			$allsones = "<tr><td colspan=4 height=5><img src=\"./blank.gif\" height=5 width=1></td></tr><tr><td width=10><input name=\"schk[]\" type=\"checkbox\" onChange=\"checkSAll()\"></td><td width=360><b>Select all AFC-Core submeters</td><td width=10><input name=\"sunchk[]\" type=\"checkbox\" onChange=\"uncheckSAll();\"></td><td width=360><b>Select none</td></tr>".$allsones;
			$iszones ++;
			$hiders{iszones} ++;
		}
		$allsones = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$allsones</table></td></tr>";
		
		my $timesel = "";
		my $timezone = getoffset();
		if ($iszones) {
			$dayf = fixdate($dayf, $monthf, $yearf);
			$dayt = fixdate($dayt, $montht, $yeart);
			my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
			my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			if ($shdatef > $shdatet) {
				($montht, $monthf) = ($monthf, $montht);
				($dayt, $dayf) = ($dayf, $dayt);
				($yeart, $yearf) = ($yearf, $yeart);
			}
			my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
			for my $year (2018 .. 2030) {
				$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
				$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
			}
			for my $month (1 .. 12) {
				$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
				$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
			}
			for my $day (1 .. 31) {
				$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
				$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
			}
			$timesel = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				<tr>
					<td nowrap="nowrap" width="80">Dates Range:</td>
					<td class="stdbold"><select name="year_f" size="1">$lyearf</td>
					<td class="stdbold"><select name="month_f" size="1">$lmonthf</td>
					<td class="stdbold"><select name="day_f" size="1">$ldayf</td>
					<td class="stdbold">&nbsp;-&nbsp;</td>
					<td class="stdbold"><select name="year_t" size="1">$lyeart</td>
					<td class="stdbold"><select name="month_t" size="1">$lmontht</td>
					<td class="stdbold"><select name="day_t" size="1">$ldayt</td>
				</tr> 
				</table></td></tr>
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
EOF
		}
		my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
		my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
		$timesel = "<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>$timesel</table></td></tr>";

		my $progress = "";
		my $progmsg = "";
		my $action = $FORM{"action"};
		if ($action eq "save") {
			$progmsg = "<br>";
			if (($zscnt == 0) && ($sscnt == 0)) {
				$progmsg .= "<font color=red><b>At least one meter must be selected";
			} else {
				my %bc = ("a", 1, "b", 2, "c", 3);
				my $rid = 0;
				my $zid = 0;		# iserial meters
				for my $zz (0 .. ($zscnt - 1)) {
					my $did = $zsel[$zz];
					if ($did =~ m/^(\d+)([a-z])$/) {
						$did = $1;
						$rid = $bc{$2};
					}
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, $rid, 1, 0, 0, 0, 0)");
					for my $zzid (1 .. 6) {
						$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zzid, $did, '$datef', '$datet', $timezone, $rid, 1, 6, 0, 0, 0)");	# dummy for graph needs
					}
				}
				$zid = 1;		# sensor-poe meters
				$rid = 0;
				for my $zz (0 .. ($sscnt - 1)) {
					my $did = $ssel[$zz];
					$db->do("INSERT INTO reports VALUES (NULL, NOW(), NOW(), $clientid, $sessid, $coresel, $zid, $did, '$datef', '$datet', $timezone, $rid, 1, 0, 0, 0, 0)");
				}
			}
		} elsif (($action eq "cancel") || ($action eq "stop")) {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 4, updated = NOW() WHERE id = $repid AND status IN (0,1)");		# set to stopped
		} elsif ($action eq "restart") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 0, updated = NOW() WHERE id = $repid AND status IN (3,4)");		# set to pending
		} elsif ($action eq "remove") {
			my $repid = $FORM{"repid"} + 0;
			$db->do("UPDATE reports SET status = 5, updated = NOW() WHERE id = $repid AND status IN (0,1,2,3,4)");		# set to removed
		} elsif ($action eq "download") {
			my @dlist = ("iSerial", "Sensor");
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype, $zid) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id, zone_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repname = "submetering\_".$dlist[$zid]."\_$sftime-$sttime\_Core$cid\_Device$did\_$repid";
			my $repurl = "/charts/$repname.csv";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
#			print "Content-Type:application/x-download\n";
#			print "Content-Disposition:attachment;filename=$outname\n\n";
#			print $tabdata;
		} elsif ($action eq "graph") {
			my $repid = $FORM{"repid"} + 0;
			my ($cid, $did, $ftime, $ttime, $tzone, $rtype) = $db->selectrow_array("SELECT core_id, device_id, FLOOR(datefrom + 0), FLOOR(dateto + 0), timezone, report_id FROM reports WHERE id = $repid");
			my $sftime = substr($ftime, 0, 8);
			my $sttime = substr($ttime, 0, 8);
			my $repurl = "/dygraphs/graphs.html?repid=$repid";
			print "Content-type: text/html\n\n";
			print "<html><HEAD><META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=$repurl\"><script>setTimeout(\"window.close()\",1000);</script></HEAD></html>\n";
			$db->disconnect();
			exit;
		}
		my @statuses = ("Pending", "Processing", "Finished", "Error", "Cancelled", "Deleted");
		my $tzoff = gettzsecoff();
		{
			my @gnames = ("Current Load", "Line Voltage", "Power Load", "Frequency", "Power Consumed", "Power Sold", "KVARH");
			my $allrows = 0;
			my $all = $db->selectall_arrayref("SELECT id, updated, zone_id, DATE_FORMAT(datefrom, '%y.%m.%d'), DATE_FORMAT(dateto, '%y.%m.%d'), timezone, device_id, report_id, status FROM reports WHERE user_id = $clientid AND core_id = $coresel AND report_tab = 1 AND status IN (0,1,2,3,4) ORDER BY id DESC LIMIT $fromrec, $maxrec");
			foreach my $row (@$all) {
				$allrows ++;
				my $id = @$row[0];
				my $zid = @$row[2];
				my $datec = dateLocal(@$row[1], $tzoff, 8);
				my $datef = @$row[3];
				my $datet = @$row[4];
				my $tzone = sprintf("GMT%+05d", @$row[5]);
				$tzone =~ s/(...)(..)$/$1\:$2/;
				my $did = @$row[6];
				my $rid = @$row[7] + 0;
				my $sts = @$row[8];
				my $actions = "";
				if ($sts == 0) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=cancel&repid=$id\" class=\"navi\">Cancel</a>";
					$pencnt ++;
				} elsif ($sts == 1) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=stop&repid=$id\" class=\"navi\">Stop</a>";
					$pencnt ++;
				} elsif ($sts == 2) {
					my @glinks = ();
					for my $ii (0 .. $#gnames) {
						@glinks[$ii] = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=graph&coresel=$coresel&repid=".($id + $ii)."\" class=\"navi\">".$gnames[$ii]."</a>";
					}
					my $occupop = <<EOF;
						<div style="position: relative; width: 0; height: 0">
						<div id="osch$id" style="position: absolute; left: 65px; top: -55px; visibility: hidden;">
						<table style="border: 1px solid black; padding: 3px; background-color: #F0F0F0;">
							<td width=90 nowrap="nowrap" align=left class="stdbold">$glinks[0]</td><td width=20 valign=top nowrap="nowrap" align=right rowspan=2><input type="button" value="X" onClick="showSch($id);" style="color:#F00;"></td></tr>
							<td width=90 nowrap="nowrap" align=left class="stdbold">$glinks[1]</td></tr>
							<td width=110 nowrap="nowrap" align=left colspan=2 class="stdbold">$glinks[2]</td></tr>
							<td width=110 nowrap="nowrap" align=left colspan=2 class="stdbold">$glinks[3]</td></tr>
							<td width=110 nowrap="nowrap" align=left colspan=2 class="stdbold">$glinks[4]</td></tr>
							<td width=110 nowrap="nowrap" align=left colspan=2 class="stdbold">$glinks[5]</td></tr>
							<td width=110 nowrap="nowrap" align=left colspan=2 class="stdbold">$glinks[6]</td></tr>
						</table></div></div>
EOF
					$actions = "<a target=_blank href=\"./engine.pl?mode=$uimode&submode=$uismode&action=download&coresel=$coresel&repid=$id\" class=\"navi\">Text</a>&nbsp;&nbsp;<a id=\"dev$id\" href=\"#\" onClick=\"showSch($id);\" class=\"navi\">Graph</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>$occupop";
				} elsif (($sts == 3) || ($sts == 4)) {
					$actions = "<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=restart&repid=$id\" class=\"navi\">Restart</a>&nbsp;&nbsp;<a href=\"./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel&action=remove&repid=$id\" class=\"navi\">Delete</a>";
				}
				my $dname = "";
				if ($zid == 0) {		# iserial
					my @cb = ("", "a", "b", "c");
					$did .= $cb[$rid];
					$dname = $zonames{$did};
				} elsif ($zid == 1) {		# sensor-poe
					$dname = $sonames{$did};
				}
				$progmsg .= "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td nowrap=\"nowrap\">$datec</td>
						<td nowrap=\"nowrap\">$datef - $datet ($tzone)</td>
						<td nowrap=\"nowrap\">$dname</td>
						<td nowrap=\"nowrap\">".$statuses[$sts]."</td>
						<td nowrap=\"nowrap\">$actions</td>
						</tr>\n";
			}
			undef $all;
			if (($progmsg ne "") && ($allrows)) {
				$progmsg = "<tr><td nowrap=\"nowrap\" colspan=7><div class=in5></div></td></tr><tr>
						<td width=\"120\"><small>Last update</td>
						<td width=\"190\"><small>Date range + timezone</td>
						<td width=\"280\"><small>Submetering device</td>
						<td width=\"80\"><small>Status</td>
						<td width=\"100\"><small>Action</td>
						</tr>$progmsg";
			}
		}
		if ($progmsg ne "") {
			$progress = <<EOF;
				<tr><td colspan=4 height=3><img src="./blank.gif" height=3 width=1></td></tr>
				<tr><td colspan=4 width=770><table cellpadding=0 cellspacing=0 border=0>
				$progmsg
				</table></td></tr>
EOF
		}
		$homelist .= $timesel.$allzones.$allsones.$progress;

	} elsif ($allrec > 1) {		# search in progress
		my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.connected, systems.description, systemadd.name1, systemadd.name2, systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			my $homedesc = @$row[2];
			my $owname = "";
			if ((@$row[3] ne "") || (@$row[4] ne "")) {
				$owname = @$row[3]." ".@$row[4];
			}
			if (@$row[5] ne "") {
				if ($owname eq "") {
					$owname = @$row[5];
				} else {
					$owname = @$row[5]." - ".$owname;
				}
			}
			if ($owname eq "") {
				$owname = "No name or company specified";
			} else {
				if ($owname =~ m/ \- /) {
					$owname = "<b>$owname</b>";
				} else {
					$owname = "Site administrator <b>$owname</b>";
				}
			}
			my $homeconn = @$row[1];
			$stylecnt ++;
			$homelist .= "<tr class=\"pointer".(($stylecnt & 1)?"1":"2")."\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$houseid';\">
					<td nowrap=\"nowrap\" width=\"80\">Core ID <b>$houseid</b></td>
					<td nowrap=\"nowrap\" width=\"280\"><b>$homedesc</b></td>
					<td nowrap=\"nowrap\" width=\"290\">$owname</td>
					<td nowrap=\"nowrap\" width=\"120\">$homeconn</td>
					</tr>\n";
			$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in2></div></td></tr>\n";
		}
		undef $all;
	} else {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=660 class=\"stdbold\" colspan=4><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function showSch(zid) {
			var opsch = document.selectform.opsched.value;
			if (opsch > 0) {
				if (opsch == zid) {
					document.getElementById('osch'+zid).style.visibility = 'hidden';
					document.getElementById('dev'+zid).style.color = '#000';
					document.selectform.opsched.value = 0;
				} else {
					document.getElementById('osch'+opsch).style.visibility = 'hidden';
					document.getElementById('dev'+opsch).style.color = '#000';
					document.getElementById('osch'+zid).style.visibility = 'visible';
					document.getElementById('dev'+zid).style.color = '#F00';
					document.selectform.opsched.value = zid;
				}
			} else {
				document.getElementById('osch'+zid).style.visibility = 'visible';
				document.getElementById('dev'+zid).style.color = '#F00';
				document.selectform.opsched.value = zid;
			}
			return false;
		}
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('z')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		function checkSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = true;
					}
				}
			}
		}
		function uncheckSAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].name.startsWith('s')) {
						checkboxes[i].checked = false;
					}
				}
			}
		}
		</script>
		<style>
      			.pointer1 { background-color: #fff; }
      			.pointer2 { background-color: #eee; }
      			.pointer1:hover { cursor: pointer; background-color: #ccc; }
      			.pointer2:hover { cursor: pointer; background-color: #ccc; }
    		</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (10, 20, 50);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	if ($pencnt) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"30;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&coresel=$coresel\">\n";
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--corelist--/$homelist/g;
		$inline =~ s/--coresel--/$coresel/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
	$top1class = "Top1B";
}

# graphs page

if (($uimode eq "reports") && ($uismode eq "graph") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $repid = (exists $FORM{repid})?$FORM{repid}:0;
	my ($datef, $datet, $tzone, $datett) = $db->selectrow_array("SELECT DATE_FORMAT(datefrom, '%b %e, %Y'), DATE_FORMAT(dateto, '%b %e, %Y'), timezone, DATE(dateto) FROM reports WHERE id = $repid");
	$tzone = sprintf("GMT%+05d", $tzone);
	$tzone =~ s/(...)(..)$/$1\:$2/;
	my $dateint = "$datef - $datet ($tzone)";
	my $servip = $servname;
	$servip =~ s/\:[0-9]+$//g;
	my $wsocket = (($servprot eq "https")?"wss":"ws")."://".$servip.":".(($servprot eq "https")?"8083":"8082")."/";

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--dateint--/$dateint/g;
		$inline =~ s/--enddate--/$datett/g;
		$inline =~ s/--wsocket--/$wsocket/g;
		$inline =~ s/--startdate--/$datef/g;
		$inline =~ s/--timezone--/$tzone/g;
		$inline =~ s/--repid--/$repid/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
	$top1class = "Top1B";

	$headadd .= <<EOF;
		<link href="/static/css/2.e6f51e71.chunk.css" rel="stylesheet">
		<link href="/static/css/main.c439b7f2.chunk.css" rel="stylesheet">
EOF
	$bottomadd .= <<EOF;
		<script>!function(e){function r(r){for(var n,l,i=r[0],p=r[1],f=r[2],c=0,s=[];c<i.length;c++)l=i[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in p)Object.prototype.hasOwnProperty.call(p,n)&&(e[n]=p[n]);for(a&&a(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,i=1;i<t.length;i++){var p=t[i];0!==o[p]&&(n=!1)}n&&(u.splice(r--,1),e=l(l.s=t[0]))}return e}var n={},o={1:0},u=[];function l(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,l),t.l=!0,t.exports}l.m=e,l.c=n,l.d=function(e,r,t){l.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,r){if(1&r&&(e=l(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(l.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)l.d(t,n,function(r){return e[r]}.bind(null,n));return t},l.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(r,"a",r),r},l.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},l.p="/";var i=this.webpackJsonpcello_reporting=this.webpackJsonpcello_reporting||[],p=i.push.bind(i);i.push=r,i=i.slice();for(var f=0;f<i.length;f++)r(i[f]);var a=p;t()}([])</script>
		<script src="/static/js/2.30ee727c.chunk.js">
		</script>
		<script src="/static/js/main.f580837f.chunk.js">
		</script>
EOF
}

if (((($uimode eq "reports") && ($uismode eq "master")) || (($uimode eq "partners") && ($uismode eq "master"))) && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	$dayf = fixdate($dayf, $monthf, $yearf);
	$dayt = fixdate($dayt, $montht, $yeart);
	my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
	my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
	my $repotype = (exists $FORM{repotype})?$FORM{repotype}:0;		# 0 = Cumulative, 1 = Detailed
	my @repovals = ("Cumulative", "Detailed");
	my $rrepotype = "";
	for my $ii (0 .. $#repovals) {
		$rrepotype .= "<option value=\"$ii\"".(($repotype == $ii)?" selected=\"selected\"":"").">".$repovals[$ii]."</option>";
	}
	if ($shdatef > $shdatet) {
		($montht, $monthf) = ($monthf, $montht);
		($dayt, $dayf) = ($dayf, $dayt);
		($yeart, $yearf) = ($yearf, $yeart);
	}
	my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $month (1 .. 12) {
		$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
		$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
	}
	for my $day (1 .. 31) {
		$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
		$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
	}
	my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
	my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
	my $houseid = (exists $FORM{houseid})?$FORM{houseid}:0;
	my $lhouse = "<option value=\"0\"".(($houseid == 0)?" selected=\"selected\"":"").">-- Select Core --</option>";
	{
		my $hidfilter = "systems.house_id > 0";
		if ($uaccess < 2) {
			$hidfilter = "systems.house_id IN ($housemask)";
		}
		my $all = $db->selectall_arrayref("SELECT systems.house_id, CONCAT(systemadd.name1,' ',systemadd.name2) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $hidfilter ORDER BY id");
		foreach my $row (@$all) {
			$lhouse .= "<option value=\"".@$row[0]."\"".((@$row[0] == $houseid)?" selected=\"selected\"":"").">".sprintf("%05d", @$row[0]).": ".@$row[1]."</option>";
		}
		undef $all;
	}
	my $replist = "";

	if (($action eq "save") && ($houseid > 0) && ($repotype == 1)) {		# Detailed report
		my $housedb = "smart".sprintf("%05d", $houseid);
		my ($udatef, $udatet, $udaten) = $db->selectrow_array("SELECT UNIX_TIMESTAMP('$datef'), UNIX_TIMESTAMP('$datet'), UNIX_TIMESTAMP(NOW())");
		my %vals = ("ts", -1, "heat1", -1, "heat2", -1, "cool1", -1, "cool2", -1, "aux1", -1, "aux2", -1, "fc", -1, "ov", -1);
		my %vabs = ("ts", 0, "heat1", 0, "heat2", 0, "cool1", 0, "cool2", 0, "aux1", 0, "aux2", 0, "fc", 0, "ov", 0);
		my $ostamp = $udatef;
		my $iters = 120;		# number of iteratio points
		my $dincr = floor(($udatet - $udatef) / $iters);	# seconds increment
		my $udiff = $udatet - $udatef;
		my $maxtime = floor((($udaten - $udatef) / $udiff) * $iters);
		my $idatr = 0;						# date placement counter
		my @datemarks = ();
		my @heatA = ();
		my @heatB = ();
		my @coolA = ();
		my @coolB = ();
		my @auxA = ();
		my @auxB = ();
		my @fcovA = ();
		my @fcovB = ();
		my @dummy = ();
		my $idatp = 1;						# date placement per iteration
		my $idatr = 0;						# date placement counter
		my %totals = ("heat1", 0, "heat2", 0, "cool1", 0, "cool2", 0, "aux1", 0, "aux2", 0, "fcov1", 0, "fcov2", 0);
		for my $datper (0 .. $iters) {
			my ($dmsec,$dmmin,$dmhr,$dmday,$dmmon,$dmyr) = localtime(($datper * $dincr) + $udatef);
			$dmmon += 1;
			$dmyr += 1900;
			if ($idatr == 0) {
				$datemarks[$datper] = sprintf("%02d-%02d-%02d %02d:%02d", ($dmyr - 2000), $dmmon, $dmday, $dmhr, $dmmin);
				$idatr = $idatp;
			} else {
				$datemarks[$datper] = "-";
				$idatr--;
			}
			$heatA[$datper] = -1;
			$heatB[$datper] = -1;
			$coolA[$datper] = -1;
			$coolB[$datper] = -1;
			$auxA[$datper] = -1;
			$auxB[$datper] = -1;
			$fcovA[$datper] = -1;
			$fcovB[$datper] = -1;
			$dummy[$datper] = 0;
		}
		my $all = $db->selectall_arrayref("SELECT updated, UNIX_TIMESTAMP(updated), value_ FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND cots_id = 5 AND name_ = 'ven-runtime' GROUP BY updated");
		foreach my $row (@$all) {
			my $udate = @$row[0];
			my $stamp = @$row[1];
			my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
			my @values = split(/\,/, @$row[2]);
#			$debug .= @$row[2]."<br>";
			my $tdiff = $stamp - $ostamp;
			$ostamp = $stamp;
			foreach my $rec (@values) {
				my ($n, $v) = split(/\:/, $rec);
				$n =~ s/\"//g;
				if ($vals{$n} < 0) {
					$vals{$n} = $v;
				}
				my $vv = $v - $vals{$n};
				if ($vv < 0) {
					$vv = $v;
				}
				if (exists $totals{$n}) {
					$totals{$n} += $vv;
				}
				$vals{$n} = $v;
				my $vvv = 0;
				if ($vv > 0) {
					$vvv = $tdiff / $vv;
					if ($vvv > 60) {
						$vvv = 60;
					}
				}
				$vabs{$n} = floor($vvv + 0.5);		# save difference
#				$debug .= "$tdiff : $n: $v : $vv : $vvv : ".$vabs{$n}."<br>";
			}
			if ($heatA[$otime] > 0) {
				$heatA[$otime] = floor(($heatA[$otime] + $vabs{"heat1"}) / 2);
			} else {
				$heatA[$otime] = $vabs{"heat1"};
			}
			if ($heatB[$otime] > 0) {
				$heatB[$otime] = floor(($heatB[$otime] + $vabs{"heat2"}) / 2);
			} else {
				$heatB[$otime] = $vabs{"heat1"};
			}
			if ($coolA[$otime] > 0) {
				$coolA[$otime] = floor(($coolA[$otime] + $vabs{"cool1"}) / 2);
			} else {
				$coolA[$otime] = $vabs{"cool1"};
			}
			if ($coolB[$otime] > 0) {
				$coolB[$otime] = floor(($coolB[$otime] + $vabs{"cool2"}) / 2);
			} else {
				$coolB[$otime] = $vabs{"cool2"};
			}
			if ($auxA[$otime] > 0) {
				$auxA[$otime] = floor(($auxA[$otime] + $vabs{"aux1"}) / 2);
			} else {
				$auxA[$otime] = $vabs{"aux1"};
			}
			if ($auxB[$otime] > 0) {
				$auxB[$otime] = floor(($auxB[$otime] + $vabs{"aux2"}) / 2);
			} else {
				$auxB[$otime] = $vabs{"aux2"};
			}
			if ($fcovA[$otime] > 0) {
				$fcovA[$otime] = floor(($fcovA[$otime] + $vabs{"fc"}) / 2);
			} else {
				$fcovA[$otime] = $vabs{"fc"};
			}
			if ($fcovB[$otime] > 0) {
				$fcovB[$otime] = floor(($fcovB[$otime] + $vabs{"ov"}) / 2);
			} else {
				$fcovB[$otime] = $vabs{"ov"};
			}
		}
		undef $all;

		my ($zh1, $zh2, $zc1, $zc2, $za1, $za2, $zfc, $zov) = (0, 0, 0, 0, 0, 0, 0, 0);
		for my $datper (0 .. $iters) {
			if ($heatA[$datper] < 0) {
				$heatA[$datper] = $zh1;
			} else {
				$zh1 = $heatA[$datper];
			}
			if ($heatB[$datper] < 0) {
				$heatB[$datper] = $zh2;
			} else {
				$zh2 = $heatB[$datper];
			}
			if ($coolA[$datper] < 0) {
				$coolA[$datper] = $zc1;
			} else {
				$zc1 = $coolA[$datper];
			}
			if ($coolB[$datper] < 0) {
				$coolB[$datper] = $zc2;
			} else {
				$zc2 = $coolB[$datper];
			}
			if ($auxA[$datper] < 0) {
				$auxA[$datper] = $za1;
			} else {
				$za1 = $auxA[$datper];
			}
			if ($auxB[$datper] < 0) {
				$auxB[$datper] = $za2;
			} else {
				$za2 = $auxB[$datper];
			}
			if ($fcovA[$datper] < 0) {
				$fcovA[$datper] = $zfc;
			} else {
				$zfc = $fcovA[$datper];
			}
			if ($fcovB[$datper] < 0) {
				$fcovB[$datper] = $zov;
			} else {
				$zov = $fcovB[$datper];
			}
			if ($datper > $maxtime) {
				$coolA[$datper] = 0;
				$coolB[$datper] = 0;
				$heatA[$datper] = 0;
				$heatB[$datper] = 0;
				$auxA[$datper] = 0;
				$auxB[$datper] = 0;
				$fcovA[$datper] = 0;
				$fcovB[$datper] = 0;
			}
		}

		my $repname = sprintf("%05d", $houseid)."-".sprintf("%04d%02d%02d", $yearf, $monthf, $dayf)."-".sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
		my $repfile = $repfolder."/".$repname;
		my @dclrs = ("blue", "white", "pink", "blue", "cyan");
		my ($minY1, $maxY1, $minY2, $maxY2, $skipY) = (0, 80, 0, 80, 50);
		my $ploty = 250;

		{	# heat1 report
			my @data = ([@datemarks], [@heatA], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Heat cycles, Stage 1";
			my $labely = "0%                100%";
			my $picname = $repfile."-heat1.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-heat1.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Heat cycle, Stage 1 total runtime</font>: ".$totals{"heat1"}." minutes<br>&nbsp;</td></tr>\n";
		{	# heat2 report
			my @data = ([@datemarks], [@heatB], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Heat cycles, Stage 2";
			my $labely = "0%                100%";
			my $picname = $repfile."-heat2.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-heat2.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Heat cycle, Stage 2 total runtime</font>: ".$totals{"heat2"}." minutes<br>&nbsp;</td></tr>\n";
		{	# cool 1 report
			my @data = ([@datemarks], [@coolA], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Cool cycles, Stage 1";
			my $labely = "0%                100%";
			my $picname = $repfile."-cool1.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-cool1.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Cool cycle, Stage 1 total runtime</font>: ".$totals{"cool1"}." minutes<br>&nbsp;</td></tr>\n";
		{	# cool 2 report
			my @data = ([@datemarks], [@coolB], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Cool cycles, Stage 2";
			my $labely = "0%                100%";
			my $picname = $repfile."-cool2.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-cool2.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Cool cycle, Stage 2 total runtime</font>: ".$totals{"cool2"}." minutes<br>&nbsp;</td></tr>\n";
		{	# aux 1 report
			my @data = ([@datemarks], [@auxA], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Auxiliary cycles, Stage 1";
			my $labely = "0%                100%";
			my $picname = $repfile."-aux1.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-aux1.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Auxiliary cycle, Stage 1 total runtime</font>: ".$totals{"aux1"}." minutes<br>&nbsp;</td></tr>\n";
		{	# aux 2 report
			my @data = ([@datemarks], [@auxB], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Auxiliary cycles, Stage 2";
			my $labely = "0%                100%";
			my $picname = $repfile."-aux2.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-aux2.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Auxiliary cycle, Stage 2 total runtime</font>: ".$totals{"aux2"}." minutes<br>&nbsp;</td></tr>\n";
		{	# fcov 1 report
			my @data = ([@datemarks], [@fcovA], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Free cooling cycles";
			my $labely = "0%                100%";
			my $picname = $repfile."-fcov1.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-fcov1.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Free Cooling cycle total runtime</font>: ".$totals{"fcov1"}." minutes<br>&nbsp;</td></tr>\n";
		{	# fcov 2 report
			my @data = ([@datemarks], [@fcovB], [@dummy]);
			my @axis = (1,2,1);
			my $zdesc = "Override cycles";
			my $labely = "0%                100%";
			my $picname = $repfile."-fcov2.png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
	        		$ret = "";
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-fcov2.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
		}
		$replist .= "<tr><td><br><b><font color=blue>Override cycle total runtime</font>: ".$totals{"fcov2"}." minutes<br>&nbsp;</td></tr>\n";
	}

	if (($action eq "save") && ($houseid > 0) && ($repotype == 0)) {		# Cumulative report
		my $housedb = "smart".sprintf("%05d", $houseid);
		my ($udatef, $udatet, $udaten) = $db->selectrow_array("SELECT UNIX_TIMESTAMP('$datef'), UNIX_TIMESTAMP('$datet'), UNIX_TIMESTAMP(NOW())");
		use GD::Graph::lines;
		my @rtypes = ("heat", "cool", "fan", "hset", "cset", "ambt");
		my @rnames = ("Heat mode and cycle", "Cool mode and cycle", "Fan cycle", "Heat setpoint °C", "Cool setpoint °C", "Ambient Temperature, Humidity and Light");
		my $idx = 0;
		foreach my $reptype (@rtypes) {
			$rreptype = $reptype;
			my $repname = $rtypes[$idx]."-".sprintf("%05d", $houseid)."-".sprintf("%04d%02d%02d", $yearf, $monthf, $dayf)."-".sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
			my $repfile = $repfolder."/".$repname;
			my $ploty = 250;
			my $zdesc = $rnames[$idx];
			my $iters = 120;		# number of iteratio points
			my $idatp = 1;						# date placement per iteration
			my $dincr = floor(($udatet - $udatef) / $iters);	# seconds increment
			my $idatr = 0;						# date placement counter
			my @datemarks = ();
			my @dbgnew = ();					# Y axe 0
			my @dbgtemp = ();					# Y axe 1
			my @dbghum = ();					# Y axe 2
			my $comm = "";
			for my $datper (0 .. $iters) {
				my ($dmsec,$dmmin,$dmhr,$dmday,$dmmon,$dmyr) = localtime(($datper * $dincr) + $udatef);
				$dmmon += 1;
				$dmyr += 1900;
				if ($idatr == 0) {
					$datemarks[$datper] = sprintf("%02d-%02d-%02d %02d:%02d", ($dmyr - 2000), $dmmon, $dmday, $dmhr, $dmmin);
					$idatr = $idatp;
				} else {
					$datemarks[$datper] = "-";
					$idatr--;
				}
				$dbgtemp[$datper] = -1;
				$dbghum[$datper] = -1;
				$dbgnew[$datper] = -1;
			}
			my $labely = " ";
			my @dclrs = ("blue", "green", "pink", "blue", "cyan");
			my ($minY1, $maxY1, $minY2, $maxY2, $skipY) = (0, 10, 0, 10, 50);
			my $udiff = $udatet - $udatef;
			my $maxtime = floor((($udaten - $udatef) / $udiff) * $iters);
			if ($reptype eq "heat") {
				$labely = "OFF                 ON";
				$dclrs[0] = "red";
				my $astatush = 0;
				my $ostamp = $udatef;
				my $conint = 0;
				my $const = 0;
				my @statuses = (0, 1, 0, 0);
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-heat','hvac_mode','hvac_state','systemSwitchPosition','eqStatusHeating','equipmentStatus','hvacMode','ven-imode','ven-istate') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my ($cval, $sval) = (0, 0);
					my $name = @$row[1];
					my $val = @$row[2];
					if ($name eq "analog-heat") {				# analog
						if (($val > 0) && ($astatush == 0)) {
							$astatush = 1;
						}
						$sval = $astatush;		# cycle
						$cval = $val;			# state
					} elsif ($name eq "hvac_mode") {			# nest status
						$astatush = 1;
						$sval = ($val =~ m/heat/)?1:0;
					} elsif ($name eq "hvac_state") {			# nest cycle
						$cval = ($val =~ m/heat/)?1:0;
					} elsif ($name eq "systemSwitchPosition") {		# hwell status
						$astatush = 1;
						$sval = ($val == 1)?1:0;
					} elsif ($name eq "eqStatusCooling") {			# hwell cycle
						$cval = ($val)?1:0
					} elsif ($name eq "hvacMode") {				# ecobee status
						$sval = ($val eq "heat")?1:0;
					} elsif ($name eq "equipmentStatus") {			# ecobee cycle
						$cval = ($val =~ "auxHeat")?1:0;
					} elsif ($name eq "ven-imode") {			# venstar status
						$sval = (($val == 1) || ($val == 3))?1:0;
					} elsif ($name eq "ven-istate") {			# venstar cycle
						$cval = ($val == 1)?1:0;
					}
					if ($cval > $dbgtemp[$otime]) {
						$dbgtemp[$otime] = $cval;
					}
					if ($cval == 0) {
						$dbgtemp[$otime + 1] = $cval;
					}
					if ($sval > $dbghum[$otime]) {
						$dbghum[$otime] = $sval;
					}
					if ($const != $cval) {
						unless ($cval) {
							$conint += ($stamp - $ostamp);
						}
						$const = $cval;
						$ostamp = $stamp;
					}
				}
				undef $all;
				my ($otemp, $ohum) = (0, 0);
				for my $datper (0 .. $iters) {
					if ($dbgtemp[$datper] < 0) {
						$dbgtemp[$datper] = $otemp;
					} else {
						$otemp = $dbgtemp[$datper];
					}
					if ($dbghum[$datper] < 0) {
						$dbghum[$datper] = $ohum;
					} else {
						$ohum = $dbghum[$datper];
					}
					$dbgtemp[$datper] = ($dbgtemp[$datper] * 8) + 1;
					$dbghum[$datper] = ($dbghum[$datper] * 6) + 2;
					if ($datper > $maxtime) {
						$dbgtemp[$datper] = 1;
					}
				}
				my $uptime = sprintf("%.1f", (($conint / $udiff) * 100));
				$comm = "<br><font color=red><b>Heat cycle ON percentage: $uptime%<b></font>";
			} elsif ($reptype eq "cool") {
				$labely = "OFF                 ON";
				$dclrs[0] = "blue";
				my $astatush = 0;
				my $ostamp = $udatef;
				my $conint = 0;
				my $const = 0;
				my @statuses = (0, 1, 0, 0);
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-cool','hvac_mode','hvac_state','systemSwitchPosition','eqStatusCooling','equipmentStatus','hvacMode','ven-imode','ven-istate') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my ($cval, $sval) = (0, 0);
					my $name = @$row[1];
					my $val = @$row[2];
					if ($name eq "analog-cool") {				# analog
						if (($val > 0) && ($astatush == 0)) {
							$astatush = 1;
						}
						$sval = $astatush;		# cycle
						$cval = $val;			# state
					} elsif ($name eq "hvac_mode") {			# nest status
						$astatush = 1;
						$sval = ($val =~ m/cool/)?1:0;
					} elsif ($name eq "hvac_state") {			# nest cycle
						$cval = ($val =~ m/cool/)?1:0;
					} elsif ($name eq "systemSwitchPosition") {		# hwell status
						$astatush = 1;
						$sval = ($val == 3)?1:0;
					} elsif ($name eq "eqStatusCooling") {			# hwell cycle
						$cval = ($val)?1:0
					} elsif ($name eq "hvacMode") {				# ecobee status
						$sval = ($val eq "cool")?1:0;
					} elsif ($name eq "equipmentStatus") {			# ecobee cycle
						$cval = ($val =~ "compCool")?1:0;
					} elsif ($name eq "ven-imode") {			# venstar status
						$sval = (($val == 2) || ($val == 3))?1:0;
					} elsif ($name eq "ven-istate") {			# venstar cycle
						$cval = ($val == 2)?1:0;
					}
					if ($cval > $dbgtemp[$otime]) {
						$dbgtemp[$otime] = $cval;
					}
					if ($cval == 0) {
						$dbgtemp[$otime + 1] = $cval;
					}
					if ($sval > $dbghum[$otime]) {
						$dbghum[$otime] = $sval;
					}
					if ($const != $cval) {
						unless ($cval) {
							$conint += ($stamp - $ostamp);
						}
						$const = $cval;
						$ostamp = $stamp;
					}
				}
				undef $all;
				my ($otemp, $ohum) = (0, 0);
				for my $datper (0 .. $iters) {
					if ($dbgtemp[$datper] < 0) {
						$dbgtemp[$datper] = $otemp;
					} else {
						$otemp = $dbgtemp[$datper];
					}
					if ($dbghum[$datper] < 0) {
						$dbghum[$datper] = $ohum;
					} else {
						$ohum = $dbghum[$datper];
					}
					$dbgtemp[$datper] = ($dbgtemp[$datper] * 8) + 1;
					$dbghum[$datper] = ($dbghum[$datper] * 6) + 2;
					if ($datper > $maxtime) {
						$dbgtemp[$datper] = 1;
					}
				}
				my $uptime = sprintf("%.1f", (($conint / $udiff) * 100));
				$comm = "<br><font color=red><b>Cool cycle ON percentage: $uptime%<b></font>";
			} elsif ($reptype eq "fan") {
				$labely = "OFF                 ON";
				$dclrs[0] = "white";
				$dclrs[1] = "black";
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-heat','analog-cool','analog-fan','fan_timer_active','hvac_state','fanMode','eqStatusCooling','eqStatusHeating','equipmentStatus','ven-ifanstate') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my ($cval, $sval) = (0, 0);
					my $name = @$row[1];
					my $val = @$row[2];
					if ($name eq "analog-fan") {				# analog 1
						$cval = $val;
					} elsif (($name eq "analog-cool") || ($name eq "analog-heat")) {	# analog 2
						$cval = ($val)?1:0;
					} elsif ($name eq "fan_timer_active") {			# nest 1
						$cval = ($val eq "true")?1:0;
					} elsif ($name eq "hvac_state") {			# nest 2
						$cval = (($val =~ m/cool/) || ($val =~ m/heat/))?1:0;
					} elsif ($name eq "fanMode") {				# hwell 1
						$cval = ($val > 0)?1:0;
					} elsif (($name eq "eqStatusCooling") || ($name eq "eqStatusHeating")) {	# hwell 2
						$cval = ($val)?1:0;
					} elsif ($name eq "equipmentStatus") {			# ecobee cycle
						$cval = ($val =~ "fan")?1:0;
					} elsif ($name eq "ven-ifanstate") {			# venstar cycle
						$cval = ($val > 0)?1:0;
#						$debug = "here";
					}
					if ($cval > $dbghum[$otime]) {
						$dbghum[$otime] = $cval;
					}
					if ($cval == 0) {
						$dbghum[$otime + 1] = $cval;
					}
				}
				undef $all;
				my ($otemp, $ohum, $conint) = (0, 0, 0);
				for my $datper (0 .. $iters) {
					if ($dbghum[$datper] < 0) {
						$dbghum[$datper] = $ohum;
					} else {
						$ohum = $dbghum[$datper];
					}
					$dbgtemp[$datper] = 0;
					if ($dbghum[$datper]) {
						$conint ++;
					}
					$dbghum[$datper] = ($dbghum[$datper] * 8) + 1;
					if ($datper > $maxtime) {
						$dbghum[$datper] = 1;
					}
				}
				$conint = ($conint)?($conint + 1):0;
				my $uptime = sprintf("%.1f", (($conint / $iters) * 100));
				$comm = "<br><font color=red><b>Fan cycle ON percentage: $uptime%<b></font>";
			} elsif ($reptype eq "hset") {
				$labely = "";
				$skipY = 5;
				$dclrs[0] = "red";
				my ($totrec, $tottmp, $maxT, $minT) = (0, 0, 10, 0);
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-target-heat','target_temperature_low_c','heatSetpoint','desiredHeat','ven-iheattemp') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my $name = @$row[1];
					my $val = @$row[2];
					my $sval = 0;
					if ($name eq "analog-target-heat") {			# analog
						$sval = $val + 0;
					} elsif ($name eq "target_temperature_low_c") {		# nest
						$sval = $val + 0;
					} elsif ($name eq "heatSetpoint") {			# hwell
						$sval = $val + 0;
					} elsif ($name eq "desiredHeat") {			# ecobee
						$sval = $val + 0;
					} elsif ($name eq "ven-iheattemp") {			# venstar
						$sval = $val + 0;
					}
					if ($sval > 0) {
						$totrec ++;
						$tottmp += $sval;
						$dbgtemp[$otime] = $sval;
						if ($minT > $sval) {
							$minT = $sval;
						}
						if ($maxT < $sval) {
							$maxT = $sval;
						}
					}
					if ($sval == 0) {
						$dbgtemp[$otime + 1] = $sval;
					}
				}
				undef $all;
				my ($otemp, $midT) = (0, 0);
				($minY1, $minY2) = (0, 0);
				if ($maxT > 10) {
					$maxY1 = floor($maxT) + 3;
					$maxY2 = $maxY1;
				}
				if ($totrec > 0) {
					$midT = sprintf("%.1f", ($tottmp / $totrec));
				}
				for my $datper (0 .. $iters) {
					$dbghum[$datper] = $midT;
					if ($dbgtemp[$datper] < 0) {
						$dbgtemp[$datper] = sprintf("%.1f", $otemp);
					} else {
						$otemp = sprintf("%.1f", $dbgtemp[$datper]);
						$dbgtemp[$datper] = $otemp;
					}
					if ($datper > $maxtime) {
						$dbgtemp[$datper] = 0;
					}
				}
				$comm = "<br><font color=green><b>Median heat setpoint: ".sprintf("%.1f", $midT)."&deg;C<b></font>";
			} elsif ($reptype eq "cset") {
				$labely = "";
				$skipY = 5;
				$dclrs[0] = "red";
				my ($totrec, $tottmp, $maxT, $minT) = (0, 0, 10, 0);
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-target-cool','target_temperature_high_c','coolSetpoint','desiredCool','ven-icooltemp') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my $name = @$row[1];
					my $val = @$row[2];
					my $sval = 0;
					if ($name eq "analog-target-cool") {			# analog
						$sval = $val + 0;
					} elsif ($name eq "target_temperature_high_c") {	# nest
						$sval = $val + 0;
					} elsif ($name eq "coolSetpoint") {			# hwell
						$sval = $val + 0;
					} elsif ($name eq "desiredCool") {			# ecobee
						$sval = $val + 0;
					} elsif ($name eq "ven-icooltemp") {			# venstar
						$sval = $val + 0;
					}
					if ($sval > 0) {
						$totrec ++;
						$tottmp += $sval;
						$dbgtemp[$otime] = $sval;
						if ($minT > $sval) {
							$minT = $sval;
						}
						if ($maxT < $sval) {
							$maxT = $sval;
						}
					}
					if ($sval == 0) {
						$dbgtemp[$otime + 1] = $sval;
					}
				}
				undef $all;
				my ($otemp, $midT) = (0, 0);
				($minY1, $minY2) = (0, 0);
				if ($maxT > 10) {
					$maxY1 = floor($maxT) + 3;
					$maxY2 = $maxY1;
				}
				if ($totrec > 0) {
					$midT = sprintf("%.1f", ($tottmp / $totrec));
				}
				for my $datper (0 .. $iters) {
					$dbghum[$datper] = $midT;
					if ($dbgtemp[$datper] < 0) {
						$dbgtemp[$datper] = sprintf("%.1f", $otemp);
					} else {
						$otemp = sprintf("%.1f", $dbgtemp[$datper]);
						$dbgtemp[$datper] = $otemp;
					}
					if ($datper > $maxtime) {
						$dbgtemp[$datper] = 0;
					}
				}
				$comm = "<br><font color=green><b>Median cool setpoint: ".sprintf("%.1f", $midT)."&deg;C<b></font>";
			} elsif ($reptype eq "ambt") {
				$labely = "";
				$skipY = 5;
				$dclrs[0] = "red";
				$dclrs[1] = "blue";
				$dclrs[2] = "green";
				my ($totrecT, $tottmpT, $totrecH, $tottmpH, $totrecL, $tottmpL, $maxT, $minT, $maxTT, $minTT, $maxHH, $minHH, $maxLL, $minLL) = (0, 0, 10, 0, 0, 100, 0, 100, 0, 30000);
				my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), name_, value_, cots_id FROM $housedb.cots_data WHERE updated BETWEEN $datef AND $datet AND name_ IN ('analog-ambient-t','ambient_temperature_c','dispTemperature','actualTemperature','analog-ambient-h','humidity','actualHumidity','analog-ambient-l','ven-ispacetemp_c') ORDER BY id");
				foreach my $row (@$all) {
					my $stamp = @$row[0];
					my $otime = floor((($stamp - $udatef) / $udiff) * $iters);
					my $name = @$row[1];
					my $val = @$row[2];
					my ($sval, $cval, $lval) = (0, 0, 0);
					if ($name eq "analog-ambient-t") {			# T analog
						$sval = $val + 0;
					} elsif ($name eq "ambient_temperature_c") {		# T nest
						$sval = $val + 0;
					} elsif ($name eq "dispTemperature") {			# T hwell
						$sval = $val + 0;
					} elsif ($name eq "actualTemperature") {		# T ecobee
						$sval = $val + 0;
					} elsif ($name eq "ven-ispacetemp_c") {			# T venstar
						$sval = $val + 0;
					}
					if ($sval > 0) {
						$totrecT ++;
						$tottmpT += $sval;
						$dbghum[$otime] = $sval;
						if ($minT > $sval) {
							$minT = $sval;
						}
						if ($maxT < $sval) {
							$maxT = $sval;
						}
						if ($minTT > $sval) {
							$minTT = $sval;
						}
						if ($maxTT < $sval) {
							$maxTT = $sval;
						}
					}
					if ($name eq 'analog-ambient-h') {
						$cval = (($val >= 0) && ($val <= 100))?$val:0;
					} elsif ($name eq 'humidity') {
						$cval = (($val >= 0) && ($val <= 100))?$val:0;
					} elsif ($name eq 'actualHumidity') {
						$cval = (($val >= 0) && ($val <= 100))?$val:0;
					}
					if ($cval > 0) {
						$totrecH ++;
						$tottmpH += $cval;
						$dbgtemp[$otime] = $cval;
						if ($minHH > $cval) {
							$minHH = $cval;
						}
						if ($maxHH < $cval) {
							$maxHH = $cval;
						}
					}
					if ($name eq 'analog-ambient-l') {
						$lval = (($val >= 0) && ($val <= 30000))?$val:0;
					}
					if ($lval > 0) {
						$totrecL ++;
						$tottmpL += $lval;
						$dbgnew[$otime] = $lval;
						if ($minLL > $lval) {
							$minLL = $lval;
						}
						if ($maxLL < $lval) {
							$maxLL = $lval;
						}
					}
				}
				undef $all;
				my ($otemp, $ohum, $olux) = (0, 0, 0);
				($minY1, $minY2, $maxY2) = (0, 0, 100);
				if ($maxT > 10) {
					$maxY1 = floor($maxT) + 3;
				}
				my $coeL = 0;
				if ($totrecL) {
					$coeL = sprintf("%.1f", (95 / $maxLL));
				}
				$coeL += 0;
				for my $datper (0 .. $iters) {
					if ($dbghum[$datper] < 0) {
						$dbghum[$datper] = sprintf("%.1f", $otemp);
					} else {
						$otemp = sprintf("%.1f", $dbghum[$datper]);
						$dbghum[$datper] = $otemp;
					}
					if ($dbgtemp[$datper] < 0) {
						$dbgtemp[$datper] = sprintf("%.1f", $ohum);
					} else {
						$ohum = sprintf("%.1f", $dbgtemp[$datper]);
						$dbgtemp[$datper] = $ohum;
					}
					if ($dbgnew[$datper] < 0) {
						$dbgnew[$datper] = sprintf("%.1f", ($olux * $coeL));
					} else {
						$olux = sprintf("%.1f", ($dbgnew[$datper] * $coeL));
						$dbgnew[$datper] = $olux;
					}
					if ($datper > $maxtime) {
						$dbgnew[$datper] = 0;
						$dbgtemp[$datper] = 0;
						$dbghum[$datper] = 0;
					}
				}
				my ($midTT, $midLL, $midHH) = (0, 0, 0);
				if ($totrecT > 0) {
					$midTT = sprintf("%.1f", ($tottmpT / $totrecT));
				} else {
					($midTT, $maxTT, $minTT) = (0, 0, 0);
				}
				if ($totrecH > 0) {
					$midHH = sprintf("%.1f", ($tottmpH / $totrecH));
				} else {
					($midHH, $maxHH, $minHH) = (0, 0, 0);
				}
				if ($totrecL > 0) {
					$midLL = sprintf("%.1f", ($tottmpL / $totrecL));
				} else {
					($midLL, $maxLL, $minLL) = (0, 0, 0);
				}
				$comm = "<br><font color=green><b>Temperature average : ".sprintf("%.1f", $midTT)."&deg;C , Maximum : ".sprintf("%.1f", $maxTT)."&deg;C , Minimum : ".sprintf("%.1f", $minTT)."&deg;C<b></font>";
				$comm .= "<br><font color=blue><b>Humidity average : ".sprintf("%.1f", $midHH)."% , Maximum : ".sprintf("%.1f", $maxHH)."% , Minimum : ".sprintf("%.1f", $minHH)."%<b></font>";
				$comm .= "<br><font color=red><b>Light level average : ".sprintf("%.1f", $midLL)."lux , Maximum : ".sprintf("%.1f", $maxLL)."lux , Minimum : ".sprintf("%.1f", $minLL)."lux<b></font>";
			}
			my @data = ([@datemarks], [@dbgtemp], [@dbghum]);
			my @axis = (1,2,1);
			if ($reptype eq "ambt") {
				@data = ([@datemarks], [@dbgnew], [@dbgtemp], [@dbghum]);
				@axis = (2,2,1);
			}
			my $picname = $repfile.".png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			sub y_format1 {
				my $value = $_[0];
				my $ret;
				if (($rreptype eq "hset") || ($rreptype eq "cset") || ($rreptype eq "ambt")) {
					$ret = sprintf("%.1f", $value);
			        } else {
			        	$ret = "";
			        }
			        return $ret;
			}			
			sub y_format2 {
				my $value = $_[0];
				my $ret;
				if ($rreptype eq "ambt") {
					$ret = floor($value)."%";
			        } else {
			        	$ret = "";
			        }
			        return $ret;
			}
			$graph->set( 
				title		=> $zdesc,
				two_axes	=> 1,
				use_axis	=> [@axis],
				x_label		=> '',
				y1_label	=> $labely,
				y1_min_value	=> $minY1,
				y1_max_value	=> $maxY1,
				y_tick_number	=> 30,
				y1_number_format	=> \&y_format1,
				y2_number_format	=> \&y_format2,
				y_label_skip	=> $skipY,
				x_label_skip	=> 3,
				y2_label	=> '',
				y2_min_value	=> $minY2,
				y2_max_value	=> $maxY2,
				dclrs		=> [@dclrs],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart".(($comm ne "")?"<br>.$comm":"")."</td></tr>\n";
			if ($idx != $#rtypes) {
				$replist .= "<tr><td>&nbsp;</td></tr>\n";
			}
			$idx ++;
		}
	} 

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--replist--/$replist/g;
		$inline =~ s/--houseid--/$lhouse/g;
		$inline =~ s/--year_f--/$lyearf/g;
		$inline =~ s/--year_t--/$lyeart/g;
		$inline =~ s/--repotype--/$rrepotype/g;
		$inline =~ s/--month_f--/$lmonthf/g;
		$inline =~ s/--month_t--/$lmontht/g;
		$inline =~ s/--day_f--/$ldayf/g;
		$inline =~ s/--day_t--/$ldayt/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

if (($uimode eq "userinfo") && ($uismode eq "useradmin") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $houseid = (exists $FORM{houseid})?$FORM{houseid}:0;
	my $lhouse = "<option value=\"0\"".(($houseid == 0)?" selected=\"selected\"":"").">-- Select Core --</option>";
	{
		my $hidfilter = "systems.house_id > 0";
		if ($uaccess < 2) {
			$hidfilter = "systems.house_id IN ($housemask)";
		}
		my $all = $db->selectall_arrayref("SELECT systems.house_id, CONCAT(systemadd.name1,' ',systemadd.name2), systemadd.company FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $hidfilter ORDER BY id");
		foreach my $row (@$all) {
			$lhouse .= "<option value=\"".@$row[0]."\"".((@$row[0] == $houseid)?" selected=\"selected\"":"").">".sprintf("%05d", @$row[0]).": ".@$row[1]."</option>";
		}
		undef $all;
	}
	my ($userlist, $zuser, $zpass) = ("", "", "");

	if (($action eq "save") && ($houseid <= 0)) {
		$message = "Select Core ID first!";
	}

	if ($houseid > 0) {
		my $housedb = "smart".sprintf("%05d", $houseid);
		if (($action eq "remove") && (exists $FORM{"userid"})) {
			my $uid = $FORM{"userid"} + 0;
			($zuser, $zpass) = $db->selectrow_array("SELECT login, password FROM $housedb.users WHERE id = $uid");
			if ($zuser ne "") {
				$db->do("DELETE FROM $housedb.users WHERE id = $uid");
				$message = "Account <b>$zuser</b> deleted";
			}
		}
		if (($action eq "save") && ($FORM{"user0"} ne "") && ($FORM{"pass0"} ne "")) {
			my ($uex) = $db->selectrow_array("SELECT COUNT(*) FROM $housedb.users WHERE login = '".$FORM{"user0"}."'");
			if ($uex == 0) {
				my $uacc = -1;
#				if (exists $FORM{"adm0"}) {
					$uacc = 1;
#				} elsif (exists $FORM{"cust0"}) {
#					$uacc = 0;
#				}
				$db->do("INSERT INTO $housedb.users (id, login, password, name1, phone1, email, timezone, comfort, access, t_display) VALUES (NULL, '".$FORM{"user0"}."', '".$FORM{"pass0"}."', ' ', '1800-ASE-SAVE', 'support\@ase-energy.ca', 0, 0, $uacc, 0)");
			} else {
				$message = "Username must be unique!";
				$zuser = $FORM{"user0"};
				$zpass = $FORM{"pass0"};
			}
		}
		my $all = $db->selectall_arrayref("SELECT id, login, password, access FROM $housedb.users ORDER BY id");
		foreach my $row (@$all) {
			my ($uid, $ulogin, $upass, $uacc) = @$row;
			if ($action eq "save") {
				if ((exists $FORM{"user$uid"}) && ($FORM{"user$uid"} ne $ulogin) && ($FORM{"user$uid"} ne "")) {
					my ($uex) = $db->selectrow_array("SELECT COUNT(*) FROM $housedb.users WHERE login = '".$FORM{"user$uid"}."'");
					if ($uex == 0) {
						$ulogin = $FORM{"user$uid"};
						$db->do("UPDATE $housedb.users SET login = '$ulogin' WHERE id = $uid");
					} else {
						$message = "Username must be unique!";
					}
				}
				if ((exists $FORM{"pass$uid"}) && ($FORM{"pass$uid"} ne $upass) && ($FORM{"pass$uid"} ne "")) {
					$upass = $FORM{"pass$uid"};
					$db->do("UPDATE $housedb.users SET password = '$upass' WHERE id = $uid");
				}
#				if ((exists $FORM{"user$uid"}) && (exists $FORM{"adm$uid"}) && ($uacc != 1)) {
					$uacc = 1;
					$db->do("UPDATE $housedb.users SET access = '$uacc' WHERE id = $uid");
#				} elsif ((exists $FORM{"user$uid"}) && (exists $FORM{"cust$uid"}) && ($uacc != 0)) {
#					$uacc = 0;
#					$db->do("UPDATE $housedb.users SET access = '$uacc' WHERE id = $uid");
#				} elsif ((exists $FORM{"user$uid"}) && !(exists $FORM{"cust$uid"}) && !(exists $FORM{"adm$uid"}) && ($uacc >= 0)) {
#					$uacc = -1;
#					$db->do("UPDATE $housedb.users SET access = '$uacc' WHERE id = $uid");
#				}
			}
			$userlist .= "<tr><td><input name=\"user$uid\" size=\"30\" maxlength=\"50\" value=\"$ulogin\" type=\"text\"></td>
					<td><input name=\"pass$uid\" size=\"30\" maxlength=\"50\" value=\"$upass\" type=\"text\"></td>
					<td align=left><input name=\"delete$uid\" value=\"Delete\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&houseid=$houseid&userid=$uid&action=remove'\" type=\"button\"></td></tr>\n";
		}
		undef $all;
	}

	if ($message ne "") {
		$message = "<tr><td nowrap=\"nowrap\" colspan=5><br>$message</td></tr>\n";
	}
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--houseid--/$lhouse/g;
		$inline =~ s/--house--/$houseid/g;
		$inline =~ s/--user0--/$zuser/g;
		$inline =~ s/--pass0--/$zpass/g;
		$inline =~ s/--userlist--/$userlist/g;
		$inline =~ s/--updmessage--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# IR database browser

if (($uimode eq "userinfo") && ($uismode eq "irdatabase") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my ($lbrand, $lmodel, $comlist) = ("", "", "");
	my @brands = ("None selected");
	my %mnames = ();
	my %pairs = ();
	my $sbrand = $FORM{"brand"} + 0;
	my $smodel = $FORM{"model"} + 0;

	{
		my $brcnt = 0;
		my $all = $db->selectall_arrayref("SELECT UCASE(brand) as brn FROM ir_devices GROUP BY brn");
		foreach my $row (@$all) {
			my ($brand) = @$row;
			if (length($brand) <= 3) {
				$brand = uc($brand);
			} else {
				my @llb = split(/\ /, $brand);
				$brand = "";
				foreach my $bb (@llb) {
					$brand .= ucfirst(lc($bb))." ";
				}
			}
			$brcnt ++;
			$brands[$brcnt] = $brand;
		}
		undef $all;

		for my $bcnt (0 .. $brcnt) {
			$lbrand .= "<option value=\"$bcnt\"".(($bcnt == $sbrand)?" selected=\"selected\"":"").">".$brands[$bcnt]."</option>";
		}
	}

	my ($iscurr) = $db->selectrow_array("SELECT COUNT(model) FROM ir_devices WHERE brand = '".$brands[$sbrand]."' AND id = $smodel");
	unless ($iscurr) {
		$smodel = 0;		# fix model selector after brand switch
	}
	if ($sbrand == 0) {
		$lmodel .= "<option value=\"0\" selected=\"selected\">None selected</option>";
	} else {
		$lmodel .= "<option value=\"0\">None selected</option>";
		my $all = $db->selectall_arrayref("SELECT id, model FROM ir_devices WHERE brand = '".$brands[$sbrand]."' ORDER BY model");
		foreach my $row (@$all) {
			my ($bid, $model) = @$row;
			$lmodel .= "<option value=\"$bid\"".(($bid == $smodel)?" selected=\"selected\"":"").">$model</option>";
		}
		undef $all;
	}

	if ($smodel == 0) {
		$comlist = "<tr><td><b>No IR commands available for selected device</b></td></tr>";
	} else {
		my %matrix = ();
		my $comcnt = 0;
		my $houseid = 0;
		my $all = $db->selectall_arrayref("SELECT ir_data.flags, ir_data.size, ir_commands.description, ir_data.house_id FROM ir_data LEFT JOIN ir_commands ON ir_data.ircommand_id = ir_commands.id WHERE ir_data.irdevice_id = $smodel ORDER BY ir_commands.id, ir_data.flags ASC");
		foreach my $row (@$all) {
			my ($flags, $size, $desc, $hid) = @$row;
			if ($size > 0) {
				my $raw = ($flags & 3)?1:0;
				my $mode = 0;			# Auto
				if ($flags & 32) {
					$mode = 1;		# Heat
				} elsif ($flags & 64) {
					$mode = 2;		# Cool
				}
				$matrix{$desc}{$mode} = $raw;
				$houseid = $hid;
				$comcnt ++;
			}
		}
		undef $all;
		if ($comcnt) {
			my @ctype = ("RC/NEC", "RAW");
			$comlist = "<tr><td class=\"irdbC\"><b>IR Command</td><td class=\"irdbC\"><b>Auto mode</td><td class=\"irdbC\"><b>Heat mode</td><td class=\"irdbC\"><b>Cool mode</td></tr>\n";
			foreach my $cmd (sort keys %matrix) {
				$comlist .= "<tr>
					<td class=\"irdbC\"><b>".$cmd."</td>
					<td ".((exists $matrix{$cmd}{0})?"class=\"irdbB\">".$ctype[$matrix{$cmd}{0}]:"class=\"irdbA\">&nbsp;")."</td>
					<td ".((exists $matrix{$cmd}{1})?"class=\"irdbB\">".$ctype[$matrix{$cmd}{1}]:"class=\"irdbA\">&nbsp;")."</td>
					<td ".((exists $matrix{$cmd}{2})?"class=\"irdbB\">".$ctype[$matrix{$cmd}{2}]:"class=\"irdbA\">&nbsp;")."</td>
					</tr>";
			}
			$comlist .= "<tr><td colspan=4><br>IR Payload set imported from <b>House $houseid</b></td></tr>";
		} else {
			$comlist = "<tr><td><b>No IR commands available for selected device</b></td></tr>";
		}
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--brand--/$lbrand/g;
		$inline =~ s/--model--/$lmodel/g;
		$inline =~ s/--comlist--/$comlist/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# power graphs report page

if (($uimode eq "reports") && ($uismode eq "powergraph") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("yaxis", "0", "group", "0");
	my $ymaxval = (exists $FORM{ymax})?$FORM{ymax}:1500;
	my $srcval = (exists $FORM{source})?$FORM{source}:0;
	my $grpval = (exists $FORM{group})?$FORM{group}:0;
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	$dayf = fixdate($dayf, $monthf, $yearf);
	$dayt = fixdate($dayt, $montht, $yeart);
	my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
	my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
	if ($shdatef > $shdatet) {
		($montht, $monthf) = ($monthf, $montht);
		($dayt, $dayf) = ($dayf, $dayt);
		($yeart, $yearf) = ($yearf, $yeart);
	}
	my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt, $lymax, $dsource, $dgroup) = ("", "", "", "", "", "", "", "", "");
	my @srcvals = ("Electric baseboards", "Zigbee plugs");
	for my $ii (0 .. $#srcvals) {
		$dsource .= "<option value=\"$ii\"".(($srcval == $ii)?" selected=\"selected\"":"").">".$srcvals[$ii]."</option>";
	}
	if ($srcval == 0) {
		$hiders{"group"} = 1;
	} elsif ($srcval == 1) {
		$hiders{"yaxis"} = 1;
	}
	my @grpvals = ("Zones", "Thermostats");
	for my $ii (0 .. $#grpvals) {
		$dgroup .= "<option value=\"$ii\"".(($grpval == $ii)?" selected=\"selected\"":"").">".$grpvals[$ii]."</option>";
	}
	my @ymvals = (1500, 1000, 500, 250, 100);
	foreach my $ymax (@ymvals) {
		$lymax .= "<option value=\"$ymax\"".(($ymaxval == $ymax)?" selected=\"selected\"":"").">$ymax</option>";
	}
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $month (1 .. 12) {
		$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
		$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
	}
	for my $day (1 .. 31) {
		$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
		$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
	}
	my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
	my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
	my $houseid = (exists $FORM{houseid})?$FORM{houseid}:0;
	my $lhouse = "<option value=\"0\"".(($houseid == 0)?" selected=\"selected\"":"").">-- Select Core --</option>";
	{
		my $hidfilter = "systems.house_id > 0";
		if ($uaccess < 2) {
			$hidfilter = "systems.house_id IN ($housemask)";
		}
		my $all = $db->selectall_arrayref("SELECT systems.house_id, CONCAT(systemadd.name1,' ',systemadd.name2) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $hidfilter ORDER BY id");
		foreach my $row (@$all) {
			$lhouse .= "<option value=\"".@$row[0]."\"".((@$row[0] == $houseid)?" selected=\"selected\"":"").">".sprintf("%05d", @$row[0]).": ".@$row[1]."</option>";
		}
		undef $all;
	}
	my $replist = "";

	if (($action eq "save") && ($houseid > 0) && ($srcval == 0)) {			# sinope
		$ymaxval = 5000;
		use GD::Graph::lines;
		my $repname = "power-".sprintf("%05d", $houseid)."-".sprintf("%04d%02d%02d", $yearf, $monthf, $dayf)."-".sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
		my $repfile = $repfolder."/".$repname;
		my $housedb = "smart".sprintf("%05d", $houseid);
		my ($udatef, $udatet) = (0, 0);

		my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP($datef), UNIX_TIMESTAMP($datet)");
		foreach my $row (@$all) {
			($udatef, $udatet) = (@$row[0], @$row[1]);
		}
		undef $all;

		my %slist = ();
		my %zname = ();
		my $znum = 0;
		my $zlast = 0;
		if ($grpval == 1) {			# group by thermostat
			my $all = $db->selectall_arrayref("SELECT id, description, xbee_addr64 FROM $housedb.devices WHERE device_type = 82 AND hardware_type = 4");	# thermostats only
			foreach my $row (@$all) {
				my $sid = unpack("V", pack("H*", @$row[2]));
				$slist{@$row[0]} = $sid;
				$zname{@$row[0]} = @$row[1];
				$znum ++;
				$zlast = @$row[0];
			}
			undef $all;
		} elsif ($grpval == 0) {		# group by zone
			my $all = $db->selectall_arrayref("SELECT hvac_zones.zone_id, zones.description, hvac_zones.value_ FROM $housedb.hvac_zones LEFT JOIN $housedb.zones ON zones.id = hvac_zones.zone_id WHERE hvac_zones.option_ = 'baseboards.sinope' AND hvac_zones.value_ > 0");	# sinope zones only
			foreach my $row (@$all) {
				$slist{@$row[0]} = @$row[2];
				$zname{@$row[0]} = @$row[1];
				$znum ++;
				$zlast = @$row[0];
			}
			undef $all;
		}

		my $gridcnt = 1;
		foreach my $sid (sort keys %zname) {
			my $ploty = ($gridcnt & 1)?250:200;
			my $zdesc = $zname{$sid};
			my $iters = 120;					# number of iteratio points
			my $idatp = 3;						# date placement per iteration
			my $dincr = floor(($udatet - $udatef) / $iters);	# seconds increment
			my $idatr = 0;						# date placement counter
			my @datemarks = ();
			my @dbgtemp = ();					# temperature debug only!
			my @dbgtcnt = ();
			my $newmaxval = 0;
			for my $datper (0 .. $iters) {
				my ($dmsec,$dmmin,$dmhr,$dmday,$dmmon,$dmyr) = localtime(($datper * $dincr) + $udatef);
				$dmmon += 1;
				$dmyr += 1900;
				if ($idatr == 0) {
					$datemarks[$datper] = ($gridcnt & 1)?(sprintf("%02d-%02d-%02d %02d:%02d", ($dmyr - 2000), $dmmon, $dmday, $dmhr, $dmmin)):" ";
					$idatr = $idatp;
				} else {
					$datemarks[$datper] = ($gridcnt & 1)?"-":" ";
					$idatr--;
				}
				$dbgtemp[$datper] = 0;
				$dbgtcnt[$datper] = 1;
			}

			my ($kwh, $allcnt, $kkwh) = (0, 0, 0);
			my %wattage = ();
			my %sheat = ();
			my %vheat = ();
			my $inlist = $slist{$sid};
			my $query = "SELECT * FROM (SELECT cots_id, value_ FROM $housedb.cots_data WHERE cots_id > 8 AND name_ LIKE '%-wattage' AND cots_id IN ($inlist) AND updated BETWEEN $datef AND $datet ORDER BY id ASC) AS nest GROUP BY name_";
			if ($eccc) {
				$query = "SELECT cots_id, value_ FROM $housedb.cots_data WHERE id IN (SELECT MIN(id) FROM $housedb.cots_data WHERE cots_id > 8 AND name_ LIKE '%-wattage' AND cots_id IN ($inlist) AND updated BETWEEN $datef AND $datet GROUP BY name_)";
			}
			my $all = $db->selectall_arrayref($query);
			foreach my $row (@$all) {
				$wattage{@$row[0]} = @$row[1];		# initial wattage values
				$sheat{@$row[0]} = 0;
				$vheat{@$row[0]} = 0;
			}
			undef $all;
			my $all = $db->selectall_arrayref("SELECT id, updated, UNIX_TIMESTAMP(updated), cots_id, name_, value_ FROM $housedb.cots_data WHERE cots_id > 8 AND (name_ LIKE '%-wattage' OR name_ LIKE '%-heatLevel') AND cots_id IN ($inlist) AND updated BETWEEN $datef AND $datet ORDER BY id");
			foreach my $row (@$all) {
				my $upd = @$row[1];
				my $uupd = @$row[2];
				my $cid = @$row[3];
				my $nam = @$row[4];
				my $val = @$row[5];
				if ($nam =~ m/wattage$/) {
					$wattage{$cid} = $val;
				} elsif ($nam =~ m/heatLevel$/) {
					my $loadl = $wattage{$cid};
					my $kwatt = floor((($uupd - $sheat{$cid}) * ($vheat{$cid} * $loadl)) / (100 * 3600));	# watt per hour
					$vheat{$cid} = $val;
					$sheat{$cid} = $uupd;
					my $otime = floor((($uupd - $udatef) / ($udatet - $udatef)) * $iters);
					$dbgtemp[$otime] += floor($val * $loadl / 100);
					$dbgtcnt[$otime] ++;
					$allcnt ++;
					$kwh += $kwatt;
				}
			}
			undef $all;
			for my $datper (0 .. $iters) {
				$dbgtemp[$datper] = floor($dbgtemp[$datper] / $dbgtcnt[$datper]);
				if ($dbgtemp[$datper] > $newmaxval) {
					$newmaxval = $dbgtemp[$datper];
				}
			}
			if ($newmaxval) {
				$newmaxval = floor($newmaxval * 1.1);
			} else {
				$newmaxval = $ymaxval;
			}
			my @data = ([@datemarks], [@dbgtemp]);
			if ($allcnt > 1) {
				if ($kwh < 1000) {
					$kwh = sprintf("%.2f", ($kwh / 1000));
				} else {
					$kwh = sprintf("%.1f", ($kwh / 1000));
				}
			} else {
				$kwh = "0.00";
			}

			if ($grpval == 0) {
				$zdesc = "in zone $zdesc";
			} elsif ($grpval == 1) {
				$zdesc = "by thermostat $zdesc";
			}
			my $picname = $repfile."-".$sid.".png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			$graph->set( 
				title		=> "Metering $zdesc : $kwh kW.h",
				line_width	=> 2,
				two_axes	=> 0,
				x_label		=> '',
				y_label		=> 'Power Consumption, watt',
				y_min_value	=> 0,
				y_max_value	=> $newmaxval,
				y_number_format => '%d',
				y_tick_number	=> 15,
				x_label_skip	=> 3,
				dclrs		=> [ qw(blue green pink blue cyan) ],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-$sid.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";
			$gridcnt ++;
		}
	} elsif (($action eq "save") && ($houseid > 0) && ($srcval == 1)) {		# zigbee plugs
		use GD::Graph::lines;
		my $repname = "power-".sprintf("%05d", $houseid)."-".sprintf("%04d%02d%02d", $yearf, $monthf, $dayf)."-".sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
		my $repfile = $repfolder."/".$repname;
		my $housedb = "smart".sprintf("%05d", $houseid);
		my ($udatef, $udatet) = (0, 0);

		my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP($datef), UNIX_TIMESTAMP($datet)");
		foreach my $row (@$all) {
			($udatef, $udatet) = (@$row[0], @$row[1]);
		}
		undef $all;

		my %zlist = ();
		my $znum = 0;
		my $zlast = 0;
		my $all = $db->selectall_arrayref("SELECT zigbee_ha.device_id, devices.description FROM $housedb.zigbee_ha LEFT JOIN $housedb.devices ON devices.id = zigbee_ha.device_id WHERE zigbee_ha.cluster_id = 1794");
		foreach my $row (@$all) {
			$zlist{@$row[0]} = @$row[1];
			$znum ++;
			$zlast = @$row[0];
		}
		undef $all;

		foreach my $zid (sort keys %zlist) {
			my $ploty = ($zid == $zlast)?250:200;
			my $zdesc = $zlist{$zid};
			my $iters = 120;					# number of iteratio points
			my $idatp = 3;						# date placement per iteration
			my $dincr = floor(($udatet - $udatef) / $iters);	# seconds increment
			my $idatr = 0;						# date placement counter
			my @datemarks = ();
			my @dbgtemp = ();					# temperature debug only!
			my @dbgtcnt = ();
			for my $datper (0 .. $iters) {
				my ($dmsec,$dmmin,$dmhr,$dmday,$dmmon,$dmyr) = localtime(($datper * $dincr) + $udatef);
				$dmmon += 1;
				$dmyr += 1900;
				if ($idatr == 0) {
					$datemarks[$datper] = ($zid == $zlast)?(sprintf("%02d-%02d-%02d %02d:%02d", ($dmyr - 2000), $dmmon, $dmday, $dmhr, $dmmin)):" ";
					$idatr = $idatp;
				} else {
					$datemarks[$datper] = ($zid == $zlast)?"-":" ";
					$idatr--;
				}
				$dbgtemp[$datper] = 0;
				$dbgtcnt[$datper] = 1;
			}

			my ($kwh, $allcnt, $kkwh) = (0, 0, 0);
			my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), return_value FROM $housedb.zigbee_commands WHERE device_id = $zid AND updated BETWEEN $datef AND $datet ORDER BY id");
			foreach my $row (@$all) {
				my $otime = floor(((@$row[0] - $udatef) / ($udatet - $udatef)) * $iters);
				$dbgtemp[$otime] += floor(@$row[1] / 100);
				$dbgtcnt[$otime] ++;
				$allcnt ++;
				if ($kkwh > 0) {
					$kwh += (@$row[1] / 100) * ((@$row[0] - $kkwh) / 3600);
				}
				$kkwh = @$row[0];
			}
			undef $all;
			for my $datper (0 .. $iters) {
				$dbgtemp[$datper] = floor($dbgtemp[$datper] / $dbgtcnt[$datper]);
			}
			my @data = ([@datemarks], [@dbgtemp]);
			if ($allcnt > 1) {
				if ($kwh < 1000) {
					$kwh = sprintf("%.2f", ($kwh / 1000));
				} else {
					$kwh = sprintf("%.1f", ($kwh / 1000));
				}
			} else {
				$kwh = "0.00";
			}

			my $picname = $repfile."-".$zid.".png";
			my $graph = GD::Graph::lines->new(500, $ploty);
			$graph->set( 
				title		=> "Metering by $zdesc : $kwh kW.h",
				line_width	=> 2,
				two_axes	=> 0,
				x_label		=> '',
				y_label		=> 'Power Consumption, watt',
				y_min_value	=> 0,
				y_max_value	=> $ymaxval,
				y_number_format => '%d',
				y_tick_number	=> 15,
				x_label_skip	=> 3,
				dclrs		=> [ qw(blue green pink blue cyan) ],
				x_labels_vertical	=> 1
			);
			my $gd = $graph->plot(\@data);
			open(IMG, ">$picname");
			binmode IMG;
			print IMG $gd->png;
			my $chart = "<img src=\"connector/charts/$repname-$zid.png\" border=0 width=500 height=$ploty>";
			close(IMG);
			$replist .= "<tr><td width=\"500\">$chart</td></tr>\n";

		}
	} 

	my $grouptext = ($srcval)?"Metering device":$grpvals[$grpval];
	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--replist--/$replist/g;
		$inline =~ s/--houseid--/$lhouse/g;
		$inline =~ s/--year_f--/$lyearf/g;
		$inline =~ s/--ymax--/$lymax/g;
		$inline =~ s/--source--/$dsource/g;
		$inline =~ s/--grouptext--/$grouptext/g;
		$inline =~ s/--group--/$dgroup/g;
		$inline =~ s/--year_t--/$lyeart/g;
		$inline =~ s/--month_f--/$lmonthf/g;
		$inline =~ s/--month_t--/$lmontht/g;
		$inline =~ s/--day_f--/$ldayf/g;
		$inline =~ s/--day_t--/$ldayt/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# tunnel uptime report

if (($uimode eq "reports") && ($uismode eq "tunnel") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:$lcuryear;
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:$lcuryear;
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:$lcurmon;
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:$lcurmon;
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:$lcurday;
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:$lcurday;
	$dayf = fixdate($dayf, $monthf, $yearf);
	$dayt = fixdate($dayt, $montht, $yeart);
	my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
	my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
	if ($shdatef > $shdatet) {
		($montht, $monthf) = ($monthf, $montht);
		($dayt, $dayf) = ($dayf, $dayt);
		($yeart, $yearf) = ($yearf, $yeart);
	}
	my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt, $tunstat) = ("", "", "", "", "", "", "");
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $month (1 .. 12) {
		$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
		$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
	}
	for my $day (1 .. 31) {
		$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
		$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
	}
	my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
	my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
	my $houseid = (exists $FORM{houseid})?$FORM{houseid}:0;
	my $lhouse = "<option value=\"0\"".(($houseid == 0)?" selected=\"selected\"":"").">-- Select Core --</option>";
	{
		my $hidfilter = "systems.house_id > 0";
		if ($uaccess < 2) {
			$hidfilter = "systems.house_id IN ($housemask)";
		}
		my $all = $db->selectall_arrayref("SELECT systems.house_id, CONCAT(systemadd.name1,' ',systemadd.name2) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $hidfilter ORDER BY id");
		foreach my $row (@$all) {
			$lhouse .= "<option value=\"".@$row[0]."\"".((@$row[0] == $houseid)?" selected=\"selected\"":"").">".sprintf("%05d", @$row[0]).": ".@$row[1]."</option>";
		}
		undef $all;
	}
	my $replist = "";

	if (($action eq "save") && ($houseid > 0)) {
		my ($stampf, $stampt) = $db->selectrow_array("SELECT UNIX_TIMESTAMP('$datef'), UNIX_TIMESTAMP('$datet')");
		my $totint = $stampt - $stampf;
		my $totrec = 0;
		my $conint = 0;
		my $const = -1;
		my $stamp = 0;
		my $ostamp = $stampf;
		my ($lastst) = $db->selectrow_array("SELECT ip_tunnel FROM tunnel WHERE house_id = $houseid");
		my $all = $db->selectall_arrayref("SELECT UNIX_TIMESTAMP(updated), status FROM tconnect WHERE house_id = $houseid AND updated BETWEEN $datef AND $datet ORDER BY id ASC");
		foreach my $row (@$all) {
			$totrec ++;
			$stamp = @$row[0];
			my $status = @$row[1];
			if ($const != $status) {
				unless ($status) {
					$conint += ($stamp - $ostamp);
				}
				$const = $status;
				$ostamp = $stamp;
			}
		}
		undef $all;
		if (($const > 0) && ($lastst ne "")) {
			$conint += ($stampt - $ostamp);
		}
		my $uptime = sprintf("%.1f", (($conint / $totint) * 100));
		$tunstat = "<b>Tunnel uptime for selected period: $uptime%<br><br>Total log records for period: $totrec<br>Currently tunnel is ".(($lastst ne "")?"connected":"disconnected")."</b>";
	} else {
		$tunstat = "<b>No core selected for report</b>";
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--tunstat--/$tunstat/g;
		$inline =~ s/--houseid--/$lhouse/g;
		$inline =~ s/--year_f--/$lyearf/g;
		$inline =~ s/--year_t--/$lyeart/g;
		$inline =~ s/--month_f--/$lmonthf/g;
		$inline =~ s/--month_t--/$lmontht/g;
		$inline =~ s/--day_f--/$ldayf/g;
		$inline =~ s/--day_t--/$ldayt/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# updates manager

if (($uimode eq "userinfo") && ($uismode eq "updates") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my @updates = ("database", "hvac", "muxdemux", "webui", "ota", "zstack", "wifi2ir", "espfw", "avrfw");
	my %upnames = ("database", "Database structure and data", "hvac", "HVAC server and other residental modules", "muxdemux", "Muxdemux and low-level modules", "webui", "Smart controller main website", "ota", "Zigbee remotes OTA firmware updates", "zstack", "Zigbee Stack binaries updates", "wifi2ir", "WiFi2iR System software updates", "espfw", "Cello Damper ESP firmware updates", "avrfw", "Cello Damper ATmega firmware updates");
	my $upsel = ($FORM{upsel} eq "")?$updates[0]:$FORM{upsel};
	my ($updsel, $packlist) = ("", "");
	my $isESP = (($upsel eq "espfw") || ($upsel eq "avrfw"))?1:0;

	if ($action eq "remove") {
		my $infile = $upfolder."/".$FORM{name};
		if (-e $infile) {
			unlink($infile);
			$message = "Package ".$FORM{name}." removed";
		}
	}

	if ($action eq "upload") {
		my $infile = "/tmp/".$FORM{file};		# uploaded to TMP folder
		if ((-e $infile) && ($isESP)) {
		} elsif ((-e $infile) && !($isESP)) {
			my $revcnt = 0;
			my $newfile = "";
			my $newver = "0.0.0.0";
			while ($revcnt < 999) {
				$newfile = $upsel."-".($lcuryear - 2000)."_".($lcurmon + 0)."_".($lcurday + 0)."_".$revcnt;
				$newver = ($lcuryear - 2000).".".($lcurmon + 0).".".($lcurday + 0).".".$revcnt;
				if (-e $upfolder."/".$newfile.".tgz") {
					$revcnt ++;
				} else {
					last;
				}
			}
			my $upscript = "/tmp/upproc.sh";
			open(UPS, ">$upscript");
			print UPS '#!/bin/sh'."\n\n";
			print UPS "cd /tmp\n";
			print UPS "mkdir $newfile\n";
			print UPS "cd $newfile\n";
			print UPS "tar xzvf $infile\n";
			print UPS "if [ -e \"manifest\" ]; then\n";	# check for manifest existance
			print UPS "echo UPDATE versions SET status = 0, current = \\'$newver\\' WHERE module = \\'$upsel\\'\\; >> ./db_update.sql\n";
			print UPS "chmod 755 update.sh\n";
			print UPS "chmod 755 post_update.sh\n";
			print UPS "tar czf ".$upfolder."/".$newfile.".tgz *\n";
			print UPS "/usr/bin/ccrypt -e -k /etc/upkey ".$upfolder."/".$newfile.".tgz\n";
			print UPS "mv ".$upfolder."/".$newfile.".tgz.cpt ".$upfolder."/".$newfile.".tgz\n";
			print UPS "fi\n";
			print UPS "cd ..\n";
			print UPS "rm -rf $newfile/*\n";
			print UPS "rmdir $newfile\n";
			print UPS "rm $infile\n";
			close(UPS);
			system("chmod 755 $upscript");
			system("$upscript");
#			unlink($upscript);
			if (-e $upfolder."/".$newfile.".tgz") {
				$message = "File ".$FORM{file}." uploaded. Package ".$newfile.".tgz created";
				my $sth = $db->prepare("SELECT house_id FROM systems");
				$sth->execute;
				unless ($sth->rows == 0) {
					my ($hid) = $sth->fetchrow_array();
					my $homedb = sprintf("smart%05d", $hid);
					$db->do("UPDATE ".$homedb.".versions SET remote = '$newver' WHERE module = '$upsel'");
				}
			} else {
				$message = "Unable to process ".$FORM{file}." and create package ".$newfile.".tgz";
			}
		}		
	}
	
	for my $upitems (0 .. $#updates) {
		$updsel .= "<option value=\"".$updates[$upitems]."\" ".(($updates[$upitems] eq $upsel)?" selected=\"selected\"":"").">".$updates[$upitems]." - ".$upnames{$updates[$upitems]}."</option>";
	}

	{					# reload local list of files here
		opendir(DIR, $upfolder);
		my @dirfiles = readdir(DIR);
		@dirfiles = sort {(stat $upfolder."/".$b)[10] <=> (stat $upfolder."/".$a)[10]} @dirfiles;
		closedir(DIR);

		my $packcnt = 0;
		foreach my $infile (@dirfiles) {
			if ($infile =~ m/^(\w+)\-(\d+)_(\d+)_(\d+)_(\d+)\.tgz$/) {
				my $modname = $1;
				my $modver = $2.".".$3.".".$4.".".$5;
				my $dtime = (stat($upfolder."/".$infile))[10];
				my ($dsec, $dmin, $dhour, $dday, $dmonth, $dyear) = (localtime($dtime))[0,1,2,3,4,5];
				my $ddtime = "$dday ".$smonths[$dmonth + 1]." ".($dyear + 1900)." ".sprintf("%02d",$dhour).":".sprintf("%02d",$dmin).":".sprintf("%02d",$dsec);
				my $dsize = (stat($upfolder."/".$infile))[7];
				if ($modname eq $upsel) {
					$packlist .= "<tr><td>$infile</td><td align=center>$ddtime</td><td align=center>".sprintf("%.1f",($dsize / 1024))." Kb</td><td align=center><a href=\"./engine.pl?mode=$uimode&submode=$uismode&action=remove&upsel=$upsel&name=$infile\">Delete package</a></td></tr>\n";
					$packcnt ++;
				}
			}
		}
		if ($packcnt == 0) {
			$packlist .= "<tr><td colspan=4><br>No update packages found. You have to upload some</td></tr>\n";
		}
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--updsel--/$updsel/g;		# list of updates
		$inline =~ s/--upsel--/$upsel/g;		# selected update
		$inline =~ s/--packlist--/$packlist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# tunnel manager

if (($uimode eq "systems") && ($uismode eq "tunnel") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:50) + 0;
	my $sort = (exists $FORM{sort})?$FORM{sort}:1;
	my $sortasc = $FORM{asc} + 0;
	my @dsort = ("", "", "", "", "", "");
	my @tsort = ("tunnel.username", "tunnel.house_id", "tunnel.connected", "tunnel.ip_remote", "tunnel.ip_tunnel", "systemadd.address2");
	if ($eccc) {
		@tsort = ("systems.description", "systems.house_id", "systems.connected", "systems.ip_address", "tunnel.ip_tunnel", "systemadd.address2");
	}
	$dsort[$sort] = (($sortasc == 0)?"<b>&nbsp;&uarr;</b>":"<b>&nbsp;&darr;</b>");
        my $tunfile = "/tmp/openvpn-serverase-status.log";
        my %tunips = ();
        if (-e $tunfile) {
        	open(TUF, "<$tunfile");
        	while(<TUF>) {
        		my $tunline = $_;
        		chomp($tunline);
        		if ($tunline =~ m/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\,([a-z0-9]+)\,/) {
        			$tunips{$2} = $1;
#        			$debug .= $2." ".$tunips{$2}."<br>";
        		}
        	}
        	close(TUF);
        }
	my $hidfilter = ($uaccess < 2)?"AND tunnel.house_id IN ($housemask)":"";
	my $tunlist = "";
        my $maxrec = $perpage;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(tunnel.id) FROM tunnel WHERE tunnel.status < 100 $hidfilter");
        if ($eccc) {
		($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems");
        }
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
        my $squery = "SELECT tunnel.username, tunnel.house_id, tunnel.connected, tunnel.ip_remote, tunnel.ip_tunnel, tunnel.status, systemadd.address2 FROM tunnel LEFT JOIN systemadd ON systemadd.house_id = tunnel.house_id WHERE status < 100 $hidfilter ORDER BY ".$tsort[$sort].(($sortasc == 0)?" ASC":" DESC")." LIMIT $fromrec, $maxrec";
	if ($eccc) {
		$squery = "SELECT SUBSTRING(systems.description, -12), systems.house_id, systems.connected, systems.ip_address, tunnel.ip_tunnel, tunnel.status, systemadd.address2 FROM systems LEFT JOIN tunnel ON tunnel.house_id = systems.house_id LEFT JOIN systemadd ON systemadd.house_id = systems.house_id ORDER BY ".$tsort[$sort].(($sortasc == 0)?" ASC":" DESC")." LIMIT $fromrec, $maxrec";
	}
	my $all = $db->selectall_arrayref($squery);
	my $stylecnt = 0;
	foreach my $row (@$all) {
		if ((@$row[4] eq "") && (exists $tunips{@$row[0]})) {
			@$row[4] = $tunips{@$row[0]};
		}
		$tunlist .= "<tr".(($stylecnt & 1)?"":" style=\"background-color: #f1f3f5;\"")."><td nowrap=\"nowrap\" width=\"100\">".uc(@$row[0])."</td>
				<td nowrap=\"nowrap\" width=\"60\">".((@$row[1] eq "")?"N/A":sprintf("%05d", @$row[1]))."</td>
				<td nowrap=\"nowrap\" width=\"125\">".((@$row[2] eq "")?"Never":@$row[2])."</td>
				<td nowrap=\"nowrap\" width=\"100\">".((@$row[5] == 1)?"MAC Blocked":((@$row[3] eq "")?"Disconnected":((($uaccess < 2) || (! $eccc))?@$row[3]:"<a href=\"http://".@$row[3]."/\" target=_blank>".@$row[3]."</a>")))."</td>
				<td nowrap=\"nowrap\" width=\"90\">".((@$row[4] eq "")?"Disconnected":(($uaccess < 2)?@$row[4]:"<a href=\"http://".@$row[4]."/\" target=_blank>".@$row[4]."</a>"))."</td>
				<td nowrap=\"nowrap\" width=\"293\">".@$row[6]."</td>
				</tr>\n";
		$stylecnt ++;
	}
	undef $all;
	my $nasc = ($sortasc == 0)?1:0;

	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		</script>
EOF

	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (20, 50, 100);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";
	
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--sort0--/$dsort[0]/g;
		$inline =~ s/--sort1--/$dsort[1]/g;
		$inline =~ s/--sort2--/$dsort[2]/g;
		$inline =~ s/--sort3--/$dsort[3]/g;
		$inline =~ s/--sort4--/$dsort[4]/g;
		$inline =~ s/--sort5--/$dsort[5]/g;
		$inline =~ s/--asc--/$sortasc/g;
		$inline =~ s/--nasc--/$nasc/g;
		$inline =~ s/--sort--/$sort/g;
		$inline =~ s/--tunlist--/$tunlist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
	$top1class = "Top1B";
}

# systems status

if (($uimode eq "systems") && ($uismode eq "status") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $sort = (exists $FORM{sort})?$FORM{sort}:1;
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:50) + 0;
	my $sortasc = $FORM{asc} + 0;
	my @dsort = ("", "", "", "", "", "", "", "");
	my @tsort = ("tunnel.username", "systems.house_id", "tunnel.ip_tunnel", "systemadd.zed_online", "systemadd.zed_offline", "systemadd.zr_count", "systemadd.bypass", "systems.connected");
	$dsort[$sort] = (($sortasc == 0)?"<b>&nbsp;&uarr;</b>":"<b>&nbsp;&darr;</b>");
        my $tunfile = "/tmp/openvpn-serverase-status.log";
        my %tunips = ();
        if (-e $tunfile) {
        	open(TUF, "<$tunfile");
        	while(<TUF>) {
        		my $tunline = $_;
        		chomp($tunline);
        		if ($tunline =~ m/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\,([a-z0-9]+)\,/) {
        			$tunips{$2} = $1;
        		}
        	}
        	close(TUF);
        }
	my $hidfilter = ($uaccess < 2)?"AND systems.house_id IN ($housemask)":"";
	my $infolist = "";
	{			# update counters if needed
		my $all = $db->selectall_arrayref("SELECT house_id, zed_online, zed_offline, zr_count, bypass FROM systemadd WHERE zed_online = -1 OR zed_offline = -1 OR zr_count = -1 OR bypass = -1");
		foreach my $row (@$all) {
			my $hidb = "smart".sprintf("%05d", @$row[0]);
			my ($zonl, $zofl, $zrcnt, $byp) = (@$row[1], @$row[2], @$row[3], @$row[4]);
			if (($zonl == -1) || ($zofl == -1)) {
				($zonl) = $db->selectrow_array("SELECT COUNT(*) FROM $hidb.zigbee_ase WHERE device_status IN (1,4,5)");
				($zofl) = $db->selectrow_array("SELECT COUNT(*) FROM $hidb.zigbee_ase WHERE device_status = 0");
				if ($zonl eq "") {
					$zonl = "NULL";
				}
				if ($zofl eq "") {
					$zofl = "NULL";
				}
			}
			if ($zrcnt == -1) {
				($zrcnt) = $db->selectrow_array("SELECT COUNT(DISTINCT addr64) FROM $hidb.zigbee_ha");
				if ($zrcnt eq "") {
					$zrcnt = "NULL";
				}
			}
			if ($byp == -1) {
				$byp = 0;
				my ($hbypass) = $db->selectrow_array("SELECT status FROM $hidb.bypass WHERE type_ = 0 ORDER BY id DESC LIMIT 1");
				my ($bypweb) = $db->selectrow_array("SELECT status FROM $hidb.bypass WHERE type_ BETWEEN 1 AND 2 ORDER BY id DESC LIMIT 1");	# web and mobile app
				if ($hbypass > 0) {
					$byp = 2;
				} elsif ($bypweb > 0) {
					$byp = 1;
				}
			}
			$db->do("UPDATE systemadd SET zed_online = '$zonl', zed_offline = '$zofl', zr_count = '$zrcnt', bypass = '$byp' WHERE house_id = ".@$row[0]);
		}
		undef $all;
	}
        my $maxrec = $perpage;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN tunnel ON tunnel.house_id = systems.house_id WHERE tunnel.status < 100 $hidfilter");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $all = $db->selectall_arrayref("SELECT tunnel.username, systems.house_id, tunnel.ip_tunnel, systemadd.zed_online, systemadd.zed_offline, systemadd.zr_count, systemadd.bypass, systems.connected FROM systems LEFT JOIN tunnel ON tunnel.house_id = systems.house_id LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE tunnel.status < 100 $hidfilter ORDER BY ".$tsort[$sort].(($sortasc == 0)?" ASC":" DESC")." LIMIT $fromrec, $maxrec");
	my $stylecnt = 0;
	my @bstatus = ("Retrosave", "Software Bypass", "Hardware Bypass");
	foreach my $row (@$all) {
		if ((@$row[2] eq "") && (exists $tunips{@$row[0]})) {
			@$row[2] = $tunips{@$row[0]};
		}
		$infolist .= "<tr".(($stylecnt & 1)?"":" style=\"background-color: #f1f3f5;\"")."><td nowrap=\"nowrap\">".uc(@$row[0])."</td>
				<td nowrap=\"nowrap\">".((@$row[1] eq "")?"N/A":sprintf("%05d", @$row[1]))."</td>
				<td nowrap=\"nowrap\">".((@$row[2] eq "")?"Disconnected":(($uaccess < 2)?@$row[2]:"<a href=\"http://".@$row[2]."/\" target=_blank>".@$row[2]."</a>"))."</td>
				<td nowrap=\"nowrap\">".(((@$row[6] eq "") || (@$row[6] eq "-1"))?"N/A":$bstatus[@$row[6]])."</td>
				<td nowrap=\"nowrap\">".((@$row[7] eq "")?"Never":@$row[7])."</td>
				</tr>\n";
		$stylecnt ++;
	}
	undef $all;
	my $nasc = ($sortasc == 0)?1:0;

	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		</script>
EOF

	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (20, 50, 100);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--sort0--/$dsort[0]/g;
		$inline =~ s/--sort1--/$dsort[1]/g;
		$inline =~ s/--sort2--/$dsort[2]/g;
		$inline =~ s/--sort3--/$dsort[3]/g;
		$inline =~ s/--sort4--/$dsort[4]/g;
		$inline =~ s/--sort5--/$dsort[5]/g;
		$inline =~ s/--sort6--/$dsort[6]/g;
		$inline =~ s/--sort7--/$dsort[7]/g;
		$inline =~ s/--asc--/$sortasc/g;
		$inline =~ s/--nasc--/$nasc/g;
		$inline =~ s/--sort--/$sort/g;
		$inline =~ s/--infolist--/$infolist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
	$top1class = "Top1B";
}

# core remote update

if (($uimode eq "systems") && ($uismode eq "update") && ($uaccess >= $alevel{$uimode.$uismode})) {
	opendir(DIR, $upfolder);
	my @dirfiles = readdir(DIR);
	closedir(DIR);
	my %maxversn = ();
	my %maxverst = ();
	foreach my $infile (@dirfiles) {
		if ($infile =~ m/^(\w+)\-(\d+)_(\d+)_(\d+)_(\d+)\.tgz$/) {
			my $modname = $1;
			my $modver = $2.".".$3.".".$4.".".$5;
			my $newver = $2 * 8760 + $3 * 720 + $4 * 24 + $5;
			if (exists $maxversn{$modname}) {
				if ($newver > $maxversn{$modname}) {
					$maxverst{$modname} = $modver;
					$maxversn{$modname} = $newver;
				}
			} else {
				$maxverst{$modname} = $modver;
				$maxversn{$modname} = $newver;
			}
		}
	}
	my %modules = ("webui", 0, "hvac", 1, "muxdemux", 2, "database", 3, "ota", 4, "zstack", 5);
	foreach my $mod (keys %maxverst) {
		$maxverst{$modules{$mod}} = $maxverst{$mod};		# reindex with ids
	}

	if ($action eq "stop") {
		my $hid = $FORM{hid};
		if ($hid) {
			my $all = $db->selectall_arrayref("SELECT other FROM core_update WHERE house_id = $hid");
			my $needrest = 0;
			foreach my $row (@$all) {
				if (@$row[0] == 6) {		# retrosave mode preserved
					$needrest ++;
				}
			}
			undef $all;
			my $dbname = sprintf("smart%05d", $hid);
			if ($needrest) {
				$db->do("INSERT INTO $dbname.bypass VALUES (NULL, NOW(), 1, 0, 'Toggle from Cloud auto updates')");
				$db->do("UPDATE $dbname.hvac SET value_ = 1 WHERE option_ = 'furnace.mode'");		# restore retrosave
			}
			$db->do("UPDATE $dbname.versions SET status = 0");		# clear update status to Core
			$db->do("UPDATE core_update SET status = 0, other = NULL WHERE house_id = $hid");	# clear update status to Cloud
		}
	}
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $perpage = ((exists $FORM{perpage})?$FORM{perpage}:50) + 0;
	my $hidfilter = ($uaccess < 2)?"AND systems.house_id IN ($housemask)":"";
	my $infolist = "";
        my $maxrec = $perpage;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems $hidfilter");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $all = $db->selectall_arrayref("SELECT systems.house_id, systemadd.bypass FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id $hidfilter ORDER BY systems.house_id LIMIT $fromrec, $maxrec");
	my ($hmin, $hmax) = (0, 0);
	my %mode = ();
	my %uplist = ();
	foreach my $row (@$all) {
		if (! $hmin) {
			$hmin = @$row[0];
		}
		$hmax = @$row[0];
		my $dbname = sprintf("smart%05d", $hmax);
		my $byp = @$row[1];
		if ($byp == -1) {		# update required
			$byp = 0;
			my ($hbypass) = $db->selectrow_array("SELECT status FROM $dbname.bypass WHERE type_ = 0 ORDER BY id DESC LIMIT 1");
			my ($bypweb) = $db->selectrow_array("SELECT status FROM $dbname.bypass WHERE type_ BETWEEN 1 AND 2 ORDER BY id DESC LIMIT 1");	# web and mobile app
			if ($hbypass > 0) {
				$byp = 1;
			} elsif ($bypweb > 0) {
				$byp = 1;
			}
			$db->do("UPDATE systemadd SET bypass = $byp WHERE house_id = $hmax");
		}
		$mode{@$row[0]} = $byp;
		if (($action eq "start") && (exists $FORM{"home$hmax"})) {
			$db->do("UPDATE $dbname.versions SET status = 5");		# set check update status to Core
			$db->do("UPDATE core_update SET status = 5, other = '5' WHERE house_id = $hmax");	# set update status to Cloud
			$db->do("INSERT INTO $dbname.history_store VALUES (NULL, 'hvac_actions', '<27>0</27>', '<27>0</27>', 5)");	# send check for updates command to Core
		}
	}
	undef $all;
	my $stylecnt = 0;
	my $checkonp = 0;
	my @bstatus = ("Retrosave", "Bypass", "Bypass");
	my @ustatus = ("Idle", "Updating", "Downloading", "D/L error", "Apply error", "Checking", "Pending");
	my $all = $db->selectall_arrayref("SELECT house_id, service_id, updated, status, version, other FROM core_update WHERE house_id BETWEEN $hmin AND $hmax ORDER BY house_id, service_id");
	my $alche = 0;
	foreach my $row (@$all) {
		if (@$row[1] == 0) {
			$infolist .= "<tr".(($stylecnt & 1)?"":" style=\"background-color: #f1f3f5;\"")."><td nowrap=\"nowrap\" width=\"60\">".sprintf("%05d", @$row[0])."</td>
				<td nowrap=\"nowrap\" width=\"110\">".@$row[2]."</td>
				<td nowrap=\"nowrap\" width=\"60\">".$bstatus[$mode{@$row[0]}]."</td>";
			$alche = 0;
		}
		if ((! @$row[3]) && (@$row[5])) {
			@$row[3] = 6;
		}
		my $modver = @$row[4];
		if ($modver eq $maxverst{@$row[1]}) {
			$modver = "<font color=\"#007000\">$modver</font>";
		}
		$infolist .= "<td nowrap=\"nowrap\" width=\"80\">".((@$row[3])?($ustatus[@$row[3]]):($modver))."</td>";
		if ((@$row[3]) || (@$row[5])) {
			$alche = 1;
		}
		if (@$row[1] == 5) {
			if ($alche) {
				$infolist .= "<td nowrap=\"nowrap\" width=\"30\"><b><a href=\"#\" style=\"navi\" onClick=\"StopUpd(".@$row[0].");\"><font color=\"#F33\">[X]</font></a></b></td></tr>\n";
				$checkonp ++;
			} else {
				$infolist .= "<td nowrap=\"nowrap\" width=\"30\"><input style=\"padding:0; margin:0;\" id=\"home".@$row[0]."\" name=\"home".@$row[0]."\" type=\"checkbox\"></td></tr>\n";
			}
			$stylecnt ++;
		}
	}
	undef $all;

	if ($checkonp) {
		$headadd .= "<meta http-equiv=\"refresh\" content=\"60;URL=./engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage\">\n";
	}
	$headadd .= <<EOF;
		<script language="JavaScript">
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.selectform.submit();
		}
		function VPagerDirect(vpage) {
			document.getElementById('perpage').value = vpage;
			document.getElementById('page').value = '1';
			document.selectform.submit();
		}
		function toggleIPAll() {
			var checkboxes = document.getElementsByTagName('input');
			var ttflag = 0;
			var ttstatus = true;
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					if (checkboxes[i].disabled == 0) {
						if (ttflag == 0) {
							ttflag ++;
							ttstatus = checkboxes[i].checked;
						} else {
							checkboxes[i].checked = ttstatus;
						}
					}
				}
			}
		}
		function StopUpd(hid) {
			var answer = confirm ("Are you sure to stop Core "+hid+" updates?");
			if (answer) {
				window.location = './engine.pl?mode=$uimode&submode=$uismode&page=$curpage&perpage=$perpage&hid='+hid+'&action=stop';
			}
		}
		</script>
EOF

        my $extracip = "<input style=\"padding: 0px; margin: 0px;\" name=\"ipupdmain\" type=\"checkbox\" onChange=\"toggleIPAll();\">";
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\">Prev.page</a>";
	}
	$pager .= "&nbsp;&nbsp;<select name=\"vpage\" onChange=\"PagerDirect(this.value);\">";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		$pager .= "<option value=\"$ii\" ".(($ii == $curpage)?"selected=\"selected\"":"").">Page $ii</option>";
	}
	$pager .= "</select>&nbsp;&nbsp;";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page</a>";
	}
	my $recor = "<select name=\"vrpage\" onChange=\"VPagerDirect(this.value);\">";
	my @rvals = (20, 50, 100);
	foreach my $ii (@rvals) {
		$recor .= "<option value=\"$ii\" ".(($ii == $perpage)?"selected=\"selected\"":"").">$ii</option>";
	}
	$recor .= "</select>";

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--recor--/$recor/g;
		$inline =~ s/--extracip--/$extracip/g;
		$inline =~ s/--infolist--/$infolist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
	$top1class = "Top1B";
}

# access password

if (($uimode eq "systems") && ($uismode eq "retrosave") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $perpage = 50;		# default value
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $stfilter = "";
	my $fstatus = ((exists $FORM{sfilter})?$FORM{sfilter}:3) + 0;		# all by default
	my @stlist = ("Active", "Paused", "Deleted", "All");
	for my $ii (0 .. $#stlist) {
		$stfilter .= "<option value=\"".$ii."\" ".(($ii == $fstatus)?" selected=\"selected\"":"").">".$stlist[$ii]."</option>";
	}
	if ($uaccess >= 2) {
		if ($action eq "unreg") {
			my $homeid = $FORM{homeid} + 0;
			my $rdbid = sprintf("smart%05d", $homeid);
			$db->do("DROP DATABASE IF EXISTS $rdbid");
			$db->do("DELETE FROM systems WHERE house_id = $homeid");
			$db->do("DELETE FROM sysprop WHERE house_id = $homeid");
			$db->do("DELETE FROM tunnel WHERE house_id = $homeid");
                        $action = "view";
		}
		if ($action eq "tunnel") {
			my $homeid = sprintf("%05d", $FORM{homeid});	# remote homeID
			my ($macaddr) = $db->selectrow_array("SELECT LOWER(value) FROM smart".$homeid.".smartstatus WHERE group_ = 'network' AND name = 'mac'");
			my $salt = "ase2015";
			my $passwd = "";
			if ($macaddr ne "") {
				$passwd = md5_hex($salt.$macaddr);
				$db->do("DELETE FROM tunnel WHERE username = '$macaddr'");
				$db->do("INSERT INTO tunnel VALUES (NULL, '$homeid', '$macaddr', '$passwd', NULL, NULL, NULL, 0)");
				$db->do("INSERT INTO smart".$homeid.".history_store VALUES (NULL, 'hvac_actions', '<24>0</24>', '<24>0</24>', 5)");	# restart tunnel remotely
			}
                        $action = "view";
		}
	}
	my $corelist = "";
	if ($action eq "endclone") {
		my $cto = $FORM{homeid} + 0;
		if ($cto) {
			$db->do("UPDATE clone SET status = 0, updated = NOW() WHERE coreto = $cto");
		}
	}
	if ($action eq "runclone") {
		my $cfrom = $FORM{copyfrom} + 0;
		my $cto = $FORM{homeid} + 0;
		if (($cto) && ($cfrom)) {
			$db->do("DELETE FROM clone WHERE coreto = $cto");
			$db->do("INSERT INTO clone VALUES (NULL, $cfrom, $cto, NOW(), NOW(), 1)");
			$forkme = 1;		# invoke bg process
			my $homedb = sprintf("smart%05d", $cto);
			$db->do("INSERT INTO $homedb.history_store VALUES (NULL, 'hvac_actions', '<56>0</56>', '<56>0</56>', 5)");	# set clone flag
		}
	}
	if ($action eq "clone") {
		my $hid = $FORM{homeid} + 0;
		$corelist = "<select name=\"coresel\" onChange=\"RunClone(this.value, $hid, $curpage);\" style=\"width:155px;\"><option value=\"0\">-- Select the Core --</option>";
		my $filter = "";
		if ($uaccess < 2) {
			$filter = " AND tunnel.house_id IN ($housemask)";
		}
		my $all = $db->selectall_arrayref("SELECT tunnel.house_id, systemadd.name1, systemadd.name2 FROM tunnel LEFT JOIN systemadd ON systemadd.house_id = tunnel.house_id WHERE tunnel.house_id IS NOT NULL $filter ORDER BY id");
		foreach my $row (@$all) {
			my $houseid = @$row[0];
			$corelist .= "<option value=\"$houseid\">$houseid:".@$row[1]." ".@$row[2]."</option>";
		}
		undef $all;
		$corelist .= "</select>";
		$headadd .= <<EOF;
			<script language="JavaScript">
			function RunClone(corefrom, coreto, curpage) {
				if (corefrom > 0) {
					var answer = confirm ("Are you sure to copy all settings from Core "+corefrom+" to Core "+coreto+"?\\n\\nAction will overwrite all current settings of Core "+coreto);
					if (answer) {
						window.location = './engine.pl?mode=systems&submode=retrosave&action=runclone&copyfrom='+corefrom+'&homeid='+coreto+'&page='+curpage;
					}
				}
			}
			</script>
EOF
	}
        if ($action eq "connect") {
		my $homeid = sprintf("%05d", $FORM{homeid});	# remote homeID
		my ($allowed) = $db->selectrow_array("SELECT ($homeid IN ($housemask))");		# check if connect allowed
		if (($allowed) || ($uaccess >= 2)) {
			my $rdsn = "DBI:mysql:smart".$homeid.":".$config{dbhost};
			my $rdbuser = "dbuser".$homeid;
			my $rdbpass = "dbpass".$homeid;
			my ($rclientid, $rclientacc) = (-1, -1);
			my $rdb = DBI->connect($rdsn, $rdbuser, $rdbpass);
			if ($rdb) {
				my $sth = $rdb->prepare("SELECT id, access FROM users ORDER BY access DESC LIMIT 1");
				$sth->execute;
				unless ($sth->rows == 0) {
					my ($id, $access) = $sth->fetchrow_array();
					if ($access >= 1) {					# use admin only
						$rclientid = $id;
						$rclientacc = $access;
					}
					$sth->finish;
				} else {
					$sth->finish;
				}
                
				if ($clientid >= 0) {
					$rdb->do("INSERT INTO sessions VALUES(NULL,$rclientid,'$userhash',now(),date_add(now(),interval $signtime minute),$rclientacc,$homeid)");
					my $sth = $rdb->prepare("SELECT last_insert_id() FROM sessions");
					$sth->execute;
					($sessid) = $sth->fetchrow_array();
					$sth->finish;
                
					my $fut_time = gmtime(time() + (60 * 60 * 24 * 30))." GMT";  	# cookie expires in 30 days
					my $cookie = $cooknames[3]."=$sessid; path=/; expires=$fut_time;";
					print "Set-Cookie: " . $cookie . "\n";
					$cookie = $cooknames[4]."=$homeid; path=/; expires=$fut_time;";
					print "Set-Cookie: " . $cookie . "\n";
                
					print "Content-type: text/html\n\n";
					print "<HEAD>\n";
					print "<META HTTP-EQUIV=REFRESH CONTENT=\"0;URL=".$connweb."?mode=status&submode=system\">\n";
					print "</HEAD>\n";
					$rdb->disconnect();
					$db->disconnect();
					exit;
				}
			}
		}
		$action = "view";
        }

	my $hidfilter = "systems.house_id > 0";
	if ($uaccess < 2) {
		$hidfilter = "systems.house_id IN ($housemask)";
	}
	my $stafilter = "1 = 1";		# any
	my @stlist = ("Active", "Paused", "Deleted", "All");
	if ($fstatus == 0) {
		$stafilter = "tunnel.status = 0";		# active
	} elsif ($fstatus == 1) {
		$stafilter = "tunnel.status = 2";		# paused
	} elsif ($fstatus == 2) {
		$stafilter = "tunnel.status = 3";		# deleted
	}
	my $sfilter = ($search eq "")?"$hidfilter AND $stafilter":"(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%' OR UCASE(systemadd.company) LIKE '%".uc($search)."%') AND $hidfilter AND $stafilter";
        my $maxrec = 10;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN tunnel ON tunnel.house_id = systems.house_id LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }
	my $homelist = "";
	my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.version, systems.connected, systems.description, systemadd.name1, systemadd.name2, clone.status, (UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(systems.connected)), systems.ip_address, systemadd.company, tunnel.status FROM systems LEFT JOIN tunnel ON tunnel.house_id = systems.house_id LEFT JOIN systemadd ON systemadd.house_id = systems.house_id LEFT JOIN clone ON clone.coreto = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $fromrec, $maxrec");	# only 20 records on page
	foreach my $row (@$all) {
		my $houseid = @$row[0];
		my $homeid = sprintf("%05d", $houseid);
		my $homedesc = @$row[3];
		my $owname = "";
		if ((@$row[4] ne "") || (@$row[5] ne "")) {
			$owname = @$row[4]." ".@$row[5];
		}
		if (@$row[9] ne "") {
			if ($owname eq "") {
				$owname = @$row[9];
			} else {
				$owname = @$row[9]." - ".$owname;
			}
		}
		if ($owname eq "") {
			$owname = "No name or company specified";
		} else {
			if ($owname =~ m/ \- /) {
				$owname = "<b>$owname</b>";
			} else {
				$owname = "Site administrator: <b>$owname</b>";
			}
		}
		my $homever = @$row[1];
		my $homeconn = @$row[2];
		my $isclone = @$row[6] + 0;
		my $ostatus = ((@$row[7] + 0) < 3600)?"Online":"Offline";		# 1 hour offline threshold
		my $sysip = @$row[8];
#		my ($ups) = $db->selectrow_array("SELECT value_ FROM sysprop WHERE house_id = $houseid AND name_ = 'ups'");	# obsolete
		my ($ups) = $db->selectrow_array("SELECT value_ FROM smart$homeid.hvac WHERE option_ = 'system.ups_status'");
		my ($corehost) = $db->selectrow_array("SELECT value_ FROM smart$homeid.hvac WHERE option_ = 'system.hostname'");
		my @tslist = ("Active virtual core", "Active physical core", "Suspended virtual core", "Deleted virtual core", "Physical core");
		my ($tunstat, $tunremip) = $db->selectrow_array("SELECT status, ip_remote FROM tunnel WHERE house_id = $houseid");
		if ($tunstat eq "") {
			$tunstat = 4;		# tunnel record missing
		} else {
			if ($tunremip ne "") {
				$tunstat = 1;		# physical core
			}
		}
		if (($corehost ne "") && (! $eccc)) {
			$corehost = "<span style=\"float:right; margin-right:22px;\"><a href=\"http://$corehost.local:51000\" class=\"navi\" target=\"_blank\">$corehost.local</a></span>";
		} else {
			$corehost = "<span style=\"float:right; margin-right:22px;\"><b>".$tslist[$tunstat]."</b></span>";
		}
		my $upstatus = "Line Powered<br>$ostatus";
		if ($ups eq "ONLINE") {
			my ($batt) = $db->selectrow_array("SELECT value_ FROM smart$homeid.hvac WHERE option_ = 'system.ups_bcharge'");
			$batt += 0;
			$upstatus = "Main UPS Power Feed ON<br>$ostatus, Battery level ".$batt."%";
		} elsif ($ups eq "COMMLOST") {
			# TBD
		} elsif ($ups eq "ONBATT") {
			my ($batt) = $db->selectrow_array("SELECT value_ FROM smart$homeid.hvac WHERE option_ = 'system.ups_bcharge'");
			$batt += 0;
			$upstatus = "Main UPS Power Feed OFF<br>$ostatus, Battery level ".$batt."%";
		}
		my ($tstamp, $uptime) = $db->selectrow_array("SELECT updated, value FROM smart".$homeid.".smartstatus WHERE group_ = 'health' AND name = 'uptime'");
		my ($macaddr, $homefirst, $curmode, $modeset) = ("000000000000", "", "Unknown", "Unknown");
		($macaddr) = $db->selectrow_array("SELECT LOWER(value) FROM smart".$homeid.".smartstatus WHERE group_ = 'network' AND name = 'mac'");
		my ($water, $flood) = (0, 0);
#		if ($uaccess < 2) {
#			($water) = $db->selectrow_array("SELECT value_ FROM smart".$homeid.".hvac WHERE option_ = 'water.metering'");
#			($flood) = $db->selectrow_array("SELECT value_ FROM smart".$homeid.".hvac WHERE option_ = 'flood.prevention'");
#			$water += 0;
#			$flood += 0;
#		}
		my ($istun) = $db->selectrow_array("SELECT count(id) FROM tunnel WHERE username = '$macaddr'");
		if ($uaccess >= 2) {
			($homefirst) = $db->selectrow_array("SELECT create_time FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'smart".$homeid."' AND table_name = 'smartstatus'");
		} else {			
			my ($hbypass, $hbset) = $db->selectrow_array("SELECT status, updated FROM smart".$homeid.".bypass WHERE type_ = 0 ORDER BY id DESC LIMIT 1");
			if ($hbypass > 0) {
				$curmode = "Bypass HW";
				$modeset = $hbset;
			} else {
				my ($sbypass, $sbset) = $db->selectrow_array("SELECT status, updated FROM smart".$homeid.".bypass WHERE type_ BETWEEN 1 AND 2 ORDER BY id DESC LIMIT 1");
				if ($sbset ne "") {
					if ($sbypass > 0) {
						$curmode = "Bypass SW";
					} else {
						$curmode = "RetroSAVE";
					}
					$modeset = $sbset;
				}
			}
		}
		if ($tstamp ne "") {
			$homeconn = $tstamp;
		}
		if ($uptime eq "") {
			$uptime = "Unaccessible";
		}
		if ($sysip eq "127.0.0.1") {
			$upstatus = "&nbsp;<br>&nbsp;";
			$homeconn = "Local";
			$uptime = "N/A";
			{
				my $hwfile = $selfpath."/tmp/system.status";
				if (-e $hwfile) {
					open(INF, "<$hwfile");
					while(<INF>) {
						my $inline = $_;
						chomp($inline);
						if ($inline =~ m/^ \d\d:\d\d:\d\d up (.+)\, (.+)\,  load average: (.+)$/) {		# cpu and uptime
							$uptime = $1;
						}
					}
					close(INF);
				}
			}
		}
		$homelist .= "<tr class=\"gr\"><td nowrap=\"nowrap\" width=100>Core ID:</td>
			<td class=\"stdbold\" width=\"120\">$homeid</td>
			<td nowrap=\"nowrap\" width=\"330\" class=\"stdbold\">$homedesc$corehost</td><td nowrap=\"nowrap\" width=\"200\" rowspan=2 class=\"stdbold\">$upstatus</td></tr>
			<tr class=\"gr\"><td nowrap=\"nowrap\" width=\"100\">System uptime:</td>
			<td class=\"stdbold\" width=\"120\">$uptime</td>
			<td nowrap=\"nowrap\" width=\"330\">$owname";
#		if ($uaccess < 2) {
#			$homelist .= "<span style=\"float:right; margin-bottom:-10px;\">Water metering<input id=\"water$houseid\" name=\"water$houseid\" type=\"checkbox\"".(($water == 0)?"":" checked")." onClick=\"Water('$houseid');\"></span>";
#		}
		$homelist .= "</td></tr>
			<tr class=\"gr\"><td nowrap=\"nowrap\" width=\"100\">Last accessed:</td>
			<td class=\"stdbold\" width=\"120\">$homeconn</td>";
		if ($uaccess >= 2) {
			my $hhomeid = $homeid + 0;
			if ($eccc) {
				$homelist .= "<td nowrap=\"nowrap\" rowspan=2 valign=center align=left><input name=\"connect\" value=\"Connect\" onClick=\"window.location.href='./engine.pl?mode=systems&submode=retrosave&action=connect&homeid=$homeid&page=$curpage';\" type=\"button\">&nbsp;&nbsp;&nbsp;";
				if ($istun) {
					$homelist .= "<input type=\"button\" value=\"Open reports\" onClick=\"window.location.href='./engine.pl?mode=reports&submode=cons&page=1&perpage=$perpage&coresel=$homeid';\">&nbsp;&nbsp;&nbsp;";
				} else {
					$homelist .= "<input name=\"connect\" value=\"Create Tunnel Auth Data\" onClick=\"window.location.href='./engine.pl?mode=systems&submode=retrosave&action=tunnel&homeid=$homeid&page=$curpage';\" type=\"button\">&nbsp;&nbsp;&nbsp;";
				}
				if ($tunstat == 3) {		# deleted
					$homelist .= "<input id=\"unreg$homeid\" name=\"unreg$homeid\" value=\"Restore\" onClick=\"UnDeleteSys($hhomeid);\" type=\"button\">&nbsp;&nbsp;&nbsp;";
				} else {
					$homelist .= "<input id=\"unreg$homeid\" name=\"unreg$homeid\" value=\"".(($tunstat == 2)?"Resume":"Pause")."\" onClick=\"PauseSys($hhomeid, $tunstat);\" type=\"button\">&nbsp;&nbsp;&nbsp;";
				}
				if ($tunstat == 2) {		# paused
					$homelist .= "<input id=\"unreg$homeid\" name=\"unreg$homeid\" value=\"Delete\" onClick=\"DeleteSys($hhomeid);\" type=\"button\">&nbsp;&nbsp;&nbsp;";
				}
			} else {
				if ($isclone) {
					my @msgs = ("Copy settings complete", "green>Copy settings pending. Connecting to the target Core", "red>Copy settings in progress. Do not power off or reboot Core!", "blue>Copy settings completed successfully", "red>Copy settings error. Reload the Core and try again");
					$homelist .= "<td nowrap=\"nowrap\" rowspan=2 valign=center align=left><b><font color=".$msgs[$isclone]."</font></b>";
					if (($isclone == 3) || ($isclone == 4)) {
						$homelist .= "<b>.&nbsp;&nbsp;<a href=\"./engine.pl?mode=systems&submode=retrosave&action=endclone&page=$curpage&homeid=$homeid\" class=\"navi\">Click to continue</a></b>";
					}
				} else {
					$homelist .= "<td nowrap=\"nowrap\" rowspan=2 colspan=2 valign=center align=left><input name=\"connect\" value=\"".(($istun)?"Connect":"Create Tunnel Auth Data")."\" onClick=\"window.location.href='./engine.pl?mode=systems&submode=retrosave&action=".(($istun)?"connect":"tunnel")."&homeid=$homeid&page=$curpage';\" type=\"button\">&nbsp;&nbsp;&nbsp;";
					if ($istun) {
						$homelist .= "<input id=\"unreg$homeid\" name=\"unreg$homeid\" value=\"Unregister\" onClick=\"UnregSys($hhomeid);\" type=\"button\">&nbsp;&nbsp;&nbsp;<input type=\"button\" value=\"Open reports\" onClick=\"window.location.href='./engine.pl?mode=reports&submode=cons&page=1&perpage=50&coresel=$homeid';\">";
					} else {
						if (($action eq "clone") && ($homeid == $FORM{homeid})) {
							$homelist .= "Copy from core&nbsp;&nbsp;".$corelist;
						} else {
							$homelist .= "<input id=\"unreg$homeid\" name=\"unreg$homeid\" value=\"Unregister\" onClick=\"UnregSys($hhomeid);\" type=\"button\">&nbsp;&nbsp;&nbsp;<input name=\"clone\" value=\"Copy settings from other Core\" onClick=\"window.location.href='./engine.pl?mode=systems&submode=retrosave&action=clone&homeid=$homeid&page=$curpage';\" type=\"button\">";
						}
					}
				}
			}
			$homelist .= "</td></tr>";
		} else {
			$homelist .= "<td nowrap=\"nowrap\" rowspan=2 valign=center align=left>".(($istun)?"<input name=\"connect\" value=\"Connect\" onClick=\"window.location.href='./engine.pl?mode=systems&submode=retrosave&action=connect&homeid=$homeid&page=$curpage';\" type=\"button\">":"&nbsp;")."</td></tr>";
#			$homelist .= "<td nowrap=\"nowrap\" width=\"120\">Current mode:</td><td class=\"stdbold\" width=\"120\">$curmode</td></tr>";
		}
		if ($uaccess >= 2) {
			$homelist .= "</tr><tr class=\"gr\"><td nowrap=\"nowrap\" width=\"110\">Created on:</td>
			<td class=\"stdbold\" width=\"130\">$homefirst</td></tr>";
		} else {
			$homelist .= "</tr><tr class=\"gr\"><td nowrap=\"nowrap\" width=\"110\">Current mode:</td>
			<td class=\"stdbold\" width=\"130\">$curmode</td></tr>";
		}
		$homelist .= "<tr><td nowrap=\"nowrap\" colspan=4><div class=in10></div></td></tr>\n";
	}
	undef $all;
	if ($homelist eq "") {
		if ($search eq "") {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=460 class=\"stdbold\" colspan=3><br>No Smart controllers registered with Cloud yet<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		} else {
			$homelist .= "<tr><td nowrap=\"nowrap\" width=460 class=\"stdbold\" colspan=3><br>No Smart controllers corresponds search query<br>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
		}
	}

	$headadd .= <<EOF;
		<script language="JavaScript">
		function UnregSys(dbid) {
			var answer = confirm ("Action cleans ASE Cloud storage for controller\\n\\nAre you sure to de-register system with HomeID "+dbid+" ?");
			if (answer) {
				window.location = './engine.pl?mode=systems&submode=retrosave&action=unreg&homeid='+dbid;
			}
		}
		function DeleteSys(dbid) {
			var answer = confirm ("Action removes Virtual Core "+dbid+"\\n\\nAre you sure?");
			if (answer) {
				window.location = './engine.pl?mode=systems&submode=retrosave&action=remove&homeid='+dbid;
			}
		}
		function UnDeleteSys(dbid) {
			var answer = confirm ("Action restores Virtual Core "+dbid+"\\n\\nAre you sure?");
			if (answer) {
				window.location = './engine.pl?mode=systems&submode=retrosave&action=restore&homeid='+dbid;
			}
		}
		function PauseSys(dbid, mode) {
			var newstate = "Idle";
			if (mode == 2) {
				newstate = "Active";
			}
			var answer = confirm ("Action set Virtual Core "+dbid+" to "+newstate+" state\\n\\nAre you sure?");
			if (answer) {
				window.location = './engine.pl?mode=systems&submode=retrosave&action=pause&homeid='+dbid;
			}
		}
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.eventForm.submit();
		}
		function Water(houseID) {
			document.eventForm.action.value = 'water';
			document.eventForm.kodihid.value = houseID;
			document.eventForm.submit();
		}
		function RunReport(repID, houseID) {
			if (repID == 1) {
				window.location = './engine.pl?mode=partners&submode=zeduptime&houseid='+houseID;
			}
			if (repID == 2) {
				window.location = './engine.pl?mode=partners&submode=occupancy&houseid='+houseID;
			}
			if (repID == 3) {
				window.location = './engine.pl?mode=partners&submode=powergraph&houseid='+houseID;
			}
		}
		</script>
EOF

	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\"><< Previous page</a>";
	}
	$pager .= " | ";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		if ($ii == $curpage) {
			$pager .= "<b>$ii</b> ";
		} else {
			$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('$ii');\">$ii</a> ";
		}
	}
	$pager .= "| ";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page >></a>";
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--homelist--/$homelist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--sfilter--/$stfilter/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
	$top1class = "Top1B";
}

# peak demand events manager

if (($uimode eq "systems") && ($uismode eq "peak") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("newevt", "0", "pendevt", "0", "single", "0", "multiple", "0", "searchhid", 0, "profile", 0, "similar", 0, "both", 0, "stopevt", 0, "info", 0);
	my $eventid = 0;
	my ($message, $hidlist, $searchtext, $sresults) = ("", "", "", "");

	if ($action eq "resform") {
		$db->do("DELETE FROM peak_events WHERE status = 0 AND session_id = $sessid");
		$db->do("UPDATE peak_events SET session_id = NULL, updated = NOW() WHERE status > 0 AND session_id = $sessid");
	} elsif ($action eq "resfilter") {
		delete $SDATA{"peak:vsort"};
		delete $SDATA{"peak:dayf"};
		delete $SDATA{"peak:dayt"};
		delete $SDATA{"peak:monthf"};
		delete $SDATA{"peak:montht"};
		delete $SDATA{"peak:yearf"};
		delete $SDATA{"peak:yeart"};
		$SDATA{save} = 1;
	}

	my $yearf = (exists $FORM{year_f})?$FORM{year_f}:((exists $SDATA{"peak:yearf"})?$SDATA{"peak:yearf"}:$lcuryear);
	my $yeart = (exists $FORM{year_t})?$FORM{year_t}:((exists $SDATA{"peak:yeart"})?$SDATA{"peak:yeart"}:$lcuryear);
	my $monthf = (exists $FORM{month_f})?$FORM{month_f}:((exists $SDATA{"peak:monthf"})?$SDATA{"peak:monthf"}:$lcurmon);
	my $montht = (exists $FORM{month_t})?$FORM{month_t}:((exists $SDATA{"peak:montht"})?$SDATA{"peak:montht"}:$lcurmon);
	my $dayf = (exists $FORM{day_f})?$FORM{day_f}:((exists $SDATA{"peak:dayf"})?$SDATA{"peak:dayf"}:$lcurday);
	my $dayt = (exists $FORM{day_t})?$FORM{day_t}:((exists $SDATA{"peak:dayt"})?$SDATA{"peak:dayt"}:$lcurday);
	$dayf = fixdate($dayf, $monthf, $yearf);
	$dayt = fixdate($dayt, $montht, $yeart);
	my $shdatef = sprintf("%04d%02d%02d", $yearf, $monthf, $dayf);
	my $shdatet = sprintf("%04d%02d%02d", $yeart, $montht, $dayt);
	if ($shdatef > $shdatet) {
		($montht, $monthf) = ($monthf, $montht);
		($dayt, $dayf) = ($dayf, $dayt);
		($yeart, $yearf) = ($yearf, $yeart);
	}
	my ($lyearf, $lyeart, $lmonthf, $lmontht, $ldayf, $ldayt) = ("", "", "", "", "", "");
	for my $year (2014 .. 2024) {
		$lyearf .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
		$lyeart .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
	}
	for my $month (1 .. 12) {
		$lmonthf .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
		$lmontht .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$monthtxt[($month - 1)]."</option>";
	}
	for my $day (1 .. 31) {
		$ldayf .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
		$ldayt .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
	}
	my $datef = sprintf("%04d%02d%02d000000", $yearf, $monthf, $dayf);
	my $datet = sprintf("%04d%02d%02d235959", $yeart, $montht, $dayt);
	my $vsort = (exists $FORM{vsort})?$FORM{vsort}:((exists $SDATA{"peak:vsort"})?$SDATA{"peak:vsort"}:0);

	if ($action eq "delevent") {
		my $evid = $FORM{eventid};
#		$db->do("DELETE FROM peak_events WHERE id = $evid");
		$db->do("UPDATE peak_events SET status = 7 WHERE id = $evid");		# set to deleted instead of delete
		$db->do("INSERT INTO events (changed, events.status, events.table, record_id) VALUES (NOW(), 1, 'peak_events', $evid)");
		$eventid = 0;
	}
	if ($action eq "stopevent") {
		my $evid = $FORM{eventid};
		$db->do("UPDATE peak_events SET status = 3, updated = NOW() WHERE status = 2 AND id = $evid");	# change status to stopping
		$db->do("INSERT INTO events (changed, events.status, events.table, record_id) VALUES (NOW(), 1, 'peak_events', $evid)");
		$eventid = 0;
	}
	if ($action eq "view") {
		my $evid = $FORM{eventid};
		$db->do("DELETE FROM peak_events WHERE status = 0 AND session_id = $sessid");
		$db->do("UPDATE peak_events SET session_id = NULL WHERE status > 0 AND session_id = $sessid");
		$db->do("UPDATE peak_events SET session_id = $sessid WHERE status > 0 AND id = $evid");
		$eventid = $evid;
	}

	my ($seventid, $creator, $sstatus, $sstart, $tstart, $send, $timezone, $tzshort, $multiple, $city, $province, $country, $postal, $houseid, $level, $orientation, $condsource, $sleeparea, $profile) = $db->selectrow_array("SELECT id, creator, status, (start + 0), start, (end + 0), timezone, tz_short, multiple, city, province, country, postal, house_id, level, orientation, cond_source, sleep_area, profile FROM peak_events WHERE session_id = $sessid AND status BETWEEN 0 AND 6");	# not deleted
	my @hlevel = ("255", "254", "0", "1", "2", "3", "4", "5");
	my @horientation = ("0", "1", "2", "3", "4");
	my @hcondsource = ("0", "1", "2", "3", "4");
	my @hsleeparea = ("0", "1");
	my @clevel = ("", "", "", "", "", "", "", "");
	my @corientation = ("", "", "", "", "");
	my @ccondsource = ("", "", "", "", "");
	my @csleeparea = ("", "");
	my %houses = ();
	{
		my @h = split(/\,/, $houseid);
		foreach my $hh (@h) {
			$houses{$hh} = 1;
		}
	}


	if ($action eq "selecthid") {
		my $nhid = $FORM{selhid} + 0;
		$houses{$nhid} = 1;
	}
	if ($action eq "deletehid") {
		my $dhid = $FORM{selhid} + 0;
		$houses{$dhid} = 0;
		delete $FORM{"houseid"};
	}

	$houseid = "0";
	foreach my $hh (sort keys %houses) {
		if (($hh > 0) && ($houses{$hh} > 0)) {
			$houseid .= ",$hh";
		}
	}

	if ($sstatus ne "") {		# session data exists
		my $needupd = 0;
		$eventid = $seventid;
		if ((exists $FORM{city}) && ($FORM{city} ne $city)) {
			$city = $FORM{city};
			$needupd ++;
		}
		if ((exists $FORM{province}) && ($FORM{province} ne $province)) {
			$province = $FORM{province};
			$needupd ++;
		}
		if ((exists $FORM{country}) && ($FORM{country} ne $country)) {
			$country = $FORM{country};
			$needupd ++;
		}
		if ((exists $FORM{postal}) && ($FORM{postal} ne $postal)) {
			$postal = $FORM{postal};
			$needupd ++;
		}
#		$debug = $FORM{houseid}.";$houseid";
		if ((exists $FORM{houseid}) && ($FORM{houseid} ne $houseid)) {
#			$houseid = $FORM{houseid};
			$needupd ++;
		}
		if ((exists $FORM{multiple}) && ($FORM{multiple} ne $multiple)) {
			$multiple = $FORM{multiple};
			$needupd ++;
		}
		if ((exists $FORM{timezone}) && ($FORM{timezone} ne $timezone)) {
			my @stimezone = ("-12:00", "-11:00", "-10:00", "-09:00", "-08:00", "-07:00", "-07:00", "-06:00", "-06:00", "-06:00", "-06:00", "-05:00", "-04:00", "-03:00", "-03:00", "-03:00", "-02:00", "-01:00", "+00:00", "+01:00", "+01:00", "+01:00", "+01:00", "+02:00", "+02:00", "+02:00", "+03:00", "+03:00", "+03:30", "+04:00", "+04:30", "+05:00", "+05:30", "+05:45", "+06:00", "+06:00", "+06:30", "+07:00", "+07:00", "+08:00", "+08:00", "+08:00", "+08:00", "+09:00", "+09:00", "+09:30", "+10:00", "+10:00", "+11:00", "+12:00", "+12:00", "+13:00");
			$timezone = $FORM{timezone};
			$tzshort = $stimezone[$timezone];
			$needupd ++;
		}
		if (($multiple == 1) || (($multiple == 0) && ($houseid =~ m/\,/))) {
			my $chkkey = ($multiple == 1)?"country":"houseid";
			my ($nlevel, $norientation, $ncondsource, $nsleeparea) = ("", "", "", "");
			my %korientation = ();
			my $iidx = 0;
			foreach my $ival (@horientation) {
				$korientation{$ival} = $iidx;
				$iidx ++;
				if ((exists $FORM{"orientation".$ival}) && (exists $FORM{$chkkey})) {
					$norientation .= (($norientation eq "")?$ival:(",".$ival));
				}
			}
			if (($norientation ne $orientation) && (exists $FORM{$chkkey})) {
				$orientation = $norientation;
				$needupd ++;
			}
			my @vorientation = split(/\,/, $orientation);
			foreach my $ival (@vorientation) {
				$corientation[$korientation{$ival}] = "checked = \"checked\"";
			}
			my %kcondsource = ();
			$iidx = 0;
			foreach my $ival (@hcondsource) {
				$kcondsource{$ival} = $iidx;
				$iidx ++;
				if ((exists $FORM{"condsource".$ival}) && (exists $FORM{$chkkey})) {
					$ncondsource .= (($ncondsource eq "")?$ival:(",".$ival));
				}
			}
			if (($ncondsource ne $condsource) && (exists $FORM{$chkkey})) {
				$condsource = $ncondsource;
				$needupd ++;
			}
			my @vcondsource = split(/\,/, $condsource);
			foreach my $ival (@vcondsource) {
				$ccondsource[$kcondsource{$ival}] = "checked = \"checked\"";
			}
			my %klevel = ();
			$iidx = 0;
			foreach my $ival (@hlevel) {
				$klevel{$ival} = $iidx;
				$iidx ++;
				if ((exists $FORM{"level".$ival}) && (exists $FORM{$chkkey})) {
					$nlevel .= (($nlevel eq "")?$ival:(",".$ival));
				}
			}
			if (($nlevel ne $level) && (exists $FORM{$chkkey})) {
				$level = $nlevel;
				$needupd ++;
			}
			my @vlevel = split(/\,/, $level);
			foreach my $ival (@vlevel) {
				$clevel[$klevel{$ival}] = "checked = \"checked\"";
			}
			my %ksleeparea = ();
			$iidx = 0;
			foreach my $ival (@hsleeparea) {
				$ksleeparea{$ival} = $iidx;
				$iidx ++;
				if ((exists $FORM{"sleeparea".$ival}) && (exists $FORM{$chkkey})) {
					$nsleeparea .= (($nsleeparea eq "")?$ival:(",".$ival));
				}
			}
			if (($nsleeparea ne $sleeparea) && (exists $FORM{$chkkey})) {
				$sleeparea = $nsleeparea;
				$needupd ++;
			}
			my @vsleeparea = split(/\,/, $sleeparea);
			foreach my $ival (@vsleeparea) {
				$csleeparea[$ksleeparea{$ival}] = "checked = \"checked\"";
			}
		}
		if ((exists $FORM{syear}) && (exists $FORM{smonth}) && (exists $FORM{sday}) && (exists $FORM{shour}) && (exists $FORM{sminute})) {
			$FORM{sday} = fixdate($FORM{sday}, $FORM{smonth}, $FORM{syear});
			my $nstart = sprintf("%04d%02d%02d%02d%02d00", $FORM{syear}, $FORM{smonth}, $FORM{sday}, $FORM{shour}, $FORM{sminute});
			if ($nstart ne $sstart) {
				$sstart = $nstart;
				$needupd ++;
			}
		}
		if ((exists $FORM{eyear}) && (exists $FORM{emonth}) && (exists $FORM{eday}) && (exists $FORM{ehour}) && (exists $FORM{eminute})) {
			$FORM{eday} = fixdate($FORM{eday}, $FORM{emonth}, $FORM{eyear});
			my $nend = sprintf("%04d%02d%02d%02d%02d00", $FORM{eyear}, $FORM{emonth}, $FORM{eday}, $FORM{ehour}, $FORM{eminute});
			if ($nend ne $send) {
				$send = $nend;
				$needupd ++;
			}
		}
		if ($sstart > $send) {
			($sstart, $send) = ($send, $sstart);
		}
		if ($needupd) {
			$db->do("UPDATE peak_events SET updated = NOW(), start = '$sstart', end = '$send', timezone = $timezone, tz_short = '$tzshort', multiple = $multiple, city = '$city', province = '$province', country = '$country', postal = '$postal', house_id = '$houseid', level = '$level', orientation = '$orientation', cond_source = '$condsource', sleep_area = '$sleeparea' WHERE status = 0 AND session_id = $sessid");
		}
	} else {
		$multiple = (exists $FORM{multiple})?$FORM{multiple}:0;
		$timezone = (exists $FORM{timezone})?$FORM{timezone}:18;		# default GMT timezone
		if (exists $FORM{timezone}) {
			my @stimezone = ("-12:00", "-11:00", "-10:00", "-09:00", "-08:00", "-07:00", "-07:00", "-06:00", "-06:00", "-06:00", "-06:00", "-05:00", "-04:00", "-03:00", "-03:00", "-03:00", "-02:00", "-01:00", "+00:00", "+01:00", "+01:00", "+01:00", "+01:00", "+02:00", "+02:00", "+02:00", "+03:00", "+03:00", "+03:30", "+04:00", "+04:30", "+05:00", "+05:30", "+05:45", "+06:00", "+06:00", "+06:30", "+07:00", "+07:00", "+08:00", "+08:00", "+08:00", "+08:00", "+09:00", "+09:00", "+09:30", "+10:00", "+10:00", "+11:00", "+12:00", "+12:00", "+13:00");
			$timezone = $FORM{timezone};
			$tzshort = $stimezone[$timezone];			
		} else {
			$timezone = 18;
			$tzshort = "+00:00";			# UTC default
		}
		if ((exists $FORM{syear}) && (exists $FORM{smonth}) && (exists $FORM{sday}) && (exists $FORM{shour}) && (exists $FORM{sminute})) {
			$FORM{sday} = fixdate($FORM{sday}, $FORM{smonth}, $FORM{syear});
			$sstart = sprintf("%04d%02d%02d%02d%02d00", $FORM{syear}, $FORM{smonth}, $FORM{sday}, $FORM{shour}, $FORM{sminute});
		} else {
			$sstart = sprintf("%04d%02d%02d000000", $lcuryear, $lcurmon, $lcurday);
		}
		if ((exists $FORM{eyear}) && (exists $FORM{emonth}) && (exists $FORM{eday}) && (exists $FORM{ehour}) && (exists $FORM{eminute})) {
			$FORM{eday} = fixdate($FORM{eday}, $FORM{emonth}, $FORM{eyear});
			$send = sprintf("%04d%02d%02d%02d%02d00", $FORM{eyear}, $FORM{emonth}, $FORM{eday}, $FORM{ehour}, $FORM{eminute});
		} else {
			$send = sprintf("%04d%02d%02d235900", $lcuryear, $lcurmon, $lcurday);
		}
		if ($sstart > $send) {
			($sstart, $send) = ($send, $sstart);
		}
		$houseid = (exists $FORM{houseid})?$FORM{houseid}:"0";
		$profile = (exists $FORM{profile})?$FORM{profile}:"";
		$postal = (exists $FORM{postal})?$FORM{postal}:"";
		$country = (exists $FORM{country})?$FORM{country}:"Canada";
		$province = (exists $FORM{province})?$FORM{province}:"CAN-ON";
		$city = (exists $FORM{city})?$FORM{city}:"";
		($level, $orientation, $condsource, $sleeparea) = ("", "", "", "");
		my $iidx = 0;
		foreach my $ival (@hsleeparea) {
			if ((exists $FORM{"sleeparea".$ival}) || !(exists $FORM{multiple})) {
				$sleeparea .= (($sleeparea eq "")?$ival:(",".$ival));
				$csleeparea[$iidx] = "checked=\"checked\"";
			}
			$iidx ++;
		}
		$iidx = 0;
		foreach my $ival (@hcondsource) {
			if ((exists $FORM{"condsource".$ival}) || !(exists $FORM{multiple})) {
				$condsource .= (($condsource eq "")?$ival:(",".$ival));
				$ccondsource[$iidx] = "checked=\"checked\"";
			}
			$iidx ++;
		}
		$iidx = 0;
		foreach my $ival (@horientation) {
			if ((exists $FORM{"orientation".$ival}) || !(exists $FORM{multiple})) {
				$orientation .= (($orientation eq "")?$ival:(",".$ival));
				$corientation[$iidx] = "checked=\"checked\"";
			}
			$iidx ++;
		}
		$iidx = 0;
		foreach my $ival (@hlevel) {
			if ((exists $FORM{"level".$ival}) || !(exists $FORM{multiple})) {
				$level .= (($level eq "")?$ival:(",".$ival));
				$clevel[$iidx] = "checked=\"checked\"";
			}
			$iidx ++;
		}
		$db->do("INSERT INTO peak_events VALUES (NULL, $sessid, $clientid, 0, NOW(), '$sstart', '$send', $timezone, '$tzshort', $multiple, '$city', '$province', '$country', '$postal', '$houseid', '$level', '$orientation', '$condsource', '$sleeparea', '$profile')");
	}

	if ($action eq "save") {
		if (($multiple == 0) && !($houseid =~ m/\,/)) {
			$message = "<br>Core ID must be selected before saving Single Smart Controller Peak event!";
		} elsif ($profile eq "") {
			$message = "<br>Temperature Profile&Schedule must be uploaded before saving Peak event!";
		} elsif ($level eq "") {
			$message = "<br>At least one <b>Floor level</b> option must be checked!";
		} elsif ($orientation eq "") {
			$message = "<br>At least one <b>Orientation</b> option must be checked!";
		} elsif ($condsource eq "") {
			$message = "<br>At least one <b>Conditioning source</b> option must be checked!";
		} elsif ($sleeparea eq "") {
			$message = "<br>At least one <b>Sleeping area</b> option must be checked!";
		} else {
			my ($recid) = $db->selectrow_array("SELECT id FROM peak_events WHERE status = 0 AND session_id = $sessid");
			$db->do("UPDATE peak_events SET status = 1, session_id = NULL, updated = NOW() WHERE status = 0 AND session_id = $sessid");
			if ($recid) {
				$db->do("INSERT INTO events (changed, events.status, events.table, record_id) VALUES (NOW(), 1, 'peak_events', $recid)");
			}
			$message = "<br>New event successfully added!";
			$hiders{similar} = 1;
		}
	}

	my @tmultiple = ("Single", "Group");
	my $lmultiple = "";
	for my $imultiple (0 .. $#tmultiple) {
		$lmultiple .= "<option value=\"".$imultiple."\" ".(($imultiple == $multiple)?" selected=\"selected\"":"").">".$tmultiple[$imultiple]."</option>";
	}
	if (($multiple == 0) && !($houseid =~ m/\,/)) {
		$hiders{searchhid} = 1;
	} elsif (($multiple == 0) && ($houseid =~ m/\,/)) {
		if ($sstatus == 0) {
			$hiders{searchhid} = 1;
		}
		$hiders{single} = 1;
		$hiders{both} = 1;
	} elsif ($multiple == 1) {
		$hiders{multiple} = 1;
		$hiders{both} = 1;
	}

	my $ltimezone = "";
	my @ttimezone = ("(GMT-12:00) International Date Line West", "(GMT-11:00) Mixxxay Island, Samoa", "(GMT-10:00) Hawaii", "(GMT-09:00) Alaska", "(GMT-08:00) Pacific Time (USA &amp; Canada)", "(GMT-07:00) Arizona", "(GMT-07:00) Mountain Time (USA &amp; Canada)", "(GMT-06:00) Central America", "(GMT-06:00) Central Time (USA &amp; Canada)", "(GMT-06:00) Guadalajara, Mexico City, Monterrey", "(GMT-06:00) Saskatchewan", "(GMT-05:00) Eastern Time (USA &amp; Canada)", "(GMT-04:00) Atlantic Time (Canada)", "(GMT-03:30) Newfoundland", "(GMT-03:00) Brasilia", "(GMT-03:00) Buenos Aires, Georgetown", "(GMT-02:00) Mid-Atlantic", "(GMT-01:00) Azores", "(GMT) Dublin, Edinburgh, Lisbon, London", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Vienna", "(GMT+01:00) Belgrade, Bratislava, Budapest, Prague", "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris", "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb", "(GMT+02:00) Athens, Istanbul, Minsk", "(GMT+02:00) Kyiv, Riga, Sofia, Tallinn, Vilnius", "(GMT+02:00) Helsinki, Jerusalem, Lutsk", "(GMT+03:00) Baghdad", "(GMT+03:00) Moscow, St. Petersburg, Volgograd", "(GMT+03:30) Tehran", "(GMT+04:00) Abu Dhabi, Muscat", "(GMT+04:30) Kabul", "(GMT+05:00) Ekaterinburg", "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi", "(GMT+05:45) Kathmandu", "(GMT+06:00) Almaty, Novosibirsk", "(GMT+06:00) Astana, Dhaka", "(GMT+06:30) Rangoon", "(GMT+07:00) Bangkok, Hanoi, Jakarta", "(GMT+07:00) Krasnoyarsk", "(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi", "(GMT+08:00) Irkutsk, Ulaan Bataar", "(GMT+08:00) Kuala Lumpur, Singapore", "(GMT+08:00) Taipei", "(GMT+09:00) Osaka, Sapporo, Tokyo", "(GMT+09:00) Seoul", "(GMT+09:30) Adelaide", "(GMT+10:00) Brisbane", "(GMT+10:00) Vladivostok", "(GMT+11:00) Magadan, Solomon Is., New Caledonia", "(GMT+12:00) Auckland, Wellington", "(GMT+12:00) Fiji, Kamchatka, Marshall Is.", "(GMT+13:00) Nuku'alofa");
	for my $itimezone (0 .. $#ttimezone) {
		$ltimezone .= "<option value=\"".$itimezone."\" ".(($itimezone == $timezone)?" selected=\"selected\"":"").">".$ttimezone[$itimezone]."</option>";
	}

	my ($lprovince, $lcountry) = ("", "");
	my %tprovince = ("NONE", "Not Canada or USA", "CAN-AL", "Alberta", "CAN-BC", "British Columbia", "CAN-MT", "Manitoba", "CAN-NB", "New Brunswick", "CAN-NS", "Nova Scotia", "CAN-ON", "Ontario", "CAN-QB", "Quebec", "CAN-SS", "Saskatchewan", "CAN-PE", "Prince Edward Island", "CAN-NL", "Newfoundland and Labrador", "USA-AL", "Alabama", "USA-AK", "Alaska", "USA-AZ", "Arizona", "USA-AR", "Arkansas", "USA-CA", "California", "USA-CO", "Colorado", "USA-CT", "Connecticut", "USA-DE", "Delaware", "USA-FL", "Florida", "USA-GA", "Georgia", "USA-HI", "Hawaii", "USA-ID", "Idaho", "USA-IL", "Illinois", "USA-IN", "Indiana", "USA-IA", "Iowa", "USA-KS", "Kansas", "USA-KY", "Kentucky", "USA-LA", "Louisiana", "USA-ME", "Maine", "USA-MD", "Maryland", "USA-MA", "Massachusetts", "USA-MI", "Michigan", "USA-MN", "Minnesota", "USA-MS", "Mississippi", "USA-MO", "Missouri", "USA-MT", "Montana", "USA-NE", "Nebraska", "USA-NV", "Nevada", "USA-NH", "New Hampshire", "USA-NJ", "New Jersey", "USA-NM", "New Mexico", "USA-NY", "New York", "USA-NC", "North Carolina", "USA-ND", "North Dakota", "USA-OH", "Ohio", "USA-OK", "Oklahoma", "USA-OR", "Oregon", "USA-PA", "Pennsylvania", "USA-RI", "Rhode Island", "USA-SC", "South Carolina", "USA-SD", "South Dakota", "USA-TN", "Tennessee", "USA-TX", "Texas", "USA-UT", "Utah", "USA-VT", "Vermont", "USA-VA", "Virginia", "USA-WA", "Washington", "USA-WV", "West Virginia", "USA-WI", "Wisconsin", "USA-WY", "Wyoming");
	my %tcountry = ("Afghanistan", "Afghanistan", "Aland Islands", "Aland Islands", "Albania", "Albania", "Algeria", "Algeria", "American Samoa", "American Samoa", "Andorra", "Andorra", "Angola", "Angola", "Anguilla", "Anguilla", "Antarctica", "Antarctica", "Antigua and Barbuda", "Antigua and Barbuda", "Argentina", "Argentina", "Armenia", "Armenia", "Aruba", "Aruba", "Australia", "Australia", "Austria", "Austria", "Azerbaijan", "Azerbaijan", "Bahamas", "Bahamas", "Bahrain", "Bahrain", "Bangladesh", "Bangladesh", "Barbados", "Barbados", "Belarus", "Belarus", "Belgium", "Belgium", "Belize", "Belize", "Benin", "Benin", "Bermuda", "Bermuda", "Bhutan", "Bhutan", "Bolivia", "Bolivia", "Bosnia and Herzegovina", "Bosnia and Herzegovina", "Botswana", "Botswana", "Bouvet Island", "Bouvet Island", "Brazil", "Brazil", "British Indian Ocean Territory", "British Indian Ocean Territory", "Brunei Darussalam", "Brunei Darussalam", "Bulgaria", "Bulgaria", "Burkina Faso", "Burkina Faso", "Burundi", "Burundi", "Cambodia", "Cambodia", "Cameroon", "Cameroon", "Canada", "Canada", "Cape Verde", "Cape Verde", "Cayman Islands", "Cayman Islands", "Central African Republic", "Central African Republic", "Chad", "Chad", "Chile", "Chile", "China", "China", "Christmas Island", "Christmas Island", "Cocos (Keeling) Islands", "Cocos (Keeling) Islands", "Colombia", "Colombia", "Comoros", "Comoros", "Congo", "Congo", "Cook Islands", "Cook Islands", "Costa Rica", "Costa Rica", "Cote D'ivoire", "Cote D'ivoire", "Croatia", "Croatia", "Cuba", "Cuba", "Cyprus", "Cyprus", "Czech Republic", "Czech Republic", "Denmark", "Denmark", "Djibouti", "Djibouti", "Dominica", "Dominica", "Dominican Republic", "Dominican Republic", "Ecuador", "Ecuador", "Egypt", "Egypt", "El Salvador", "El Salvador", "Equatorial Guinea", "Equatorial Guinea", "Eritrea", "Eritrea", "Estonia", "Estonia", "Ethiopia", "Ethiopia", "Falkland Islands", "Falkland Islands (Malvinas)", "Faroe Islands", "Faroe Islands", "Fiji", "Fiji", "Finland", "Finland", "France", "France", "French Guiana", "French Guiana", "French Polynesia", "French Polynesia", "French Southern Territories", "French Southern Territories", "Gabon", "Gabon", "Gambia", "Gambia", "Georgia", "Georgia", "Germany", "Germany", "Ghana", "Ghana", "Gibraltar", "Gibraltar", "Greece", "Greece", "Greenland", "Greenland", "Grenada", "Grenada", "Guadeloupe", "Guadeloupe", "Guam", "Guam", "Guatemala", "Guatemala", "Guernsey", "Guernsey", "Guinea", "Guinea", "Guinea-bissau", "Guinea-bissau", "Guyana", "Guyana", "Haiti", "Haiti", "Heard Island", "Heard Island and Mcdonald Islands", "Holy See", "Holy See (Vatican City State)", "Honduras", "Honduras", "Hong Kong", "Hong Kong", "Hungary", "Hungary", "Iceland", "Iceland", "India", "India", "Indonesia", "Indonesia", "Iran", "Iran, Islamic Republic of", "Iraq", "Iraq", "Ireland", "Ireland", "Isle of Man", "Isle of Man", "Israel", "Israel", "Italy", "Italy", "Jamaica", "Jamaica", "Japan", "Japan", "Jersey", "Jersey", "Jordan", "Jordan", "Kazakhstan", "Kazakhstan", "Kenya", "Kenya", "Kiribati", "Kiribati", "Korea Democratic People Republic", "Korea, Democratic People's Republic of", "Korea Republic", "Korea, Republic of", "Kuwait", "Kuwait", "Kyrgyzstan", "Kyrgyzstan", "Laos", "Lao People's Democratic Republic", "Latvia", "Latvia", "Lebanon", "Lebanon", "Lesotho", "Lesotho", "Liberia", "Liberia", "Libyan Arab Jamahiriya", "Libyan Arab Jamahiriya", "Liechtenstein", "Liechtenstein", "Lithuania", "Lithuania", "Luxembourg", "Luxembourg", "Macao", "Macao", "Macedonia", "Macedonia, The Former Yugoslav Republic of", "Madagascar", "Madagascar", "Malawi", "Malawi", "Malaysia", "Malaysia", "Maldives", "Maldives", "Mali", "Mali", "Malta", "Malta", "Marshall Islands", "Marshall Islands", "Martinique", "Martinique", "Mauritania", "Mauritania", "Mauritius", "Mauritius", "Mayotte", "Mayotte", "Mexico", "Mexico", "Micronesia", "Micronesia, Federated States of", "Moldova", "Moldova, Republic of", "Monaco", "Monaco", "Mongolia", "Mongolia", "Montenegro", "Montenegro", "Montserrat", "Montserrat", "Morocco", "Morocco", "Mozambique", "Mozambique", "Myanmar", "Myanmar", "Namibia", "Namibia", "Nauru", "Nauru", "Nepal", "Nepal", "Netherlands", "Netherlands", "Netherlands Antilles", "Netherlands Antilles", "New Caledonia", "New Caledonia", "New Zealand", "New Zealand", "Nicaragua", "Nicaragua", "Niger", "Niger", "Nigeria", "Nigeria", "Niue", "Niue", "Norfolk Island", "Norfolk Island", "Northern Mariana Islands", "Northern Mariana Islands", "Norway", "Norway", "Oman", "Oman", "Pakistan", "Pakistan", "Palau", "Palau", "Palestinian Territory", "Palestinian Territory, Occupied", "Panama", "Panama", "Papua New Guinea", "Papua New Guinea", "Paraguay", "Paraguay", "Peru", "Peru", "Philippines", "Philippines", "Pitcairn", "Pitcairn", "Poland", "Poland", "Portugal", "Portugal", "Puerto Rico", "Puerto Rico", "Qatar", "Qatar", "Reunion", "Reunion", "Romania", "Romania", "Russian Federation", "Russian Federation", "Rwanda", "Rwanda", "Saint Helena", "Saint Helena", "Saint Kitts and Nevis", "Saint Kitts and Nevis", "Saint Lucia", "Saint Lucia", "Saint Pierre and Miquelon", "Saint Pierre and Miquelon", "Saint Vincent and The Grenadines", "Saint Vincent and The Grenadines", "Samoa", "Samoa", "San Marino", "San Marino", "Sao Tome and Principe", "Sao Tome and Principe", "Saudi Arabia", "Saudi Arabia", "Senegal", "Senegal", "Serbia", "Serbia", "Seychelles", "Seychelles", "Sierra Leone", "Sierra Leone", "Singapore", "Singapore", "Slovakia", "Slovakia", "Slovenia", "Slovenia", "Solomon Islands", "Solomon Islands", "Somalia", "Somalia", "South Africa", "South Africa", "South Georgia", "South Georgia and The South Sandwich Islands", "Spain", "Spain", "Sri Lanka", "Sri Lanka", "Sudan", "Sudan", "Suriname", "Suriname", "Svalbard and Jan Mayen", "Svalbard and Jan Mayen", "Swaziland", "Swaziland", "Sweden", "Sweden", "Switzerland", "Switzerland", "Syrian Arab Republic", "Syrian Arab Republic", "Taiwan", "Taiwan, Province of China", "Tajikistan", "Tajikistan", "Tanzania", "Tanzania, United Republic of", "Thailand", "Thailand", "Timor-leste", "Timor-leste", "Togo", "Togo", "Tokelau", "Tokelau", "Tonga", "Tonga", "Trinidad and Tobago", "Trinidad and Tobago", "Tunisia", "Tunisia", "Turkey", "Turkey", "Turkmenistan", "Turkmenistan", "Turks and Caicos Islands", "Turks and Caicos Islands", "Tuvalu", "Tuvalu", "Uganda", "Uganda", "Ukraine", "Ukraine", "United Arab Emirates", "United Arab Emirates", "United Kingdom", "United Kingdom", "United States", "United States", "United States Minor Outlying Islands", "United States Minor Outlying Islands", "Uruguay", "Uruguay", "Uzbekistan", "Uzbekistan", "Vanuatu", "Vanuatu", "Venezuela", "Venezuela", "Viet Nam", "Viet Nam", "Virgin Islands, British", "Virgin Islands, British", "Virgin Islands, U.S.", "Virgin Islands, U.S.", "Wallis and Futuna", "Wallis and Futuna", "Western Sahara", "Western Sahara", "Yemen", "Yemen", "Zambia", "Zambia", "Zimbabwe", "Zimbabwe");
	foreach my $iprovince (sort keys %tprovince) {
		$lprovince .= "<option value=\"$iprovince\"".(($province eq $iprovince)?" selected=\"selected\"":"").">".$tprovince{$iprovince}."</option>";
	}
	foreach my $icountry (sort keys %tcountry) {
		$lcountry .= "<option value=\"$icountry\"".(($country eq $icountry)?" selected=\"selected\"":"").">".$tcountry{$icountry}."</option>";
	}

	my ($lsyear, $leyear, $lsmonth, $lemonth, $lsday, $leday, $lshour, $lehour, $lsminute, $leminute) = ("", "", "", "", "", "", "", "", "", "");
	{
		my $yearf = substr($sstart, 0, 4);
		my $yeart = substr($send, 0, 4);
		for my $year (2014 .. 2024) {
			$lsyear .= "<option value=\"$year\"".(($year == $yearf)?" selected=\"selected\"":"").">$year</option>";
			$leyear .= "<option value=\"$year\"".(($year == $yeart)?" selected=\"selected\"":"").">$year</option>";
		}
		my $monthf = substr($sstart, 4, 2);
		my $montht = substr($send, 4, 2);
		for my $month (1 .. 12) {
			$lsmonth .= "<option value=\"$month\"".(($month == $monthf)?" selected=\"selected\"":"").">".$smonths[$month]."</option>";
			$lemonth .= "<option value=\"$month\"".(($month == $montht)?" selected=\"selected\"":"").">".$smonths[$month]."</option>";
		}
		my $dayf = substr($sstart, 6, 2);
		my $dayt = substr($send, 6, 2);
		for my $day (1 .. 31) {
			$lsday .= "<option value=\"$day\"".(($day == $dayf)?" selected=\"selected\"":"").">$day</option>";
			$leday .= "<option value=\"$day\"".(($day == $dayt)?" selected=\"selected\"":"").">$day</option>";
		}
		my $hourf = substr($sstart, 8, 2);
		my $hourt = substr($send, 8, 2);
		for my $hour (0 .. 23) {
			$lshour .= "<option value=\"$hour\"".(($hour == $hourf)?" selected=\"selected\"":"").">".sprintf("%02d",$hour)."</option>";
			$lehour .= "<option value=\"$hour\"".(($hour == $hourt)?" selected=\"selected\"":"").">".sprintf("%02d",$hour)."</option>";
		}
		my $minutef = substr($sstart, 10, 2);
		my $minutet = substr($send, 10, 2);
		for my $minute (0 .. 59) {
			$lsminute .= "<option value=\"$minute\"".(($minute == $minutef)?" selected=\"selected\"":"").">".sprintf("%02d",$minute)."</option>";
			$leminute .= "<option value=\"$minute\"".(($minute == $minutet)?" selected=\"selected\"":"").">".sprintf("%02d",$minute)."</option>";
		}
	}

	my ($evlist, $tesort, $tssort) = ("", "", "");
	{
		my @stimezone = ("GMT-12", "GMT-11", "GMT-10", "GMT-9", "GMT-8", "GMT-7", "GMT-7", "GMT-6", "GMT-6", "GMT-6", "GMT-6", "GMT-5", "GMT-4", "GMT-3", "GMT-3", "GMT-3", "GMT-2", "GMT-1", "GMT+0", "GMT+1", "GMT+1", "GMT+1", "GMT+1", "GMT+2", "GMT+2", "GMT+2", "GMT+3", "GMT+3", "GMT+3:30", "GMT+4", "GMT+4:30", "GMT+5", "GMT+5:30", "GMT+5:45", "GMT+6", "GMT+6", "GMT+6:30", "GMT+7", "GMT+7", "GMT+8", "GMT+8", "GMT+8", "GMT+8", "GMT+9", "GMT+9", "GMT+9:30", "GMT+10", "GMT+10", "GMT+11", "GMT+12", "GMT+12", "GMT+13");
		$tstart .= " ".$stimezone[($timezone + 0)];
		my @tmultiple = ("Single", "Group");
		my @tstatus = ("In edit", "Pending", "Running", "Stopping", "Stopped", "Finishing", "Finished");
		my $orderby = "start, end";
		if ($vsort == 0) {
			$orderby = "start ASC, end ASC";
			$tesort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=2\" class=\"navi\">&rarr;</a>";
			$tssort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=1\" class=\"navi\">&darr;&darr;</a>";
		} elsif ($vsort == 1) {
			$orderby = "start DESC, end DESC";
			$tesort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=3\" class=\"navi\">&larr;</a>";
			$tssort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=0\" class=\"navi\">&uarr;&uarr;</a>";
		} elsif ($vsort == 2) {
			$orderby = "end ASC, start ASC";
			$tssort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=0\" class=\"navi\">&rarr;</a>";
			$tesort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=3\" class=\"navi\">&darr;&darr;</a>";
		} elsif ($vsort == 3) {
			$orderby = "end DESC, start DESC";
			$tssort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=1\" class=\"navi\">&larr;</a>";
			$tesort = "<a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=vsort&vsort=2\" class=\"navi\">&uarr;&uarr;</a>";
		}
		my $all = $db->selectall_arrayref("SELECT id, DATE_FORMAT(start, '%Y-%m-%d %H:%i:%S'), DATE_FORMAT(end, '%Y-%m-%d %H:%i:%S'), timezone, multiple, status, creator FROM peak_events WHERE start BETWEEN $datef AND $datet AND status BETWEEN 1 AND 6 ORDER BY $orderby");
		my $stylecnt = 0;
		foreach my $row (@$all) {
			if (($uaccess >= 2) || (@$row[6] == $clientid)) {		# security check
				$evlist .= "<tr".(($stylecnt & 1)?"":" style=\"background-color: #f1f3f5;\"")."><td nowrap=\"nowrap\" width=\"110\">".@$row[1]."</td>
						<td nowrap=\"nowrap\" width=\"110\">".@$row[2]."</td>
						<td nowrap=\"nowrap\" width=\"60\">".$stimezone[@$row[3]]."</td>
						<td nowrap=\"nowrap\" width=\"60\">".$tmultiple[@$row[4]]."</td>
						<td nowrap=\"nowrap\" width=\"60\">".$tstatus[@$row[5]]."</td>
						<td nowrap=\"nowrap\" width=\"80\"><a href=\"./engine.pl?mode=--mode--&submode=--submode--&action=view&eventid=".@$row[0]."\" class=\"navi\">Event details</a></td>
					</tr>\n";
				$stylecnt ++;
			}
		}
		undef $all;
		$SDATA{"peak:dayf"} = $dayf;
		$SDATA{"peak:dayt"} = $dayt;
		$SDATA{"peak:monthf"} = $monthf;
		$SDATA{"peak:montht"} = $montht;
		$SDATA{"peak:yearf"} = $yearf;
		$SDATA{"peak:yeart"} = $yeart;
		$SDATA{"peak:vsort"} = $vsort;
		$SDATA{save} = 1;
		if ($evlist eq "") {
			$evlist = "<tr><td colspan=5><br><b>No Peak Demand events to show!</td></tr>\n"
		}
	}

	my $cmultiple = "";
	if ($sstatus == 0) {		# inedit
		unless ($hiders{similar}) {
			$hiders{newevt} = 1;
#			$deletehid = "&nbsp;&nbsp;&nbsp;<input name=\"deletehid\" value=\"Remove selection\" type=\"button\" onClick=\"document.eventform.action.value='deletehid';document.eventform.submit();\">";
			foreach my $hid (sort keys %houses) {
				if (($hid > 0) && ($houses{$hid} > 0)) {
					$hidlist .= "<input name=\"hid$hid\" size=\"2\" maxlength=\"20\" value=\"$hid\" type=\"text\" readonly=\"readonly\">&nbsp;&nbsp;&nbsp;<input name=\"deletehid\" value=\"Remove selection\" type=\"button\" onClick=\"document.eventform.selhid.value='$hid';document.eventform.action.value='deletehid';document.eventform.submit();\"><br>";
				}
			}
			$cmultiple = " onChange=\"document.eventform.submit();\"";
		}
	} elsif ($sstatus == 1) {	# pending
		$hiders{pendevt} = 1;
		$headadd .= <<EOF;
			<script language="JavaScript">
			function DelEvent(evid) {
				var answer = confirm ("Are you sure to DELETE event starting $tstart ?");
				if (answer) {
					window.location = './engine.pl?mode=$uimode&submode=$uismode&action=delevent&eventid=$eventid';
				}
			}
			</script>
EOF
	} elsif ($sstatus == 2) {	# running
		$hiders{stopevt} = 1;
		$headadd .= <<EOF;
			<script language="JavaScript">
			function StopEvent(evid) {
				var answer = confirm ("Are you sure to STOP event starting $tstart ?");
				if (answer) {
					window.location = './engine.pl?mode=$uimode&submode=$uismode&action=stopevent&eventid=$eventid';
				}
			}
			</script>
EOF
	}
	if (($sstatus > 0) && ($multiple == 0)) {
		my $hcnt = 0;
		foreach my $hid (sort keys %houses) {
			if ($hid > 0) {
				if ($hcnt) {
					$hidlist .= ",$hid";
				} else {
					$hidlist .= "$hid";
				}
				$hcnt ++;
				if ($hcnt == 15) {
					$hcnt = 0;
					$hidlist .= "<br>";
				}
			}
		}
#		$hidlist = "<input name=\"hidlist\" size=\"20\" maxlength=\"100\" value=\"$hidlist\" type=\"text\" readonly=\"readonly\">";
		$hidlist = "<b>$hidlist</b>";
	}

	if ($action eq "search") {
		my $search = $FORM{searchtext};
		if ($search eq "") {
			$message = "Search request cannot be empty!";
		} else {
			$searchtext = $search;
			my $hidfilter = "systems.house_id > 0";
			if ($uaccess < 2) {
				$hidfilter = "systems.house_id IN ($housemask)";
			}
			my $sfilter = "(systems.house_id = ".($search + 0)." OR systems.description LIKE '%".$search."%' OR UCASE(systemadd.name1) LIKE '%".uc($search)."%' OR UCASE(systemadd.name2) LIKE '%".uc($search)."%') AND $hidfilter";
		        my $maxrec = 20;
		        my ($allrec) = $db->selectrow_array("SELECT COUNT(systems.id) FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.id WHERE $sfilter ORDER BY systems.id");
		        if ($allrec > $maxrec) {
		        	$message = "<br>More than $maxrec core records found! Please be more specific in search request";
		        }
		        if ($allrec == 0) {
		        	$message = "<br>No core records found on given search request! Please check";
		        } else {
		        	$sresults .= "<tr><td colspan=2 width=500><table border=0 cellspacing=0 cellpadding=0>\n";
				my $all = $db->selectall_arrayref("SELECT systems.house_id, systems.description, systemadd.name1, systemadd.name2 FROM systems LEFT JOIN systemadd ON systemadd.house_id = systems.house_id WHERE $sfilter ORDER BY systems.id LIMIT $maxrec");
				foreach my $row (@$all) {
					my $houseid = @$row[0];
					my $homeid = sprintf("%05d", $houseid);
					my $homedesc = @$row[1];
					my $owname = ((@$row[2] ne "") || (@$row[3] ne ""))?("Customer: <b>".@$row[2]." ".@$row[3]):"No customer name specified";
					$sresults .= "<tr><td nowrap=\"nowrap\" colspan=2><div class=in5></div></td></tr>\n";
					$sresults .= "<tr><td nowrap=\"nowrap\" width=250>Core ID <b>$homeid: $homedesc</b><br>$owname</td>\n";
					$sresults .= "<td><input name=\"sel$houseid\" value=\"Select core\" onClick=\"document.eventform.selhid.value='$houseid';document.eventform.action.value='selecthid';document.eventform.submit();\" type=\"button\"></td>";
					$sresults .= "</tr>\n";
				}
				undef $all;
				$sresults .= "</table></td></tr>\n";
		        }
		}
	}

	if ($action eq "upload") {
#		my $infile = "/tmp/".$FORM{file};		# uploaded to TMP folder
		my $infile = $selfpath."/updates/".$FORM{file};		# uploaded to TMP folder
		if (-e $infile) {
			$profile = "";
			open(INF, "<$infile");
			while(<INF>) {
				my $inline = $_;
				chomp($inline);
				if ($inline =~ m/^(\d+)\:(\d+)\,([\+\-\.0-9]+)[\s\t]*$/) {
					my $time = sprintf("%02d:%02d", $1, $2);
					my $setp = $3;
					if ($profile eq "") {
						$profile = "$time,$setp";
					} else {
						$profile .= ";$time,$setp";
					}
				}
			}
			close(INF);
			$message = "Profile ".$FORM{file}." successfully added";
			$db->do("UPDATE peak_events SET profile = '$profile', updated = NOW() WHERE status = 0 AND session_id = $sessid");
		}		
	}
	
	my ($protime, $proset) = ("", "");
	if ($profile ne "") {
		$hiders{profile} = 1;
		my @items = split(/\;/, $profile);
		foreach my $iit (@items) {
			my @iitems = split(/\,/, $iit);
			$protime .= ($protime eq "")?$iitems[0]:("<br>".$iitems[0]);
			$proset .= (($proset eq "")?$iitems[1]:("<br>".$iitems[1])).(($iitems[1] == 0)?"":"&deg;C");
		}
	}

	my $evinfo = "";
	if ($sstatus > 0) {
		$hiders{info} = 1;
		my @tstatus = ("In edit", "Pending", "Running", "Stopping", "Stopped", "Finishing", "Finished");
		my ($cruser) = $db->selectrow_array("SELECT login FROM users WHERE id = $creator");
		$evinfo = "Event ID <b>$eventid</b>, created by <b>$cruser</b> currently in <b>$tstatus[$sstatus]</b> status";
	}
	
	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--info--/$evinfo/g;
		$inline =~ s/--protime--/$protime/g;
		$inline =~ s/--proset--/$proset/g;
		$inline =~ s/--cmultiple--/$cmultiple/g;
		$inline =~ s/--hidlist--/$hidlist/g;
		$inline =~ s/--searchtext--/$searchtext/g;
		$inline =~ s/--sresults--/$sresults/g;
		$inline =~ s/--city--/$city/g;
		$inline =~ s/--province--/$lprovince/g;
		$inline =~ s/--country--/$lcountry/g;
		$inline =~ s/--postal--/$postal/g;
		$inline =~ s/--houseid--/$houseid/g;
		$inline =~ s/--evlist--/$evlist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--multiple--/$lmultiple/g;
		$inline =~ s/--year_f--/$lyearf/g;
		$inline =~ s/--year_t--/$lyeart/g;
		$inline =~ s/--month_f--/$lmonthf/g;
		$inline =~ s/--month_t--/$lmontht/g;
		$inline =~ s/--day_f--/$ldayf/g;
		$inline =~ s/--day_t--/$ldayt/g;
		$inline =~ s/--syear--/$lsyear/g;
		$inline =~ s/--eyear--/$leyear/g;
		$inline =~ s/--ssort--/$tssort/g;
		$inline =~ s/--esort--/$tesort/g;
		$inline =~ s/--smonth--/$lsmonth/g;
		$inline =~ s/--emonth--/$lemonth/g;
		$inline =~ s/--sday--/$lsday/g;
		$inline =~ s/--eday--/$leday/g;
		$inline =~ s/--shour--/$lshour/g;
		$inline =~ s/--ehour--/$lehour/g;
		$inline =~ s/--sminute--/$lsminute/g;
		$inline =~ s/--eminute--/$leminute/g;
		$inline =~ s/--timezone--/$ltimezone/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$inline =~ s/--level255--/$clevel[0]/g;
		$inline =~ s/--level254--/$clevel[1]/g;
		$inline =~ s/--level0--/$clevel[2]/g;
		$inline =~ s/--level1--/$clevel[3]/g;
		$inline =~ s/--level2--/$clevel[4]/g;
		$inline =~ s/--level3--/$clevel[5]/g;
		$inline =~ s/--level4--/$clevel[6]/g;
		$inline =~ s/--level5--/$clevel[7]/g;
		$inline =~ s/--condsource0--/$ccondsource[0]/g;
		$inline =~ s/--condsource1--/$ccondsource[1]/g;
		$inline =~ s/--condsource2--/$ccondsource[2]/g;
		$inline =~ s/--condsource3--/$ccondsource[3]/g;
		$inline =~ s/--condsource4--/$ccondsource[4]/g;
		$inline =~ s/--sleeparea0--/$csleeparea[0]/g;
		$inline =~ s/--sleeparea1--/$csleeparea[1]/g;
		$inline =~ s/--orientation0--/$corientation[0]/g;
		$inline =~ s/--orientation1--/$corientation[1]/g;
		$inline =~ s/--orientation2--/$corientation[2]/g;
		$inline =~ s/--orientation3--/$corientation[3]/g;
		$inline =~ s/--orientation4--/$corientation[4]/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# access password

if (($uimode eq "userinfo") && ($uismode eq "password") && ($uaccess >= $alevel{$uimode.$uismode})) {
        if ($action eq "save") {
		my $oldpass = "TH1SiSMAS4eRPaSS";
		{
       			my $all = $db->selectall_arrayref("SELECT password FROM users WHERE login='$ulogin' LIMIT 1");
			foreach my $row (@$all) {
				($oldpass) = @$row;
			}
			undef $all;
		}
        	my $msgtxt = "Nothing was changed";
        	if ($FORM{username} ne $ulogin) {
        		if ($FORM{username} =~ m/^[a-zA-Z0-9_]*$/) {
        			if (length($FORM{username}) < 6) {
        				$msgtxt = "<font color=red>Username too short!";
        			} else {
					if ($FORM{password_old} ne $oldpass) {
						$msgtxt = "<font color=red>Current password does not match!";
					} else {
						$db->do("UPDATE users SET login='".$FORM{username}."' WHERE login='$ulogin' AND password='".$FORM{password_old}."'");
						$msgtxt = "Username changed successfully";
						$ulogin = $FORM{username};
					}
        			}
        		} else {
        			$msgtxt = "<font color=red>Username contains wrong characters!";
        		}
        	}
        	if (length($FORM{password_new}) > 0) {
        		if ($FORM{password_old} ne $oldpass) {
				$msgtxt = "<font color=red>Current password does not match!";
			} else {
				$db->do("UPDATE users SET password='".$FORM{password_new}."' WHERE login='$ulogin' AND password='".$FORM{password_old}."'");
				$msgtxt = "Password changed successfully";
			}
        	}
        	$message = "<tr><td nowrap=\"nowrap\" width=\"138\">&nbsp;</td><td nowrap=\"nowrap\"><br>$msgtxt</td></tr>\n";
        }
	
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--username--/$ulogin/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# access password

if (($uimode eq "userconfig") && ($uismode eq "upassword") && ($uaccess >= $alevel{$uimode.$uismode})) {
        if ($action eq "save") {
		my $oldpass = "TH1SiSMAS4eRPaSS)(D*FJKFJKLDF";
		{
       			my $all = $db->selectall_arrayref("SELECT password FROM users WHERE login='$ulogin' LIMIT 1");
			foreach my $row (@$all) {
				($oldpass) = @$row;
			}
			undef $all;
		}
        	my $msgtxt = "Nothing was changed";
        	if (length($FORM{password_new}) > 0) {
        		if ($FORM{password_old} ne $oldpass) {
				$msgtxt = "<font color=red>Current password does not match!";
			} else {
				$db->do("UPDATE users SET password='".$FORM{password_new}."' WHERE login='$ulogin' AND password='".$FORM{password_old}."'");
				$msgtxt = "Password changed successfully";
			}
        	}
        	$message = "<tr><td nowrap=\"nowrap\" width=\"138\">&nbsp;</td><td nowrap=\"nowrap\"><br>$msgtxt</td></tr>\n";
        }
	
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--username--/$ulogin/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# partner email notifications

if (($uimode eq "userinfo") && ($uismode eq "notifications") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $accid = ($uaccess >= 2)?($FORM{account_id} + 0):$clientid;
	my $emlid = $FORM{id} + 0;
	my ($acemails, $acclist, $oldmail, $teaccount, $oldtun, $oldbyp, $oldups, $oldcom, $tddelay, $oldsps) = ("", "", "", "", "", "", "", "", "", "");
	my ($notenab, $oldflags) = (0, 0);
	my %hiders = ("accsel", "0");

	if ($uaccess >= 2) {
		$hiders{"accsel"} ++;
		my $all = $db->selectall_arrayref("SELECT id, login, name1 FROM users WHERE id > 1 ORDER BY id DESC");
		foreach my $row (@$all) {
			my $uid = @$row[0];
			if ($accid == 0) {
				$accid = $uid;		# set to first account in list
			}
			$acclist .= "<option value=\"$uid\" ".(($accid == $uid)?"selected=\"selected\"":"").">".@$row[1].": ".substr(@$row[2], 0, 30)."</option>";
		}
		undef $all;
		$teaccount = "&account_id=".$accid;
	}

	{
		($tddelay) = $db->selectrow_array("SELECT value_ FROM user_params WHERE name_ = 'tunnel_delay' AND user_id = $accid");
		$tddelay += 0;
		unless ($tddelay) {
			$tddelay = 60;		# default delay 60 minutes
		}
		if (($action eq "save") && (exists $FORM{"tddelay"}) && ($FORM{"tddelay"} != $tddelay) && ($FORM{"tddelay"} > 0)) {
			$tddelay = floor($FORM{"tddelay"});
			$db->do("INSERT INTO user_params VALUES (NULL, $accid, 'tunnel_delay', '$tddelay') ON DUPLICATE KEY UPDATE value_ = '$tddelay'");
		}
	}

	if ($action eq "testemail") {
		$db->do("INSERT INTO events VALUES (NULL, NULL, $accid, NOW(), 1, 'test', 0)");
	}

	if (($action eq "remove") && ($emlid > 0)) {
		($oldmail, $oldflags) = $db->selectrow_array("SELECT address, flags FROM emails WHERE id = $emlid AND users_id = $accid");
		$db->do("DELETE FROM emails WHERE id = $emlid AND users_id = $accid");
		$oldtun = ($oldflags & 1)?"checked":"";
		$oldbyp = ($oldflags & 2)?"checked":"";
		$oldups = ($oldflags & 4)?"checked":"";
		$oldcom = ($oldflags & 8)?"checked":"";
		$oldsps = ($oldflags & 16)?"checked":"";
	} else {
		$oldtun = "checked";
		$oldbyp = "checked";
		$oldups = "checked";
		$oldcom = "checked";
		$oldsps = "checked";
	}

	my %prop = ();
	{
		my $elist = $db->selectall_arrayref("SELECT name_, value_ FROM sysprop WHERE house_id = 0 AND name_ LIKE 'mail%'");
		foreach my $erow (@$elist) {
			my ($name, $val) = @$erow;
			$prop{$name} = $val;
		}
		undef $elist;
	}
	my $newadd = 0;
	if ($action eq "save") {
		if ($FORM{"email0"} ne "") {
			if ($FORM{"email0"} =~ m/^\w[\w\.\-]*\w\@\w[\w\.\-]*\w(\.\w{2,4})$/) {		# really email?
				my $flags = ((exists $FORM{"tun0"})?1:0) + ((exists $FORM{"byp0"})?2:0) + ((exists $FORM{"ups0"})?4:0) + ((exists $FORM{"com0"})?8:0) + ((exists $FORM{"sps0"})?16:0);
				$db->do("INSERT INTO emails VALUES (NULL, $accid, '".$FORM{"email0"}."', 0, $flags)");
				($newadd) = $db->selectrow_array("SELECT MAX(id) FROM emails");
			} else {
				$oldmail = $FORM{"email0"};
			}
		}
		if (exists $FORM{"alarms_email"}) {
			$db->do("UPDATE emails SET status = 1 WHERE users_id = $accid");
		} else {
			$db->do("UPDATE emails SET status = 0 WHERE users_id = $accid");
		}
		if ((exists $FORM{"mailhost"}) && ($FORM{"mailhost"} ne "")) {
			$db->do("UPDATE sysprop SET value_ = '".$FORM{"mailhost"}."' WHERE house_id = 0 AND name_ = 'mailhost'");
			$prop{"mailhost"} = $FORM{"mailhost"};
		}
		if ((exists $FORM{"mailport"}) && ($FORM{"mailport"} ne "")) {
			$db->do("UPDATE sysprop SET value_ = '".$FORM{"mailport"}."' WHERE house_id = 0 AND name_ = 'mailport'");
			$prop{"mailport"} = $FORM{"mailport"};
		}
		if ((exists $FORM{"mailfrom"}) && ($FORM{"mailfrom"} ne "")) {
			$db->do("UPDATE sysprop SET value_ = '".$FORM{"mailfrom"}."' WHERE house_id = 0 AND name_ = 'mailfrom'");
			$prop{"mailfrom"} = $FORM{"mailfrom"};
		}
		if ((exists $FORM{"mailuser"}) && ($FORM{"mailuser"} ne "")) {
			$db->do("UPDATE sysprop SET value_ = '".$FORM{"mailuser"}."' WHERE house_id = 0 AND name_ = 'mailuser'");
			$prop{"mailuser"} = $FORM{"mailuser"};
		}
		if ((exists $FORM{"mailpass"}) && ($FORM{"mailpass"} ne "")) {
			$db->do("UPDATE sysprop SET value_ = '".$FORM{"mailpass"}."' WHERE house_id = 0 AND name_ = 'mailpass'");
			$prop{"mailpass"} = $FORM{"mailpass"};
		}
	}

	{
		my $all = $db->selectall_arrayref("SELECT id, address, status, flags FROM emails WHERE users_id = $accid ORDER BY id");
		foreach my $row (@$all) {
			my ($noid, $email, $status, $flags) = @$row;
			if ($status > 0) {
				$notenab ++;
			}
			if (($action eq "save") && ($noid != $newadd)) {
				if (exists $FORM{"email".$noid}) {
					if (($FORM{"email".$noid} ne $email) && ($FORM{"email".$noid} =~ m/^\w[\w\.\-]*\w\@\w[\w\.\-]*\w(\.\w{2,4})$/)) {
						$email = $FORM{"email".$noid};
						$db->do("UPDATE emails SET address = '$email' WHERE id = $noid");
					}
				}
				my $nflags = ((exists $FORM{"tun".$noid})?1:0) + ((exists $FORM{"byp".$noid})?2:0) + ((exists $FORM{"ups".$noid})?4:0) + ((exists $FORM{"com".$noid})?8:0) + ((exists $FORM{"sps".$noid})?16:0);
				if ($nflags != $flags) {
					$flags = $nflags;
					$db->do("UPDATE emails SET flags = $flags WHERE id = $noid");
				}
			}
			$acemails .= "<tr style=\"height:30px\" align=\"center\"><td nowrap=\"nowrap\">
					<input name=\"email".$noid."\" size=\"35\" maxlength=\"190\" value=\"$email\" type=\"text\">
					<td><input name=\"tun".$noid."\" type=\"checkbox\" ".(($flags & 1)?"checked":"")."></td>
					<td><input name=\"byp".$noid."\" type=\"checkbox\" ".(($flags & 2)?"checked":"")."></td>
					<td><input name=\"ups".$noid."\" type=\"checkbox\" ".(($flags & 4)?"checked":"")."></td>
					<td><input name=\"sps".$noid."\" type=\"checkbox\" ".(($flags & 16)?"checked":"")."></td>
					<td><input name=\"com".$noid."\" type=\"checkbox\" ".(($flags & 8)?"checked":"")."></td>
					</td><td nowrap=\"nowrap\" class=\"noborder\">
					<input name=\"Delete\"".$noid." value=\" Remove \" onClick=\"window.location.href='./engine.pl?mode=--mode--&submode=--submode--&action=remove&id=$noid$teaccount';\" type=\"button\"></td></tr>\n";
		}
		undef $all;
	}

	my $nenabled = ($notenab == 0)?"":" checked=\"checked\"";
	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--alarms_email--/$nenabled/g;
		$inline =~ s/--emails--/$acemails/g;
		$inline =~ s/--accountid--/$teaccount/g;
		$inline =~ s/--oldmail--/$oldmail/g;
		$inline =~ s/--tddelay--/$tddelay/g;
		$inline =~ s/--oldtun--/$oldtun/g;
		$inline =~ s/--oldbyp--/$oldbyp/g;
		$inline =~ s/--mailhost--/$prop{mailhost}/g;
		$inline =~ s/--mailpass--/$prop{mailpass}/g;
		$inline =~ s/--mailuser--/$prop{mailuser}/g;
		$inline =~ s/--mailfrom--/$prop{mailfrom}/g;
		$inline =~ s/--mailport--/$prop{mailport}/g;
		$inline =~ s/--oldups--/$oldups/g;
		$inline =~ s/--oldsps--/$oldsps/g;
		$inline =~ s/--oldcom--/$oldcom/g;
		$inline =~ s/--acclist--/$acclist/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# mobile accounts management

if (($uimode eq "userinfo") && ($uismode eq "mobileacc") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $perpage = 50;		# default value
	my $search = (exists $FORM{searchtext})?$FORM{searchtext}:"";
	my $curpage = ((exists $FORM{page})?$FORM{page}:1) + 0;
	my $stfilter = "";
	my $fstatus = ((exists $FORM{sfilter})?$FORM{sfilter}:3) + 0;		# all by default
	my @stlist = ("Active", "Pending", "Disabled", "All");
	for my $ii (0 .. $#stlist) {
		$stfilter .= "<option value=\"".$ii."\" ".(($ii == $fstatus)?" selected=\"selected\"":"").">".$stlist[$ii]."</option>";
	}
	my $stafilter = "1 = 1";		# any
	if ($fstatus == 0) {
		$stafilter = "ausers.status & 1";		# active
	} elsif ($fstatus == 1) {
		$stafilter = "ausers.status & 4";		# pending
	} elsif ($fstatus == 2) {
		$stafilter = "(ausers.status & 1) = 0";		# disabled
	}
	my $sfilter = ($search eq "")?"$stafilter":"(ausers.core_id = ".($search + 0)." OR ausers.email LIKE '%".$search."%' OR UCASE(ausers.name_) LIKE '%".uc($search)."%') AND $stafilter";
        my $maxrec = 10;
        my $fromrec = $maxrec * ($curpage - 1);
        my ($allrec) = $db->selectrow_array("SELECT COUNT(ausers.id) FROM ausers WHERE $sfilter ORDER BY ausers.id");
        $allrec += 0;
        my $maxpage = floor($allrec / $maxrec) + 1;
        if ((floor($allrec / $maxrec) == ($allrec / $maxrec)) && (floor($allrec / $maxrec) > 0)) {
        	$maxpage --;
        }

        if ($action eq "remove") {
        	$db->do("DELETE FROM ausers WHERE id = ".($FORM{"userid"} + 0));
        }
	my $userlist = "";
	my %corez = ();
	my $all = $db->selectall_arrayref("SELECT ausers.id, ausers.core_id, ausers.updated, ausers.email, ausers.name_, ausers.zones, ausers.status, ausers.logged, ausers.regged, ausers.lastip, systems.description, tunnel.username FROM ausers LEFT JOIN systems ON systems.house_id = ausers.core_id LEFT JOIN tunnel ON tunnel.house_id = ausers.core_id WHERE $sfilter ORDER BY ausers.core_id, ausers.id LIMIT $fromrec, $maxrec");
	foreach my $row (@$all) {
		my ($uid, $cid, $upd, $email, $name, $zones, $sts, $logged, $regged, $lastip, $desc, $sid) = @$row;
		if (($action eq "disable") && ($uid == $FORM{"userid"})) {	# change user state
			if ($sts & 4) {
				$sts = $sts ^ 4;		# activate
			} else {
				$sts = $sts ^ 1;		# active/inactive
			}
			$db->do("UPDATE ausers SET updated = NOW(), status = $sts WHERE id = $uid");
		}
		my $clr = "background:#EEEEEE;";				# grey
		my $acctxt = "Inactive";
		my $diskey = "Enable";
		if ($sts & 4) {			# pending
			$clr = "background:#DDDDFF;";		# blue
			$acctxt = "Pending";
			$diskey = "Activate";
		} elsif ($sts & 1) {			# active
			$clr = "background:#DDFFDD;";		# green
			$acctxt = "Active";
			$diskey = "Disable";
		}
		$acctxt .= " <b>".(($sts & 2)?"admin":"user")."</b> account";
		my $sernum = reverse(lc($sid));
		my $tlogged = (($logged eq "") || ($logged eq "NULL"))?"Never logged":$logged;
		my $occupop = "";
		unless (exists $corez{$cid}) {
			my $dbname = sprintf("smart%05d", $cid);
			my $zall = $db->selectall_arrayref("SELECT id, description FROM $dbname.zones WHERE id > 2");
			foreach my $zow (@$zall) {
				my ($zid, $zdesc) = @$zow;
				$corez{$cid}{$zid} = $zdesc;
			}
			undef $zall;
		}
		my %write = ();
		my @accss = split(/\,/, $zones);
		foreach my $zid (@accss) {
			$write{$zid} = 1;
		}
		if (exists $corez{$cid}) {
			my $objcnt = keys %{$corez{$cid}};
			my $bobjdis = "";
			my $oldot = "";
			my $nextprev = "<td></td>";
			my $popage = 1;
			my $maxpage = floor($objcnt / 26) + 1;
			while ($popage <= $maxpage) {
				$occupop .= "<div style=\"position: relative; width: 0; height: 0\">
					<div id=\"pop".$uid."pg$popage\" style=\"position: absolute; left: -230px; top: 19px; visibility: hidden;\">
					<table style=\"border: 1px solid black; padding: 3px; background-color: #F0F0F0;\">
					<tr><td class=NWL><input type=\"button\" value=\"X\" onClick=\"showSch($uid,$popage);\" style=\"color:#F00;\"></td>
					<td class=NWC colspan=2 nowrap=\"nowrap\">&nbsp;&nbsp;<b>Zones with write access</b>&nbsp;&nbsp;</td></tr>
					<tr><td colspan=2><div class=\"in2\"></div></td></tr>";
				if ($maxpage > 1) {
					$nextprev = "<td class=NWC><a class=\"".(($popage == 1)?"greylink":"blacklink")."\" href=\"#\" onClick=\"showSch($uid,".($popage - 1).");\">Prev</a>&nbsp;&nbsp;[page $popage of $maxpage]<a class=\"".(($popage == $maxpage)?"greylink":"blacklink")."\" href=\"#\" onClick=\"showSch($uid,".($popage + 1).");\">&nbsp;&nbsp;Next</a></td>";
				}
				$occupop .= "<tr><td>&nbsp;</td>$nextprev</tr>
					<tr><td colspan=2><div class=\"in2\"></div></td></tr>";
				my $cnt = 0;
				my $cfr = (($popage - 1) * 26);
				my $cto = $popage * 26;
				foreach my $obj (sort keys %{$corez{$cid}}) {
					if ($sts & 2) {					# admin
						$write{$obj} = 1;
					}
					if (($cnt >= $cfr) && ($cnt < $cto)) {
						if ($obj ne $oldot) {
							$oldot = $obj;
							if ($cnt != $cfr) {		# not first line
								$occupop .= "<tr><td colspan=2><div class=\"in2\"></div></td></tr>";
							}
						}
						my $curobj = $corez{$cid}{$obj};
						$occupop .= "<tr><td".((exists $write{$obj})?" class=GRN":"").">&nbsp;&nbsp;&nbsp;&nbsp;</td><td class=NW>$curobj </td></tr>";
					}
					$cnt ++;
				}
				$occupop .= "</table></div></div>";
				$popage ++;
			}
		}
		my $occudis = (exists $corez{$cid})?"":' disabled="disabled"';
		$userlist .= <<EOF;
			<tbody style="$clr">
			<tr>
				<td nowrap="nowrap" width=300 colspan=2 height=18>&nbsp;$acctxt <b>$email</b></a></td>
				<td nowrap="nowrap" width=300 colspan=2>&nbsp;Assigned to Cello <b>Core $cid</b>, ID $sernum</td>
			</tr>
			<tr>
				<td nowrap="nowrap" width="148" height=18>&nbsp;Account registered:</td>
				<td class="stdbold" width="148">&nbsp;$regged</td>
				<td nowrap="nowrap" width=148>&nbsp;Customer logged in:</td>
				<td class="stdbold" width="148">&nbsp;$tlogged</td>
			</tr>
			<tr>
				<td nowrap="nowrap" width="148" height=18>&nbsp;Last known account IP:</td>
				<td class="stdbold" width="148">&nbsp;$lastip</td>
				<td nowrap="nowrap" width="300" colspan=2 align="right">$occupop<input name="butt$uid" id="butt$uid" value="Zone access" type="button" style="color:#000;" onClick="showSch($uid,0);"$occudis>&nbsp;<input name="disable" value="$diskey" type="button" onClick="DisableUser($uid);">&nbsp;<input name="delete" value="Delete" type="button" onClick="DeleteUser($uid,'$email');"></td>
			</tr>
			</tbody>
			<tr><td nowrap="nowrap" colspan=4>&nbsp;</td></tr>
EOF
	}
	undef $all;

	if ($userlist eq "") {
		$userlist .= "<tr><td nowrap=\"nowrap\" class=\"stdbold\" colspan=2 width=300><br>No mobile accounts found by search criteria<br>&nbsp;</td><td width=300>&nbsp;</td></tr><tr><td nowrap=\"nowrap\"><div class=in10></div></td></tr>\n";
	}

	$headadd .= <<EOF;
	<script language="JavaScript">
		function DeleteUser(uid,email) {
			var answer = confirm ("Action irreversibly removes account "+email+"\\n\\nAre you sure?");
			if (answer) {
				window.location = './engine.pl?mode=userinfo&submode=mobileacc&action=remove&userid='+uid;
			}
		}
		function DisableUser(uid) {
			window.location = './engine.pl?mode=userinfo&submode=mobileacc&action=disable&userid='+uid;
		}
		function PagerDirect(page) {
			document.getElementById('page').value = page;
			document.eventForm.submit();
		}
		function showSch(zid,page) {
			var opsch = document.eventForm.opsched.value;
			var oppag = document.eventForm.oppage.value;
			if (opsch > 0) {
				if (opsch == zid) {
					if (page == 0) {
						page = oppag;
					}
					document.getElementById('pop'+zid+'pg'+oppag).style.visibility = 'hidden';
					if (page == oppag) {
						document.eventForm.opsched.value = 0;
						document.getElementById('butt'+zid).style.color = '#000';
						document.eventForm.popopen.value = 0;
					} else {
						document.getElementById('pop'+zid+'pg'+page).style.visibility = 'visible';
						document.eventForm.oppage.value = page;
						document.eventForm.popopen.value = 1;
					}
				} else {
					if (page == 0) {
						page = 1;
					}
					document.getElementById('pop'+opsch+'pg'+oppag).style.visibility = 'hidden';
					document.getElementById('butt'+opsch).style.color = '#000';
					document.getElementById('pop'+zid+'pg'+page).style.visibility = 'visible';
					document.getElementById('butt'+zid).style.color = '#F00';
					document.eventForm.opsched.value = zid;
					document.eventForm.oppage.value = page;
					document.eventForm.popopen.value = 1;
				}
			} else {
				if (page == 0) {
					page = 1;
				}
				document.getElementById('pop'+zid+'pg'+page).style.visibility = 'visible';
				document.getElementById('butt'+zid).style.color = '#F00';
				document.eventForm.opsched.value = zid;
				document.eventForm.oppage.value = page;
				document.eventForm.popopen.value = 1;
			}
			return false;
		}
	</script>
	<style>
		.NWC { white-space:nowrap; text-align: center; }
		.NWL { white-space:nowrap; text-align: left; }
		.NWR { white-space:nowrap; text-align: right; }
		.NW { white-space:nowrap; }
		.DDD { background:#DDD; }
		.GRN { background:#7F7; }
		.NILH { margin:0px; background:#8F8; color:#8F8; }
		.CBOX { width:15px; }
		.NWBW { width:150px; white-space:nowrap; background:#FFF; }
		A.greylink { color: #DDD; font: bold 11px Arial,Helvetica,sans-serif; text-decoration: none; pointer-events: none; cursor: not-allowed; text-decoration: none; }
	</style>
EOF
	my $pager = "";
	if ($curpage <= 1) {
		$curpage = 1;
		$pager .= "First page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage - 1)."');\"><< Previous page</a>";
	}
	$pager .= " | ";
	for (my $ii = 1; $ii <= $maxpage; $ii ++) {
		if ($ii == $curpage) {
			$pager .= "<b>$ii</b> ";
		} else {
			$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('$ii');\">$ii</a> ";
		}
	}
	$pager .= "| ";
	if ($curpage >= $maxpage) {
		$curpage = $maxpage;
		$pager .= "Last page";
	} else {
		$pager .= "<a href=\"#\" class=\"navi\" onClick=\"PagerDirect('".($curpage + 1)."');\">Next page >></a>";
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--userlist--/$userlist/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--sfilter--/$stfilter/g;
		$inline =~ s/--searchtext--/$search/g;
		$inline =~ s/--pager--/$pager/g;
		$inline =~ s/--curpage--/$curpage/g;
		$inline =~ s/--perpage--/$perpage/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# partner accounts administration

if (($uimode eq "userinfo") && ($uismode eq "accounts") && ($uaccess >= $alevel{$uimode.$uismode})) {
	$eccc = 0;
	my %hiders = ("noneccc", (($eccc)?0:1));
	my $accid = $FORM{account_id} + 0;
	my ($acclist, $accdel, $houselst, $errmsg) = ("", "", "", "");
	my ($accactive, $hmask) = (0, "0");
	my @accactv = ("", "", "");
	my ($acemail, $acphone, $aclogin, $acpass, $acnamea, $acnameb) = ("", "", "", "", "", "");
	my $maxacc = ($eccc)?2:1;

	if (($action eq "remove") && ($accid > 0)) {
		$db->do("DELETE FROM users WHERE id = $accid AND access BETWEEN 0 AND $maxacc");
		$accid = 0;
	}

	my ($accidmax) = $db->selectrow_array("SELECT MAX(id) FROM users");
	$accidmax ++;
	if (($action eq "save") && ($accid > 0)) {
		$aclogin = $FORM{"login"};
		$acpass = $FORM{"password"};
		$acnamea = $FORM{"name1"};
		$acnameb = $FORM{"name2"};
		$acemail = $FORM{"email"};
		$acphone = $FORM{"phone1"};
		$accactive = $FORM{"active"} + 0;
		my $iserr = 0;
		if ($aclogin eq "") {
			$iserr ++;
			$errmsg = "Username cannot be empty";
		}
		if ($acpass eq "") {
			$iserr ++;
			$errmsg = "Password cannot be empty";
		}
		if ($acnamea eq "") {
			$iserr ++;
			$errmsg = "First name cannot be empty";
		}
		if ($iserr == 0) {
			my ($notunique) = $db->selectrow_array("SELECT COUNT(id) FROM users WHERE login = '$aclogin' AND id != $accid");
			if ($notunique > 0) {
				$iserr ++;
				$errmsg = "Username already exists";
			}
		}
		if (($accactive > $maxacc) || ($accactive < 0)) {		# prevent from raising admin access
			$accactive = $maxacc;
		} elsif (($accactive > 0) && ($eccc)) {
			$accactive = $maxacc;
		}
		if ($iserr == 0) {
			my ($maxhouse) = $db->selectrow_array("SELECT MAX(house_id) FROM systems");
			for my $hoid (0 .. $maxhouse) {
				if ((exists $FORM{"home".$hoid}) || ($eccc)) {
					$hmask .= ",$hoid";
				}
			}
			if ($accid == $accidmax) {		# adding new account
				$accidmax ++;
				$db->do("INSERT INTO users (id, login, password, name1, name2, phone1, email, access, houses) VALUES ($accid, '$aclogin', '$acpass', '$acnamea', '$acnameb', '$acphone', '$acemail', $accactive, '$hmask')");
#				if ($eccc) {
					my ($ruim) = $db->selectrow_array("SELECT ui_list FROM ui_access WHERE id = 1");
					$db->do("INSERT INTO ui_access VALUES (NULL, $accid, 2, '$ruim')");			# set UI access same to superadmin
#				}
			} else {				# updating existing one
				$db->do("UPDATE users SET login = '$aclogin', password = '$acpass', name1 = '$acnamea', name2 = '$acnameb', phone1 = '$acphone', email = '$acemail', access = $accactive, houses = '$hmask' WHERE id = $accid");
			}
		}
	}

	{
		my $all = $db->selectall_arrayref("SELECT id, login, name1 FROM users WHERE access BETWEEN 0 AND $maxacc AND id > 1 ORDER BY id DESC");
		foreach my $row (@$all) {
			my $uid = @$row[0];
			if ($accid == 0) {
				$accid = $uid;		# set to first account in list
			}
			$acclist .= "<option value=\"$uid\" ".(($accid == $uid)?"selected=\"selected\"":"").">".@$row[1].": ".substr(@$row[2], 0, 30)."</option>";
		}
		undef $all;
	}
	if ($accid == 0) {
		$accid = $accidmax;
	}
	$acclist .= "<option value=\"$accidmax\" ".(($accid == $accidmax)?"selected=\"selected\"":"").">Create new account</option>";

	if (($accid > 0) && ($accid < $accidmax)) {
		($acemail, $acphone, $aclogin, $acpass, $acnamea, $acnameb, $accactive, $hmask) = $db->selectrow_array("SELECT email, phone1, login, password, name1, name2, access, houses FROM users WHERE id = $accid");
		$accdel = "&nbsp;&nbsp;&nbsp;<input name=\"accdel\" value=\"Delete Account\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&account_id=$accid&action=remove'\" type=\"button\">";
	}

	{
		my $rowcnt = 0;
		my $all = $db->selectall_arrayref("SELECT house_id, IF(house_id IN ($hmask),'1','0') FROM systems ORDER BY id");
		foreach my $row (@$all) {
			my $hoid = @$row[0];
			if ($rowcnt == 0) {
				$houselst .= "<tr bgcolor=#F0F0F0>";
			} elsif ($rowcnt == 8) {
				$rowcnt = 0;
				$houselst .= "</tr><tr bgcolor=#F0F0F0>";
			}
			$rowcnt ++;
			$houselst .= "<td nowrap=\"nowrap\"><b><input ".(($eccc)?"disabled=\"disabled\"":"")." id=\"home".$hoid."\" name=\"home".$hoid."\" type=\"checkbox\" ".(((@$row[1] > 0) || ($eccc))?"checked=\"checked\"":"")."> $hoid &nbsp;</td>";
		}
		undef $all;
	}
	$houselst .= "</tr>";
	$headadd .= <<EOF;
	<script language="JavaScript">
		function checkAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					checkboxes[i].checked = true;
				}
			}
		}
		function uncheckAll() {
			var checkboxes = document.getElementsByTagName('input');
			for (var i = 0; i < checkboxes.length; i++) {
				if (checkboxes[i].type == 'checkbox') {
					checkboxes[i].checked = false;
				}
			}
		}
	</script>
EOF
	$accactv[(($accactive)?1:0)] = "checked=\"checked\"";

	if ($errmsg ne "") {
		$errmsg = "<tr><td colspan=2><br><b><font color=red>$errmsg</font></b></td></tr>";
	}
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	my $hidenow = 0;
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--active_sel1--/$accactv[1]/g;
		$inline =~ s/--active_sel0--/$accactv[0]/g;
		$inline =~ s/--email--/$acemail/g;
		$inline =~ s/--message--/$errmsg/g;
		$inline =~ s/--phone1--/$acphone/g;
		$inline =~ s/--name1--/$acnamea/g;
		$inline =~ s/--name2--/$acnameb/g;
		$inline =~ s/--houses--/$houselst/g;
		$inline =~ s/--login--/$aclogin/g;
		$inline =~ s/--password--/$acpass/g;
		$inline =~ s/--acclist--/$acclist/g;
		$inline =~ s/--accdel--/$accdel/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# personal details

if (($uimode eq "userinfo") && ($uismode eq "details") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("super", (($uaccess >= 2)?1:0));
        my $vccity = 0;
	my @timezones = ("(GMT-12:00) International Date Line West", "(GMT-11:00) Coordinated Universal Time-11", "(GMT-10:00) Hawaii", "(GMT-09:00) Alaska", "(GMT-08:00) Baja California", "(GMT-08:00) Pacific Time (US & Canada)", "(GMT-07:00) Arizona", "(GMT-07:00) Chihuahua, La Paz, Mazatlan", "(GMT-07:00) Mountain Time (US & Canada)", "(GMT-06:00) Central America", "(GMT-06:00) Central Time (US & Canada)", "(GMT-06:00) Guadalajara, Mexico City, Monterrey", "(GMT-06:00) Saskatchewan", "(GMT-05:00) Bogota, Lima, Quito, Rio Branco", "(GMT-05:00) Eastern Time (US & Canada)", "(GMT-05:00) Indiana (East)", "(GMT-04:30) Caracas", "(GMT-04:00) Asuncion", "(GMT-04:00) Atlantic Time (Canada)", "(GMT-04:00) Cuiaba", "(GMT-04:00) Georgetown, La Paz, Manaus, San Juan", "(GMT-04:00) Santiago", "(GMT-03:30) Newfoundland", "(GMT-03:00) Brasilia", "(GMT-03:00) Buenos Aires", "(GMT-03:00) Cayenne, Fortaleza", "(GMT-03:00) Greenland", "(GMT-03:00) Montevideo", "(GMT-03:00) Salvador", "(GMT-02:00) Coordinated Universal Time-02", "(GMT-01:00) Azores", "(GMT-01:00) Cabo Verde Is.", "(GMT) Casablanca", "(GMT) Coordinated Universal Time", "(GMT) Dublin, Edinburgh, Lisbon, London", "(GMT) Monrovia, Reykjavik", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris", "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb", "(GMT+01:00) West Central Africa", "(GMT+01:00) Windhoek", "(GMT+02:00) Amman", "(GMT+02:00) Athens, Bucharest", "(GMT+02:00) Beirut", "(GMT+02:00) Cairo", "(GMT+02:00) Damascus", "(GMT+02:00) E. Europe", "(GMT+02:00) Harare, Pretoria", "(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", "(GMT+02:00) Istanbul", "(GMT+02:00) Jerusalem", "(GMT+02:00) Kaliningrad (RTZ 1)", "(GMT+02:00) Tripoli", "(GMT+03:00) Baghdad", "(GMT+03:00) Kuwait, Riyadh", "(GMT+03:00) Minsk", "(GMT+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)", "(GMT+03:00) Nairobi", "(GMT+03:30) Tehran", "(GMT+04:00) Abu Dhabi, Muscat", "(GMT+04:00) Baku", "(GMT+04:00) Izhevsk, Samara (RTZ 3)", "(GMT+04:00) Port Louis", "(GMT+04:00) Tbilisi", "(GMT+04:00) Yerevan", "(GMT+04:30) Kabul", "(GMT+05:00) Ashgabat, Tashkent", "(GMT+05:00) Ekaterinburg (RTZ 4)", "(GMT+05:00) Islamabad, Karachi", "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi", "(GMT+05:30) Sri Jayawardenepura", "(GMT+05:45) Kathmandu", "(GMT+06:00) Astana", "(GMT+06:00) Dhaka", "(GMT+06:00) Novosibirsk (RTZ 5)", "(GMT+06:30) Yangon (Rangoon)", "(GMT+07:00) Bangkok, Hanoi, Jakarta", "(GMT+07:00) Krasnoyarsk (RTZ 6)", "(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi", "(GMT+08:00) Irkutsk (RTZ 7)", "(GMT+08:00) Kuala Lumpur, Singapore", "(GMT+08:00) Perth", "(GMT+08:00) Taipei", "(GMT+08:00) Ulaanbaatar", "(GMT+09:00) Osaka, Sapporo, Tokyo", "(GMT+09:00) Seoul", "(GMT+09:00) Yakutsk (RTZ 8)", "(GMT+09:30) Adelaide", "(GMT+09:30) Darwin", "(GMT+10:00) Brisbane", "(GMT+10:00) Canberra, Melbourne, Sydney", "(GMT+10:00) Guam, Port Moresby", "(GMT+10:00) Hobart", "(GMT+10:00) Magadan", "(GMT+10:00) Vladivostok, Magadan (RTZ 9)", "(GMT+11:00) Chokurdakh (RTZ 10)", "(GMT+11:00) Solomon Is., New Caledonia", "(GMT+12:00) Anadyr, Petropavlovsk-Kamchatsky (RTZ 11)", "(GMT+12:00) Auckland, Wellington", "(GMT+12:00) Coordinated Universal Time+12", "(GMT+12:00) Fiji", "(GMT+13:00) Nuku'alofa", "(GMT+13:00) Samoa", "(GMT+14:00) Kiritimati Island");
	my $locfix = $FORM{"locfix"} + 0;
	my $acclist = "";

	my $clientsel = $clientid;
	if (exists $FORM{clientsel}) {
		$clientsel = $FORM{clientsel};
	}

	if (($action eq "save") && ($clientsel > 0)) {
		if (($FORM{city} eq "") || ($FORM{city} eq "--")) {
			$FORM{city} = $FORM{ccity};		# manual city entry
			$vccity ++;
		}
		$db->do("UPDATE users SET city='".$FORM{city}."', province='".$FORM{province}."', country='".$FORM{country}."', postal='".$FORM{postal}."', phone1='".$FORM{phone1}."', phone2='".$FORM{phone2}."', phone3='".$FORM{phone3}."', email='".$FORM{email}."', timezone='".($FORM{timezone} + 0)."', comfort='".($FORM{comfort} + 0)."', t_display='".($FORM{t_display} + 0)."', name1='".$FORM{name1}."', name2='".$FORM{name2}."', address1='".$FORM{address1}."', address2='".$FORM{address2}."' WHERE id = $clientsel");
		if (($FORM{name1} eq "") || ($FORM{name2} eq "") || ($FORM{address1} eq "") || ($FORM{city} eq "") || ($FORM{postal} eq "") || ($FORM{email} eq "")) {
#			$message = "<tr><td nowrap=\"nowrap\" width=\"138\">&nbsp;</td><td nowrap=\"nowrap\"><font color=red><br>One or more important fields must be filled!</td></tr>\n";
		}
		if ($clientsel == $clientid) {
			$utimezone = $FORM{timezone} + 0;
		}
		$db->do("DELETE FROM user_params WHERE user_id = $clientsel AND name_ = 'dst'");
		my $dst = (exists $FORM{dst})?1:0;
		$db->do("INSERT INTO user_params VALUES (NULL, $clientsel, 'dst', '$dst')");
	}

	if ($action eq "save") {
		my ($oldpass) = $db->selectrow_array("SELECT password FROM users WHERE id = $clientsel");
        	my $msgtxt = "";
        	if (length($FORM{password_new}) > 0) {
        		if ($FORM{password_old} ne $oldpass) {
				$msgtxt = "<font color=red>Current password does not match!";
			} else {
				$db->do("UPDATE users SET password='".$FORM{password_new}."' WHERE id = $clientsel AND password='".$FORM{password_old}."'");
				$msgtxt = "Password changed successfully";
			}
        	}
        	if ($msgtxt) {
	        	$messsage = "<tr><td nowrap=\"nowrap\" width=\"138\">&nbsp;</td><td nowrap=\"nowrap\"><br>$msgtxt</td></tr>\n";
	        }
	}
	my ($usrlogin) = $db->selectrow_array("SELECT login FROM users WHERE id = $clientsel");

        my $comfort = 0;
        my @lcomfort = ("", "", "", "", "");
        my $tdisplay = 0;
        my @ltdisp = ("", "");
        my $timezone = 0;
        my ($ltimezone, $province, $lprovince, $country, $lcountry, $ccity, $lcity, $dst) = ("", "", "", "", "", "", "", "");
        my ($name1, $name2, $email, $phone1, $phone2, $phone3, $postal, $city, $address1, $address2) = ("", "", "", "", "", "", "", "", "", "");
	my $all = $db->selectall_arrayref("SELECT comfort, t_display, timezone, province, country, name1, name2, email, phone1, phone2, phone3, postal, city, address1, address2 FROM users WHERE id = $clientsel ORDER BY id DESC LIMIT 1");
	foreach my $row (@$all) {
		$comfort = @$row[0] + 0;
		$lcomfort[$comfort] = "checked=\"checked\"";
		$tdisplay = @$row[1] + 0;
		$ltdisp[$tdisplay] = "checked=\"checked\"";
		$timezone = @$row[2] + 0;
		$province = @$row[3];
		$country = @$row[4];
		$name1 = @$row[5];
		$name2 = @$row[6];
		$email = @$row[7];
		$phone1 = @$row[8];
		$phone2 = @$row[9];
		$phone3 = @$row[10];
		$postal = @$row[11];
		$city = @$row[12];
		$address1 = @$row[13];
		$address2 = @$row[14];
	}
	undef $all;
	my ($isdst) = $db->selectrow_array("SELECT value_ FROM user_params WHERE user_id = $clientsel AND name_ = 'dst'");
	$dst = ($isdst)?"checked=\"checked\"":"";
	{
		my $all = $db->selectall_arrayref("SELECT country_code, country_name, dialingPrefix FROM country ORDER BY country_name");
		foreach my $row (@$all) {
			my $cc = @$row[0];
			my $cn = @$row[1];
			my $dp = @$row[2];
			my $sel = "";
			if ($country eq $cc) {
				$sel = "selected=\"selected\"";
				if (($phone1 eq "") || ($phone1 eq "+")) {
					$phone1 = $dp;
				}
			}
			$lcountry .= "<option value=\"$cc\" $sel>$cn</option>";
		}
		undef $all;
	}
	if ($country) {
		my $all = $db->selectall_arrayref("SELECT country_code, state_code, state_name FROM states WHERE country_code = '$country' ORDER BY state_name");
		foreach my $row (@$all) {
			my $cc = @$row[0];
			my $sc = @$row[1];
			my $sn = @$row[2];
			my $sel = "";
			if ($province eq $sc) {
				$sel = "selected=\"selected\"";
			}
			$lprovince .= "<option value=\"$sc\"".(($province eq $sc)?" selected=\"selected\"":"").">$sn</option>";
		}
		undef $all;
	} else {
		$lprovince .= "<option value=\"--\">Select country first</option>";
	}
	if ($lprovince eq "") {
		$lprovince .= "<option value=\"--\">Not applicable</option>";
	}
	my $fcity = 0;
	my $pvcity = "<br>";
	my $regcode = "";
	if (($country) && ($province)) {
		my $all = $db->selectall_arrayref("SELECT city_name, state_code, country_code, city_name_ascii FROM city WHERE country_code = '$country' AND state_code = '$province'");
		foreach my $row (@$all) {
			my $cn = @$row[0];
			my $sc = @$row[1];
			my $cc = @$row[2];
			my $tz = @$row[3];
			my $sel = "";
			if ($city eq $cn) {
				$sel = "selected=\"selected\"";
				$fcity ++;
				$regcode = $tz;
			}
			$lcity .= "<option value=\"$cn\" $sel>$cn</option>";
		}
		undef $all;
	} else {
		$lcity .= "<option value=\"--\">Select country and province first</option>";
	}
	unless ($fcity) {
		if ($lcity eq "") {
			$pvcity = "&nbsp;&nbsp;";
		}
		$lcity .= "<option value=\"--\" selected=\"selected\">User defined</option>";
		$vccity ++;
		$ccity = $city;
	}
	if ($vccity) {
		$vccity = "$pvcity<input name=\"ccity\" size=\"32\" maxlength=\"90\" value=\"$ccity\" type=\"text\">";
	} else {
		$vccity = "";
		$lcity .= "<option value=\"--\">User defined</option>";
	}

	my $tzadd = "";
	if (($action eq "save") && ($locfix) && (($country ne "") || ($regcode ne ""))) {		# autofill timezone
		if ($regcode ne "") {		# tz by city
			my ($tzz) = $db->selectrow_array("SELECT gmtoffset FROM timezone WHERE timezoneid = '$regcode' LIMIT 1");
			if ($tzz) {
				my $hoff = floor($tzz);
				my $moff = floor(($tzz - $hoff) * 60);
				my $goff = $hoff * 100 + $moff;
				$tzadd = sprintf("%+.4d", $goff);
			}
		}
		if (($tzadd eq "") && ($country ne "")) {		# tz by country
			my ($tzz) = $db->selectrow_array("SELECT gmtoffset FROM timezone WHERE country_code = '$country' LIMIT 1");
			if ($tzz) {
				my $hoff = floor($tzz);
				my $moff = floor(($tzz - $hoff) * 60);
				my $goff = $hoff * 100 + $moff;
				$tzadd = sprintf("%+.4d", $goff);
			}
		}
		if ($tzadd ne "") {
			for my $itimezone (0 .. $#timezones) {
				my $ltzone = "+0000";
				if ($timezones[$itimezone] =~ m/^\(GMT([\+\-]\d\d)\:(\d\d)\)/) {		# extract timezone from list
					$ltzone = $1.$2;
				}
				if ($ltzone eq $tzadd) {
					$timezone = $itimezone;
				}
			}
#			$db->do("UPDATE users SET timezone='$timezone' WHERE id = $clientsel");
		}
	}
	for my $itimezone (0 .. $#timezones) {
		$ltimezone .= "<option value=\"".$itimezone."\" ".(($itimezone == $timezone)?" selected=\"selected\"":"").">".$timezones[$itimezone]."</option>";
	}

	if ($hiders{super}) {
		my $all = $db->selectall_arrayref("SELECT id, login, name1 FROM users WHERE access BETWEEN 0 AND 2 AND id > 1 ORDER BY id DESC");
		foreach my $row (@$all) {
			my $uid = @$row[0];
			$acclist .= "<option value=\"$uid\" ".(($clientsel == $uid)?"selected=\"selected\"":"").">".@$row[1].": ".substr(@$row[2], 0, 30)."</option>";
		}
		undef $all;
	}

	my $hidenow = 0;
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--email--/$email/g;
		$inline =~ s/--name1--/$name1/g;
		$inline =~ s/--name2--/$name2/g;
		$inline =~ s/--phone1--/$phone1/g;
		$inline =~ s/--phone2--/$phone2/g;
		$inline =~ s/--phone3--/$phone3/g;
		$inline =~ s/--postal--/$postal/g;
		$inline =~ s/--lcity--/$lcity/g;
		$inline =~ s/--ccity--/$ccity/g;
		$inline =~ s/--vccity--/$vccity/g;
		$inline =~ s/--dst--/$dst/g;
		$inline =~ s/--address1--/$address1/g;
		$inline =~ s/--address2--/$address2/g;
		$inline =~ s/--t_display0--/$ltdisp[0]/g;
		$inline =~ s/--t_display1--/$ltdisp[1]/g;
		$inline =~ s/--comfort0--/$lcomfort[0]/g;
		$inline =~ s/--comfort1--/$lcomfort[1]/g;
		$inline =~ s/--comfort2--/$lcomfort[2]/g;
		$inline =~ s/--comfort3--/$lcomfort[3]/g;
		$inline =~ s/--comfort4--/$lcomfort[4]/g;
		$inline =~ s/--timezone--/$ltimezone/g;
		$inline =~ s/--province--/$lprovince/g;
		$inline =~ s/--country--/$lcountry/g;
		$inline =~ s/--username--/$usrlogin/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--acclist--/$acclist/g;
		$inline =~ s/--messsage--/$messsage/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# ESP Customer details

if (($uimode eq "customer") && ($uismode eq "customer") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $locfix = $FORM{"locfix"} + 0;
	my @timezones = ("(GMT-12:00) International Date Line West", "(GMT-11:00) Coordinated Universal Time-11", "(GMT-10:00) Hawaii", "(GMT-09:00) Alaska", "(GMT-08:00) Baja California", "(GMT-08:00) Pacific Time (US & Canada)", "(GMT-07:00) Arizona", "(GMT-07:00) Chihuahua, La Paz, Mazatlan", "(GMT-07:00) Mountain Time (US & Canada)", "(GMT-06:00) Central America", "(GMT-06:00) Central Time (US & Canada)", "(GMT-06:00) Guadalajara, Mexico City, Monterrey", "(GMT-06:00) Saskatchewan", "(GMT-05:00) Bogota, Lima, Quito, Rio Branco", "(GMT-05:00) Eastern Time (US & Canada)", "(GMT-05:00) Indiana (East)", "(GMT-04:30) Caracas", "(GMT-04:00) Asuncion", "(GMT-04:00) Atlantic Time (Canada)", "(GMT-04:00) Cuiaba", "(GMT-04:00) Georgetown, La Paz, Manaus, San Juan", "(GMT-04:00) Santiago", "(GMT-03:30) Newfoundland", "(GMT-03:00) Brasilia", "(GMT-03:00) Buenos Aires", "(GMT-03:00) Cayenne, Fortaleza", "(GMT-03:00) Greenland", "(GMT-03:00) Montevideo", "(GMT-03:00) Salvador", "(GMT-02:00) Coordinated Universal Time-02", "(GMT-01:00) Azores", "(GMT-01:00) Cabo Verde Is.", "(GMT) Casablanca", "(GMT) Coordinated Universal Time", "(GMT) Dublin, Edinburgh, Lisbon, London", "(GMT) Monrovia, Reykjavik", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris", "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb", "(GMT+01:00) West Central Africa", "(GMT+01:00) Windhoek", "(GMT+02:00) Amman", "(GMT+02:00) Athens, Bucharest", "(GMT+02:00) Beirut", "(GMT+02:00) Cairo", "(GMT+02:00) Damascus", "(GMT+02:00) E. Europe", "(GMT+02:00) Harare, Pretoria", "(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", "(GMT+02:00) Istanbul", "(GMT+02:00) Jerusalem", "(GMT+02:00) Kaliningrad (RTZ 1)", "(GMT+02:00) Tripoli", "(GMT+03:00) Baghdad", "(GMT+03:00) Kuwait, Riyadh", "(GMT+03:00) Minsk", "(GMT+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)", "(GMT+03:00) Nairobi", "(GMT+03:30) Tehran", "(GMT+04:00) Abu Dhabi, Muscat", "(GMT+04:00) Baku", "(GMT+04:00) Izhevsk, Samara (RTZ 3)", "(GMT+04:00) Port Louis", "(GMT+04:00) Tbilisi", "(GMT+04:00) Yerevan", "(GMT+04:30) Kabul", "(GMT+05:00) Ashgabat, Tashkent", "(GMT+05:00) Ekaterinburg (RTZ 4)", "(GMT+05:00) Islamabad, Karachi", "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi", "(GMT+05:30) Sri Jayawardenepura", "(GMT+05:45) Kathmandu", "(GMT+06:00) Astana", "(GMT+06:00) Dhaka", "(GMT+06:00) Novosibirsk (RTZ 5)", "(GMT+06:30) Yangon (Rangoon)", "(GMT+07:00) Bangkok, Hanoi, Jakarta", "(GMT+07:00) Krasnoyarsk (RTZ 6)", "(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi", "(GMT+08:00) Irkutsk (RTZ 7)", "(GMT+08:00) Kuala Lumpur, Singapore", "(GMT+08:00) Perth", "(GMT+08:00) Taipei", "(GMT+08:00) Ulaanbaatar", "(GMT+09:00) Osaka, Sapporo, Tokyo", "(GMT+09:00) Seoul", "(GMT+09:00) Yakutsk (RTZ 8)", "(GMT+09:30) Adelaide", "(GMT+09:30) Darwin", "(GMT+10:00) Brisbane", "(GMT+10:00) Canberra, Melbourne, Sydney", "(GMT+10:00) Guam, Port Moresby", "(GMT+10:00) Hobart", "(GMT+10:00) Magadan", "(GMT+10:00) Vladivostok, Magadan (RTZ 9)", "(GMT+11:00) Chokurdakh (RTZ 10)", "(GMT+11:00) Solomon Is., New Caledonia", "(GMT+12:00) Anadyr, Petropavlovsk-Kamchatsky (RTZ 11)", "(GMT+12:00) Auckland, Wellington", "(GMT+12:00) Coordinated Universal Time+12", "(GMT+12:00) Fiji", "(GMT+13:00) Nuku'alofa", "(GMT+13:00) Samoa", "(GMT+14:00) Kiritimati Island");

	if ($action eq "save") {
		$db->do("DELETE FROM esp_settings WHERE user_id = $clientid AND name_ IN ('name1', 'name2', 'phone', 'email', 'country', 'province', 'timezone', 'dst')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'name2', '".$FORM{'name2'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'phone', '".$FORM{'phone'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'email', '".$FORM{'email'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'country', '".$FORM{'country'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'province', '".$FORM{'province'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'timezone', '".$FORM{'timezone'}."')");
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'name1', '".$FORM{'name1'}."')");
		my $newdst = (exists $FORM{'dst'})?1:0;
		$db->do("INSERT INTO esp_settings VALUES (NULL, $clientid, 1, NOW(), 'dst', '$newdst')");
		if (($FORM{'password_old'} ne "") && ($FORM{'password_new'} ne "")) {
			my ($uid) = $db->selectrow_array("SELECT id FROM esp_users WHERE email = '$ulogin' AND password = MD5('".$FORM{'password_old'}."')");
			if ($uid) {
				if (length($FORM{'password_new'}) < 6) {
					$message = "<font color=red><br>New password is too short!";
				} else {
					$db->do("UPDATE esp_users SET password = MD5('".$FORM{'password_new'}."') WHERE id = $uid");
					$message = "<font color=green><br>Customer password updated";
				}
			} else {
				$message = "<font color=red><br>Old password does not match!";
			}
		}
	}

        my ($ltimezone, $lprovince, $lcountry) = ("", "", "");
        my %values = ();
        $values{'email'} = $ulogin;
        $values{'country'} = "Canada";
        $values{'province'} = "CAN-ON";
        $values{'timezone'} = 14;
        $values{'dst'} = 1;
	my $all = $db->selectall_arrayref("SELECT flags, name_, value_ FROM esp_settings WHERE user_id = $clientid");
	foreach my $row (@$all) {	
		my $flags = @$row[0] + 0;
		if ($flags > 0) {		# record active
			$values{@$row[1]} = @$row[2];
		}
	}
	undef $all;
	my $name1 = $values{'name1'};
	my $name2 = $values{'name2'};
	my $phone = $values{'phone'};
	my $email = $values{'email'};
	my $country = $values{'country'};
	my $province = $values{'province'};
	my $timezone = $values{'timezone'} + 0;
	my $dst = ($values{'dst'} & 1)?"checked=\"checked\"":"";

	{
		my $all = $db->selectall_arrayref("SELECT country_code, country_name, dialingPrefix FROM country ORDER BY country_name");
		foreach my $row (@$all) {
			my $cc = @$row[0];
			my $cn = @$row[1];
			my $dp = @$row[2];
			my $sel = "";
			if ($country eq $cc) {
				$sel = "selected=\"selected\"";
				if (($phone eq "") || ($phone eq "+")) {
					$phone = $dp;
				}
			}
			$lcountry .= "<option value=\"$cc\" $sel>$cn</option>";
		}
		undef $all;
	}
	if ($country) {
		my $all = $db->selectall_arrayref("SELECT country_code, state_code, state_name FROM states WHERE country_code = '$country' ORDER BY state_name");
		foreach my $row (@$all) {
			my $cc = @$row[0];
			my $sc = @$row[1];
			my $sn = @$row[2];
			my $sel = "";
			if ($province eq $sc) {
				$sel = "selected=\"selected\"";
			}
			$lprovince .= "<option value=\"$sc\"".(($province eq $sc)?" selected=\"selected\"":"").">$sn</option>";
		}
		undef $all;
	} else {
		$lprovince .= "<option value=\"--\">Select country first</option>";
	}
	if ($lprovince eq "") {
		$lprovince .= "<option value=\"--\">Not applicable</option>";
	}
	my $tzadd = "";
	if (($action eq "save") && ($locfix) && ($country ne "")) {			# autofill timezone
		if ($country ne "") {		# tz by country
			my ($tzz) = $db->selectrow_array("SELECT gmtoffset FROM timezone WHERE country_code = '$country' LIMIT 1");
			if ($tzz) {
				my $hoff = floor($tzz);
				my $moff = floor(($tzz - $hoff) * 60);
				my $goff = $hoff * 100 + $moff;
				$tzadd = sprintf("%+.4d", $goff);
			}
		}
		if ($tzadd ne "") {
			for my $itimezone (0 .. $#timezones) {
				my $ltzone = "+0000";
				if ($timezones[$itimezone] =~ m/^\(GMT([\+\-]\d\d)\:(\d\d)\)/) {		# extract timezone from list
					$ltzone = $1.$2;
				}
				if ($ltzone eq $tzadd) {
					$timezone = $itimezone;
				}
			}
#			$db->do("UPDATE users SET timezone='$timezone' WHERE id = $clientid");
		}
	}
	for my $itimezone (0 .. $#timezones) {
		$ltimezone .= "<option value=\"".$itimezone."\"".(($itimezone == $timezone)?" selected=\"selected\"":"").">".$timezones[$itimezone]."</option>";
	}
	if ($message ne "") {
		$message = "<tr><td nowrap=\"nowrap\" width=\"138\">&nbsp;</td><td nowrap=\"nowrap\">$message</td></tr>\n";
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--email--/$email/g;
		$inline =~ s/--name1--/$name1/g;
		$inline =~ s/--name2--/$name2/g;
		$inline =~ s/--phone--/$phone/g;
		$inline =~ s/--timezone--/$ltimezone/g;
		$inline =~ s/--dst--/$dst/g;
		$inline =~ s/--province--/$lprovince/g;
		$inline =~ s/--country--/$lcountry/g;
		$inline =~ s/--message--/$message/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# ESP Areas

if (($uimode eq "groups") && ($uismode eq "areas") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $updmsg = "";
	my $grid = $FORM{groupid};
	my $hidenew = "";
	my $groupsl = "";
	my $whomas = $FORM{zonesms} + 0;		# who is master now?
	unless ($grid) {
		($grid) = $db->selectrow_array("SELECT MIN(id) FROM esp_groups WHERE (flags & 1) = 1");
	}
	if ($grid) {
		if ($action eq "remove") {
			my $zoneid = $FORM{zoneid} + 0;
			if ($zoneid > 0) {
				$db->do("UPDATE esp_devices SET zone_id = 0 WHERE zone_id = $zoneid AND user_id = $clientid");
				$db->do("DELETE FROM esp_zones WHERE id = $zoneid AND user_id = $clientid");
				$updmsg = "<tr><td colspan=6><br>Area deleted and all corresponding devices are unassigned</td></tr>\n";
			}
		}

		if ($action eq "save") {
			my $nzname = $FORM{zonesn};
			my $nlev = $FORM{zonesla} + 0;
			my $nori = $FORM{zonesoa} + 0;
			my $nvol = $FORM{zonesvl} + 0;
			my $ndet = $FORM{zonesdt} + 0;
			if ((length($nzname) < 6) && (length($nzname) > 0)) {
				$updmsg = "<tr><td colspan=6><br>Area name should have at least 6 alphanumeric characters</td></tr>\n";
				$nzname = "";
			} elsif (length($nzname) >= 6)  {
				my ($nzcnt) = $db->selectrow_array("SELECT COUNT(*) FROM esp_zones WHERE description = '$nzname' AND group_id = $grid AND user_id = $clientid");
				if ($nzcnt > 0) {
					$updmsg = "<tr><td colspan=6><br>Area name must be unique. Two areas of same name cannot be created</td></tr>\n";
					$nzname = "";
				}
			}
			if ($nvol < 0) {
				$updmsg = "<tr><td colspan=6><br>Area volume cannot be negative</td></tr>\n";
				$nzname = "";
			}
			unless ($nzname eq "") {
				my $ismas = ($whomas == 0)?1:0;
				if ($ismas) {
					$db->do("UPDATE esp_zones SET master = 0 WHERE group_id = $grid AND user_id = $clientid");
				}
				$db->do("INSERT INTO esp_zones VALUES (NULL, $clientid, NOW(), 1, '$nzname', $grid, $nvol, $ismas, $ndet, $nlev, $nori)");
			}
		}
		my $all = $db->selectall_arrayref("SELECT id, description FROM esp_groups WHERE user_id = $clientid AND (flags & 1) = 1 ORDER BY description, id");
		foreach my $row (@$all) {
			my $id = @$row[0];
			my $desc = @$row[1];
			$groupsl .= "<option value=\"$id\" ".(($id == $grid)?"selected=\"selected\"":"").">$desc</option>";
		}
		undef $all;
	} else {
		$updmsg = "<tr><td colspan=6><br><h2>At least <a href=\"./engine.pl?mode=groups&submode=groups\" class=\"navi\">one group</a> must be created!</td></tr>\n";
		$hidenew = ' style="visibility: hidden;"';
		$groupsl = '<option value="" disabled="disabled" selected="selected">-- No groups defined --</option>';
	}

	my $zonesl = "";
	my $zoneid = 1;
	my $ismasex = 0;
	my @zlevels = ("Basement", "Main", "Floor 1", "Floor 2", "Floor 3", "Floor 4");
	my @zorient = ("N/A", "South", "North", "West", "East");
	my @zdeltat = ("-3", "-2.5", "-2", "-1.5", "-1", "0", "1", "1.5", "2", "2.5", "3");
	my $all = $db->selectall_arrayref("SELECT id, flags, description, level, orientation, volume, master, delta_t FROM esp_zones WHERE group_id = $grid AND user_id = $clientid ORDER BY id");
	foreach my $row (@$all) {
		my $zid = @$row[0];
		my $zonedef = "zones".$zid;
		my $flags = @$row[1];
		my $zdesc = @$row[2];
		my $zlcidx = @$row[3];
		my $zocidx = @$row[4];
		my $zvol = @$row[5] + 0;
		my $zmas = @$row[6];
		my $zdelt = @$row[7] + 0;
		if ($zmas) {
			$ismasex ++;		# master found
		}
		if (($action eq "save") && ($FORM{$zonedef} ne ""))  {
			if ($FORM{$zonedef} ne $zdesc) {
				$db->do("UPDATE esp_zones SET updated = NOW(), description = '".$FORM{$zonedef}."' WHERE id = ".$zid);
				$zdesc = $FORM{$zonedef};
			}
			my $nzlev = $FORM{"zonesla".$zid} + 0;
			if ($zlcidx != $nzlev) {
				$zlcidx = $nzlev;
				$db->do("UPDATE esp_zones SET level = '$nzlev' WHERE id = ".$zid);
			}
			my $nzori = $FORM{"zonesoa".$zid} + 0;
			if ($zocidx != $nzori) {
				$zocidx = $nzori;
				$db->do("UPDATE esp_zones SET orientation = '$nzori' WHERE id = ".$zid);
			}
			my $nzdet = $FORM{"zonesdt".$zid} + 0;
			if ($zdelt != $nzdet) {
				$zdelt = $nzdet;
				$db->do("UPDATE esp_zones SET delta_t = '$nzdet' WHERE id = ".$zid);
			}
			my $nzvol = $FORM{"zonesvl".$zid} + 0;
			if (($zvol != $nzvol) && ($nzvol >= 0)) {
				$zvol = $nzvol;
				$db->do("UPDATE esp_zones SET volume = '$nzvol' WHERE id = ".$zid);
			}
			if ($whomas > 0) {
				if (($zmas) && ($whomas != $zid)) {
					$db->do("UPDATE esp_zones SET master = 0 WHERE id = ".$zid);
					$zmas = 0;
				}
				if (($zmas == 0) && ($whomas == $zid)) {
					$db->do("UPDATE esp_zones SET master = 1 WHERE id = ".$zid);		# define new master
					$zmas = 1;
				}
			}
		}
		if ($flags > 0) {
			my ($zllist, $zolist, $zdlist) = ("", "", "");
			for my $zoidx (0 .. $#zorient) {
				$zolist .= "<option value=\"$zoidx\" ".(($zoidx == $zocidx)?" selected=\"selected\"":"").">".$zorient[$zoidx]."</option>";
			}
			for my $zoidx (0 .. $#zlevels) {
				$zllist .= "<option value=\"$zoidx\" ".(($zoidx == $zlcidx)?" selected=\"selected\"":"").">".$zlevels[$zoidx]."</option>";
			}
			for my $zoidx (0 .. $#zdeltat) {
				$zdlist .= "<option value=\"".$zdeltat[$zoidx]."\" ".(($zdeltat[$zoidx] == $zdelt)?" selected=\"selected\"":"").">".$zdeltat[$zoidx]." C&deg;</option>";
			}
			$zonesl .= "<tr><td nowrap=\"nowrap\" width=\"30\">#".$zoneid.".</td><td><input name=\"zones".$zid."\" size=\"30\" maxlength=\"50\" value=\"$zdesc\" type=\"text\"></td><td align=center><select name=\"zonesla".$zid."\" style=\"width:70px;\">$zllist</select></td><td align=center><select name=\"zonesoa".$zid."\" style=\"width:60px;\">$zolist</select></td><td align=center><select name=\"zonesdt".$zid."\" style=\"width:60px;\">$zdlist</select></td><td><input name=\"zonesvl".$zid."\" size=\"4\" maxlength=\"5\" value=\"$zvol\" type=\"text\"></td><td align=center><input name=\"zonesms\" value=\"$zid\" type=\"radio\"".(($zmas)?" checked=\"checked\"":"")."></td><td><input name=\"zones".$zid."del\" value=\"Delete\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&groupid=".$grid."&zoneid=".$zid."&action=remove'\" type=\"button\"></td></tr>\n";
		}
		$zoneid ++;
	}
	undef $all;

	my $maschecked = ($ismasex)?"":"checked=\"checked\"";
	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--updmessage--/$updmsg/g;
		$inline =~ s/--zonesl--/$zonesl/g;
		$inline =~ s/--groupid--/$groupsl/g;
		$inline =~ s/--groupsel--/$grid/g;
		$inline =~ s/--maschecked--/$maschecked/g;
		$inline =~ s/--hidenew--/$hidenew/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# ESP Groups

if (($uimode eq "groups") && ($uismode eq "groups") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my $updmsg = "";

	if ($action eq "remove") {
		my $zoneid = $FORM{zoneid} + 0;
		if ($zoneid > 0) {
			$db->do("UPDATE esp_devices SET zone_id = 0 WHERE zone_id IN (SELECT id FROM esp_zones WHERE group_id = $zoneid) AND user_id = $clientid");	# unassign devices
			$db->do("DELETE FROM esp_zones WHERE group_id = $zoneid AND user_id = $clientid");				# delete areas
			$db->do("DELETE FROM esp_groups WHERE id = $zoneid AND user_id = $clientid");					# delete group
			$updmsg = "<tr><td colspan=6><br>Group deleted and all corresponding areas are unassigned</td></tr>\n";
		}
	}

	if ($action eq "save") {
		my $nzname = $FORM{zonesn};
		if ((length($nzname) < 6) && (length($nzname) > 0)) {
			$updmsg = "<tr><td colspan=6><br>Group name should have at least 6 alphanumeric characters</td></tr>\n";
			$nzname = "";
		} elsif (length($nzname) >= 6)  {
			my ($nzcnt) = $db->selectrow_array("SELECT COUNT(*) FROM esp_groups WHERE description = '$nzname' AND user_id = $clientid");
			if ($nzcnt > 0) {
				$updmsg = "<tr><td colspan=6><br>Group name must be unique. Two groups of same name cannot be created</td></tr>\n";
				$nzname = "";
			}
		}
		unless ($nzname eq "") {
			$db->do("INSERT INTO esp_groups VALUES (NULL, $clientid, NOW(), 1, '$nzname')");
		}
	}

	my $zonesl = "";
	my $zoneid = 1;
	my $all = $db->selectall_arrayref("SELECT id, flags, description FROM esp_groups WHERE user_id = $clientid ORDER BY id");
	foreach my $row (@$all) {
		my $zid = @$row[0];
		my $zonedef = "zones".$zid;
		my $flags = @$row[1];
		my $zdesc = @$row[2];
		if (($action eq "save") && ($FORM{$zonedef} ne ""))  {
			if ($FORM{$zonedef} ne $zdesc) {
				$db->do("UPDATE esp_groups SET updated = NOW(), description = '".$FORM{$zonedef}."' WHERE id = ".$zid);
				$zdesc = $FORM{$zonedef};
			}
		}
		if ($flags > 0) {
			$zonesl .= "<tr><td nowrap=\"nowrap\" width=\"30\">#".$zoneid.".</td><td><input name=\"zones".$zid."\" size=\"30\" maxlength=\"50\" value=\"$zdesc\" type=\"text\"></td><td><input name=\"zones".$zid."del\" value=\"Delete\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&zoneid=".$zid."&action=remove'\" type=\"button\"></td></tr>\n";
		}
		$zoneid ++;
	}
	undef $all;

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--updmessage--/$updmsg/g;
		$inline =~ s/--zonesl--/$zonesl/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--submode--/$uismode/g;
		$contents .= $inline."\n";
	}
	close(INF);
}

# ESP Devices

if (($uimode eq "devices") && ($uismode eq "devices") && ($uaccess >= $alevel{$uimode.$uismode})) {
	my %hiders = ("config", "0", "ispressure", "0", "isdamper", "0", "isafcpoe", "0", "isafcbatt", "0", "isstepper", "0", "isactuator", "0", "isactuatorA", "0", "isactuatorD", "0", "isactuatorS", "0", "isstatic", "0", "iswifi", "0", "islan", "0");
	my ($ldevices, $aplist, $zonelist, $devmodel) = ("", "", "", "");
	my $devsel = $FORM{"deviceid"} + 0;
	my @dmodels = ("Unknown", "AFC-Battery", "iLoVAC-3");
	my @stepsts = ("Not available", "Idle", "Moving", "Jammed", "Malfunction");
	my @powersts = ("Not available", "Offline", "Line mode", "Battery mode");
	my @checkbox = ("", ' checked="checked"');
	$FORM{"autovolt"} = ($FORM{"autovolt"})?1:0;
	$FORM{"ignorefb"} = ($FORM{"ignorefb"})?1:0;
	my $userfilt = "user_id = $clientid";
	if ($clientid == 7) {
		$userfilt = "7 = 7";		# superuser
	}

	my %zones = ("", "Not assigned");
	my $all = $db->selectall_arrayref("SELECT id, description FROM esp_zones WHERE $userfilt ORDER BY id");
	foreach my $row (@$all) {
		$zones{@$row[0]} = @$row[1];
	}
	undef $all;

	if (($devsel > 0) && ($action eq "unreg")) {
		my ($devmac) = $db->selectrow_array("SELECT macaddr FROM esp_devices WHERE id = $devsel");
		$db->do("INSERT INTO esp_dsettings VALUES (NULL, $devsel, 1, NOW(), 'clearpref', '$devmac')");
		sleep(5);
		$db->do("DELETE FROM esp_devices WHERE id = $devsel");
		$db->do("INSERT INTO esp_data VALUES (NULL, 0, $devsel, NOW(), 'lastmac', '$devmac')");
		$devsel = 0;
	}

	my %devmac = ();
	my %devdesc = ();
	my $devcnt = 0;
	my $all = $db->selectall_arrayref("SELECT id, flags, description, zone_id, macaddr, updated FROM esp_devices WHERE $userfilt ORDER BY description, macaddr");
	foreach my $row (@$all) {
		my $devid = @$row[0];
		my $flags = @$row[1];
		my $desc = @$row[2];
		my $zid = @$row[3];
		my $mac = @$row[4];
		my $upd = @$row[5];
		if ($flags > 0) {
			if ($devsel == 0) {
				$devsel = $devid;
			}
			my $ddesc = uc($mac);
			$ddesc =~ s/..\K(?=.)/:/g;
			$devmac{$devid} = $ddesc;
			$devdesc{$devid} = $desc;
			$devcnt ++;
		}
	}
	undef $all;

	my %values = ("stepper", "Not available", "stepstat", "0", "airtemp", "Not available", "roomtemp", "Not available", "roomhum", "Not available", "motions", "Not available", "wakeint", "Not available", "wlanip", "Not available", "lastconn", "Not available", "devcaps", "Not available", "devmodel", "0", "hwrev", "0", "fwrev", "0.0.0", "pressure", "Not available", "prestemp", "Not available");
	if (($devcnt) && ($devsel > 0)) {
		my $aall = $db->selectall_arrayref("SELECT * FROM (SELECT name_, value_ FROM esp_data WHERE device_id = $devsel AND updated BETWEEN DATE_SUB(NOW(), INTERVAL 3 DAY) AND NOW() ORDER BY id DESC) AS esp GROUP BY name_");	# get last device data
		foreach my $rrow (@$aall) {
			my $name = @$rrow[0];
			my $value = @$rrow[1];
			if ($name eq "stepper") {
				if ($value <= 0) {
					$value = "0% (fully closed)";
				} elsif ($value >= 100) {
					$value = "100% (fully open)";
				} else {
					$value .= "%";
				}
			} elsif (($name eq "airtemp") || ($name eq "roomtemp") || ($name eq "prestemp")) {
				$value .= "&deg;C";
			} elsif ($name eq "roomhum") {
				$value .= "%";
			} elsif ($name eq "wakeint") {
				$value .= " min";
			} elsif ($name eq "pressure") {
				$value .= " Pa";
			} elsif ($name eq "devmodel") {
				if ($value == 2) {		# AFC-POE
					$hiders{"isafcpoe"} = 1;
				} elsif ($value == 1) {		# AFC-Batt
					$hiders{"isafcbatt"} = 1;
					$hiders{"iswifi"} = 1;
				}
			} elsif ($name eq "devcaps") {
				my $temp = $value;
				$value = "";
				if ($temp & 1) {	# is HTU present
					$value .= (($value eq "")?"":"<br>")."Room Humidity & Temperature sensor (HTU i2c)";
				}
				if ($temp & 2) {	# is MLX present
					$value .= (($value eq "")?"":"<br>")."Room & Air Temperature sensor (MLX i2c)";
				}
				if ($temp & 4) {	# is DS present
					$value .= (($value eq "")?"":"<br>")."Room Temperature sensor (DS 1-wire)";
				}
				if ($temp & 8) {	# is stepper or actuator present
					$value .= (($value eq "")?"":"<br>")."Damper control";
					$hiders{"isdamper"} = 1;
				}
				if ($temp & 16) {	# is pressure present
					$value .= (($value eq "")?"":"<br>")."Pressure sensor";
					$hiders{"ispressure"} = 1;
				}
				if ($value eq "") {
					$value = "None";
				}
			}
			$values{$name} = $value;
		}
		undef $aall;
	}
	
	my %config = ("maxcurrent", "0", "maxsteps", "0", "stepmode", "0", "ledlevel", "2", "lanwifi", "0", "autovolt", "0", "ignorefb", "0", "lowvolt", "0", "highvolt", "10", "modbusip", "BELIMO.local:502", "devloc", "0", "lanip", "192.168.0.10", "lanmask", "255.255.255.0", "langw", "192.168.0.1", "landns", "192.168.0.1", "lanmode", "0", "conntime", "10", "devmode", "0", "upsmonip", "CEC-UPS-Monitor", "cooltres", "2", "heattres", "5", "presread", "0", "safeshut", "0", "microstep", "0", "damptype", "0", "compref", "0", "perwake", "0", "commint", "1440", "wakeint", "120", "blewint", "120", "bleaint", "100", "nickname", "", "apkey", "", "zone", "");
	my ($ccompref, $cperwake, $cdamptype, $csangle, $cmicrostep, $csafeshut, $cpresread, $cdevmode, $clanmode, $cdevloc, $clanwifi, $cledlevel, $cstepmode) = ("", "", "", "", "", "", "", "", "", "", "", "", "");
	my @lcompref = ("IP over BLE", "BLE over IP");
	my @llanwifi = ("LAN Ethernet", "WiFi Client");
	my @lperwake = ("No", "Yes");
	my @ldamptype = ("None", "Stepper motor");
	my @lstepmode = ("Auto", "Manual");
	my @lsafeshut = ("Do nothing", "Full open", "Full close");
	my @lpresread = ("Once after heat or cool cycle goes from OFF to ON", "While the cycle is ON based on wake up interval");
	my @ldevmode = ("Manual", "Schedule", "Air balance");
	my @lledlevel = ("Off", "Low", "Normal", "High");
	my @llanmode = ("DHCP", "Static IP");
	my @ldevloc = ("Supply", "Return");
	if ($values{devmodel} == 2) {
		$ldamptype[2] = "IP based actuator (modbus)";
		$ldamptype[3] = "Local actuator (analog)";
		$ldamptype[4] = "Local actuator + modbus server";
		$config{"commint"} = 120;				# 120 seconds for POE
		$ldevmode[3] = "Room to room temperature control";
	}
	my @lmicrostep = ("Full step", "1/2", "1/4");
	my $loopstart = 0;
	my $calibdone = 0;
	my $sflag = 1;			# default flag
	if ($devcnt) {
		if ($devsel > 0) {
			$hiders{"config"} = 1;
			my $all = $db->selectall_arrayref("SELECT flags, name_, value_ FROM esp_dsettings WHERE device_id = $devsel");
			foreach my $row (@$all) {
				if (@$row[0] > 0) {
					$config{@$row[1]} = @$row[2];
				}
			}
			undef $all;			
			if ($action eq "save") {
				if ($subact eq "move") {
					$config{"dampmpos"} = "-1";		# manually move damper
					delete $FORM{"autovolt"};
					delete $FORM{"ignorefb"};
				}
				if ($subact eq "looptest") {
					if ($config{"looptest"}) {
						$FORM{"looptest"} = "0";
					} else {
						$FORM{"looptest"} = "1";
						$loopstart ++;
					}
					$config{"looptest"} = "-1";
					delete $FORM{"autovolt"};
					delete $FORM{"ignorefb"};
				}
				if ($FORM{"schedule"} eq "yes") {
					my $newdate = $FORM{"sdatetime"};
					if ($newdate =~ m/(\d\d\d\d)\-(\d\d)\-(\d\d) (\d\d)\:(\d\d)/) {
						$newdate = $1.$2.$3.$4.$5."00";
						my $newang = $FORM{"sangle"} + 0;
						$db->do("INSERT INTO esp_schedule VALUES (NULL, $clientid, $devsel, $newdate, NOW(), 1, $newang)");
					}
				} else {
					foreach my $cfg (sort keys %config) {
						if (exists $FORM{$cfg}) {
							my $newval = $FORM{$cfg};
							if ($newval ne $config{$cfg}) {
								if (($cfg eq "lanip") || ($cfg eq "lanmask") || ($cfg eq "langw") || ($cfg eq "landns")) {
									if ($newval =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/) {	# check IP
										$newval = $1;
									} else {
										$newval = $config{$cfg};
									}
								}
								if (($cfg eq "lowvolt") || ($cfg eq "highvolt")) {
									if (($newval < 0) || ($newval > 10)) {
										$newval = $config{$cfg};
									}
								}
								if (($cfg eq "stepmode") && ($newval > 1)) {
									$sflag = 3;				# priority command
									if ($newval >= 4) {
										$newval = 1;
										$calibdone ++;
									}
								}
								$config{$cfg} = $newval;
								$db->do("DELETE FROM esp_dsettings WHERE device_id = $devsel AND name_ = '$cfg'");
								$db->do("INSERT esp_dsettings VALUES (NULL, $devsel, $sflag, NOW(), '$cfg', '$newval')");
								if ($cfg eq "nickname") {
									$db->do("UPDATE esp_devices SET updated = NOW(), description = '$newval' WHERE id = $devsel");
									$devdesc{$devsel} = $newval;
								} elsif ($cfg eq "zone") {
									$db->do("UPDATE esp_devices SET updated = NOW(), zone_id = '$newval' WHERE id = $devsel");
								}
								$sflag = 1;
							}
						}
					}
				}
			}
			my @aps = split(/\;\;/, $config{'aplist'});
			foreach my $ap (@aps) {				
				$aplist .= "<option value=\"$ap\"".(($ap eq $config{'wlanap'})?" selected=\"selected\"":"").">$ap</option>";
			}
			foreach my $zone (sort keys %zones) {
				$zonelist .= "<option value=\"$zone\"".(($zone eq $config{'zone'})?" selected=\"selected\"":"").">".$zones{$zone}."</option>";
			}
			for my $bp (0 .. $#lcompref) {
				$ccompref .= "<option value=\"$bp\"".(($bp eq $config{'compref'})?" selected=\"selected\"":"").">".$lcompref[$bp]."</option>";
			}
			for my $dt (0 .. $#ldamptype) {
				$cdamptype .= "<option value=\"$dt\"".(($dt eq $config{'damptype'})?" selected=\"selected\"":"").">".$ldamptype[$dt]."</option>";
			}
			for my $pw (0 .. $#lperwake) {
				$cperwake .= "<option value=\"$pw\"".(($pw eq $config{'perwake'})?" selected=\"selected\"":"").">".$lperwake[$pw]."</option>";
			}
			for my $pw (0 .. $#lmicrostep) {
				$cmicrostep .= "<option value=\"$pw\"".(($pw eq $config{'microstep'})?" selected=\"selected\"":"").">".$lmicrostep[$pw]."</option>";
			}
			for my $pw (0 .. $#lsafeshut) {
				$csafeshut .= "<option value=\"$pw\"".(($pw eq $config{'safeshut'})?" selected=\"selected\"":"").">".$lsafeshut[$pw]."</option>";
			}
			for my $pw (0 .. $#lledlevel) {
				$cledlevel .= "<option value=\"$pw\"".(($pw eq $config{'ledlevel'})?" selected=\"selected\"":"").">".$lledlevel[$pw]."</option>";
			}
			for my $pw (0 .. $#lstepmode) {
				$cstepmode .= "<option value=\"$pw\"".((($config{'stepmode'} == $pw) || ((($pw > 0) && ($config{'stepmode'} >= $pw))))?" selected=\"selected\"":"").">".$lstepmode[$pw]."</option>";
			}
			for my $pw (0 .. $#ldevmode) {
				$cdevmode .= "<option value=\"$pw\"".(($pw eq $config{'devmode'})?" selected=\"selected\"":"").">".$ldevmode[$pw]."</option>";
			}
			for my $pw (0 .. $#llanmode) {
				$clanmode .= "<option value=\"$pw\"".(($pw eq $config{'lanmode'})?" selected=\"selected\"":"").">".$llanmode[$pw]."</option>";
			}
			for my $pw (0 .. $#llanwifi) {
				$clanwifi .= "<option value=\"$pw\"".(($pw eq $config{'lanwifi'})?" selected=\"selected\"":"").">".$llanwifi[$pw]."</option>";
			}
			for my $pw (0 .. $#ldevloc) {
				$cdevloc .= "<option value=\"$pw\"".(($pw eq $config{'devloc'})?" selected=\"selected\"":"").">".$ldevloc[$pw]."</option>";
			}
			for my $pw (0 .. $#lpresread) {
				$cpresread .= "<option value=\"$pw\"".(($pw eq $config{'presread'})?" selected=\"selected\"":"").">".$lpresread[$pw]."</option>";
			}
			for my $sa (0 .. 20) {
				my $osa = floor($sa * 5);
				$csangle .= "<option value=\"$osa\">$osa".(($osa == 0)?"% (fully closed)":(($osa == 100)?"% (fully open)":"%"))."</option>";
			}
		}
		foreach my $dev (sort keys %devmac) {
			if ($devdesc{$dev} ne "") {
				$devmac{$dev} .= ": ".$devdesc{$dev};
			}
			$ldevices .= "<option value=\"$dev\"".(($dev == $devsel)?" selected=\"selected\"":"").">".$devmac{$dev}."</option>";
		}
	} else {
		$ldevices = "<option value=\"0\">-- None --</option>";
	}
	my $calibme = "";
	if ($config{damptype} == 0) {
		$hiders{"isdamper"} = 0;
	} elsif ($config{damptype} == 1) {
		$hiders{"isstepper"} = 1;
		if ($config{stepmode} >= 1) {			# manual mode
			my ($msgA, $msgB) = ("Calibrate", "Uncalibrated");
			if (($config{maxsteps}) && ($config{maxcurrent})) {
				$msgB = "Calibrated";
			}
			if ($config{stepmode} >= 2) {
				$msgA = "Stop";
				if ($config{stepmode} == 2) {
					$msgB = "Stop at full close";
				} elsif ($config{stepmode} == 3) {
					$msgB = "Stop at full open";
				}
			}
			if ($calibdone) {
				$msgB = "Calibration finished";
			}
			$calibme = "&nbsp;&nbsp;&nbsp;<input name=\"calibme\" value=\"$msgA\" type=\"button\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&deviceid=$devsel&action=save&stepmode=".($config{stepmode} + 1)."'\">&nbsp;&nbsp;&nbsp;$msgB";
		}
	} elsif ($config{damptype} > 1) {
		$hiders{"isactuator"} = 1;
		if ($config{damptype} == 2) {
			$hiders{"isactuatorD"} = 1;		# modbus
		} elsif ($config{damptype} == 3) {
			$hiders{"isactuatorA"} = 1;		# analog
		} elsif ($config{damptype} == 4) {
			$hiders{"isactuatorS"} = 1;		# server
			$hiders{"isactuatorA"} = 1;		# analog
		}
	}
	if ($values{"devmodel"} == 2) {
		if ($config{"lanwifi"} == 0) {			# lan
			$hiders{"islan"} = 1;
			if ($config{"lanmode"} == 1) {		# Static
				$hiders{"isstatic"} = 1;
			}
		} elsif ($config{"lanwifi"} == 1) {		# wifi
			$hiders{"iswifi"} = 1;
		}
	}
	
	my $looptest = "";
	if (($config{damptype} > 0) && ($values{"devmodel"} == 2)) {		# AFC-POE + stepper/actuator
		$looptest = "&nbsp;&nbsp;&nbsp;<input name=\"looptest\" value=\"".(($config{looptest})?"Stop loop test\" style=\"background-color: #faa;\"":"Start loop test")."\" type=\"button\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&deviceid=$devsel&action=save&subact=looptest'\">";
	}
	if ($loopstart) {
		$db->do("INSERT INTO esp_dsettings VALUES (NULL, $devsel, 1, NOW(), 'dampmpos', '77')");		# start testing
	}

	my $eventsl = "";
	my ($compA, $compB, $compfilt) = ("Show", "yes", "AND scheduled >= NOW()");
	if ($FORM{"completed"} eq "yes") {
		($compA, $compB, $compfilt) = ("Hide", "", "");
	}
	if (($devcnt) && ($devsel > 0)) {
		if ($action eq "sremove") {
			my $evid = $FORM{"eventid"};
			$db->do("DELETE FROM esp_schedule WHERE id = $evid AND device_id = $devsel AND $userfilt");
		}
		my @fdesc = ("", "Pending", "Completed", "Error");
		my @dprefix = ("&nbsp;", "&nbsp;", "&nbsp;&nbsp;", ":", "");
		my $aall = $db->selectall_arrayref("SELECT id, DATE_FORMAT(scheduled, '%Y-%m-%d %H:%i'), flags, angle FROM esp_schedule WHERE device_id = $devsel $compfilt ORDER BY scheduled");
		foreach my $rrow (@$aall) {
			my $rid = @$rrow[0];
			my $flags = @$rrow[2];
			my $angle = @$rrow[3];
			if ($flags > 0) {
				my $date = "<input type=\"text\" readonly=\"readonly\" value=\"".@$rrow[1]."\" size=\"16\">";
				if ($angle <= 0) {
					$angle = "0% (fully closed)";
				} elsif ($angle >= 100) {
					$angle = "100% (fully open)";
				} else {
					$angle .= "%";
				}
				$angle = "<select disabled=\"disabled\"><option selected=\"selected\">$angle</option><option>100% (fully open)</option></select>&nbsp;";
				$eventsl .= "<tr><td>$date</td><td>&nbsp;$angle</td>";
				if ($flags == 1) {
					$eventsl .= "<td><input name=\"ev".$rid."del\" value=\"Delete event\" onClick=\"window.location.href='./engine.pl?mode=$uimode&submode=$uismode&eventid=".$rid."&deviceid=".$devsel."&action=sremove'\" type=\"button\"></td>";
				} else {
					$eventsl .= "<td>Event completed</td>";
				}
				$eventsl .= "</tr>\n";
			}
		}
		undef $aall;
	}

	$devmodel = $dmodels[$values{'devmodel'}]." rev ".$values{'hwrev'}." firmware ".$values{'fwrev'};

	$headadd .= "<link href=\"./rome.min.css\" rel=\"stylesheet\" type=\"text/css\">\n
			<script src=\"./rome.min.js\"></script>\n";

	my $unregme = "&nbsp;";
	if ($devsel) {
		my $devnick = $config{'nickname'};
		$headadd .= <<EOF;
			<script language="JavaScript">
			function Unreg() {
				var answer = confirm ("Are you sure to unregister $devnick ?");
				if (answer) {
					window.location = './engine.pl?mode=$uimode&submode=$uismode&action=unreg&deviceid=$devsel';
				}
			}
			</script>
EOF
		$unregme = '<input name="reset" value="Unregister device" class="stdbutton" onclick="Unreg();" type="button">';
	}

	my $pagename = $selfpath.$uimode."_".$uismode.".html";
	my $hidenow = 0;
	my ($hidemeA, $hidemeB) = ("", "");
	if ($hiders{"config"} == 0) {
		($hidemeA, $hidemeB) = ('<!--', '-->');		# hide config part
	}
	open(INF,$pagename);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--calibme--/$calibme/g;
		$inline =~ s/--unregme--/$unregme/g;
		$inline =~ s/--looptest--/$looptest/g;
		$inline =~ s/--hidemeA--/$hidemeA/g;
		$inline =~ s/--hidemeB--/$hidemeB/g;
		$inline =~ s/--eventsl--/$eventsl/g;
		$inline =~ s/--deviceid--/$ldevices/g;
		$inline =~ s/--devsel--/$devsel/g;
		$inline =~ s/--devmodel--/$devmodel/g;
		$inline =~ s/--mode--/$uimode/g;
		$inline =~ s/--aplist--/$aplist/g;
		$inline =~ s/--zonelist--/$zonelist/g;
		$inline =~ s/--sangle--/$csangle/g;
		$inline =~ s/--presread--/$cpresread/g;
		$inline =~ s/--ledlevel--/$cledlevel/g;
		$inline =~ s/--safeshut--/$csafeshut/g;
		$inline =~ s/--lanmode--/$clanmode/g;
		$inline =~ s/--lanwifi--/$clanwifi/g;
		$inline =~ s/--devmode--/$cdevmode/g;
		$inline =~ s/--devloc--/$cdevloc/g;
		$inline =~ s/--microstep--/$cmicrostep/g;
		$inline =~ s/--stepmode--/$cstepmode/g;
		$inline =~ s/--apkey--/$config{'apkey'}/g;
		$inline =~ s/--nickname--/$config{'nickname'}/g;
		$inline =~ s/--upsmonip--/$config{'upsmonip'}/g;
		$inline =~ s/--modbusip--/$config{'modbusip'}/g;
		$inline =~ s/--commint--/$config{'commint'}/g;
		$inline =~ s/--conntime--/$config{'conntime'}/g;
		$inline =~ s/--wakeint--/$config{'wakeint'}/g;
		$inline =~ s/--cooltres--/$config{'cooltres'}/g;
		$inline =~ s/--heattres--/$config{'heattres'}/g;
		$inline =~ s/--highvolt--/$config{'highvolt'}/g;
		$inline =~ s/--lowvolt--/$config{'lowvolt'}/g;
		$inline =~ s/--lanip--/$config{'lanip'}/g;
		$inline =~ s/--langw--/$config{'langw'}/g;
		$inline =~ s/--landns--/$config{'landns'}/g;
		$inline =~ s/--lanmask--/$config{'lanmask'}/g;
		$inline =~ s/--stepper--/$values{'stepper'}/g;
		$inline =~ s/--stepstat--/$stepsts[$values{'stepstat'}]/g;
		$inline =~ s/--powerstat--/$powersts[$values{'powerstat'}]/g;
		$inline =~ s/--autovolt--/$checkbox[$config{'autovolt'}]/g;
		$inline =~ s/--ignorefb--/$checkbox[$config{'ignorefb'}]/g;
		$inline =~ s/--airtemp--/$values{'airtemp'}/g;
		$inline =~ s/--roomtemp--/$values{'roomtemp'}/g;
		$inline =~ s/--roomhum--/$values{'roomhum'}/g;
		$inline =~ s/--pressure--/$values{'pressure'}/g;
		$inline =~ s/--prestemp--/$values{'prestemp'}/g;
		$inline =~ s/--devcaps--/$values{'devcaps'}/g;
		$inline =~ s/--compref--/$ccompref/g;
		$inline =~ s/--damptype--/$cdamptype/g;
		$inline =~ s/--compA--/$compA/g;
		$inline =~ s/--compB--/$compB/g;
		$inline =~ s/--perwake--/$cperwake/g;
		$inline =~ s/--motions--/$values{'motions'}/g;
		$inline =~ s/--wakeint--/$values{'wakeint'}/g;
		$inline =~ s/--wlanap--/$config{'wlanap'}/g;
		$inline =~ s/--wlanip--/$values{'wlanip'}/g;
		$inline =~ s/--lastconn--/$values{'lastconn'}/g;
		$inline =~ s/--submode--/$uismode/g;
		if ($inline =~ m/^\-\=([a-zA-Z0-9]*)\=\-/) {
			my $hidename = $1;
			if ($hidenow) {
				$hidenow = 0;
			} else {
				unless ($hiders{$hidename}) {
					$hidenow ++;
				}
			}
			$inline =~ s/^\-\=([a-zA-Z0-9]*)\=\-//;
		}
		unless ($hidenow) {
			$contents .= $inline."\n";
		}
	}
	close(INF);
}

# logout from system

if (($uimode eq "logout") && ($uismode eq "logout") && ($uaccess >= $alevel{$uimode.$uismode})) {
	($password, $uimode, $uismode) = ("", "", "", "");
	$exitstatus = 2;
}

# login page

if (($uimode eq "") && ($uismode eq "")) {
	my $fut_time = gmtime(time() - 3600)." GMT";  # make time expired
	my $cookie = $cooknames[0]."=; path=/; expires=$fut_time;";
	print "Set-Cookie: " . $cookie . "\n";
	$cookie = $cooknames[2]."=; path=/; expires=$fut_time;";
	print "Set-Cookie: " . $cookie . "\n";

	if ($airdamper eq "yes") {
		my $logmsg = "";
		if ($exitstatus == 1) {					# wrong login/password
			$logmsg = "Wrong credentials! Please retry<br><br>or <a href=\"./engine.pl?airdamper=yes&mode=password&submode=recovery&ulogin=$username\" class=\"wnavi\">click here</a> for password recovery";
			$cookie = $cooknames[1]."=; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";
		} elsif ($exitstatus == 2) {				# logout
			$logmsg = "Good bye.";
		} elsif ($exitstatus == 3) {				# tips
			$logmsg = "Please use your registration email to login";
		} elsif ($exitstatus == 7) {				# DB error
			$logmsg = "Cannon connect Database. Please try later";
		}
		my $savelogin = ($saveduser ne "")?" checked":"";
		$username = ($saveduser ne "")?$saveduser:"";
		print "Content-type: text/html\n\n";
		open(INF,$eloginweb);
		while (<INF>) {
			my $inline = $_;
			chomp ($inline);
			$inline =~ s/--logmessage--/$logmsg/g;
			$inline =~ s/--username--/$username/g;
			$inline =~ s/--password--/$password/g;
			$inline =~ s/--savelogin--/$savelogin/g;
			$inline =~ s/--version--/$version/g;
			print $inline."\n";
		}
		close(INF);
	} else {
		my $logmsg = "";
		if ($exitstatus == 0) {					# opened by mistake?
		} elsif ($exitstatus == 1) {				# wrong login/password
			$logmsg = "Wrong credentials! Please retry<br><br>or <a href=\"./engine.pl?mode=password&submode=recovery&ulogin=$username\" class=\"wnavi\">click here</a> for customer password recovery";
			$cookie = $cooknames[1]."=; path=/; expires=$fut_time;";
			print "Set-Cookie: " . $cookie . "\n";
		} elsif ($exitstatus == 2) {				# logout
			$logmsg = "Good bye.";
		} elsif ($exitstatus == 3) {				# tips
			if ($servname =~ m/^commercial/) {
				$logmsg = "Please use HomeID to login";
			} else {
				$logmsg = "Please use HomeID to login<br><br>Cello Forced Air Damper Control customers <a href=\"./engine.pl?airdamper=yes\" class=\"wnavi\">click here</a>";
			}
			$logmsg = "<a href=\"./engine.pl?airdamper=yes&mode=password&submode=recovery&ulogin=$username\" class=\"wnavi\">Click here</a> for password recovery";
		} elsif ($exitstatus == 7) {				# DB error
			$logmsg = "Cannon connect Database. Please try later";
		}
		my $savelogin = ($saveduser ne "")?" checked":"";
		$username = ($saveduser ne "")?$saveduser:"";
		print "Content-type: text/html\n\n";
		open(INF,$loginweb);
		while (<INF>) {
			my $inline = $_;
			chomp ($inline);
			$inline =~ s/--logmessage--/$logmsg/g;
			$inline =~ s/--username--/$username/g;
			$inline =~ s/--password--/$password/g;
			$inline =~ s/--savelogin--/$savelogin/g;
			$inline =~ s/--version--/$version/g;
			print $inline."\n";
		}
		close(INF);
	}
	$db->disconnect();
	exit;
}

# print out page

if ($onestage) {
	print "Content-type: text/plain\n\n";
	print $message."\n";
} else {
	$mainmenu .= "<td align=right width=100% style=\"color:white; font: bold 13px Arial,Helvetica,sans-serif; text-align:right; padding-right:20px;\">$ulogin</td>\n";
	my ($datetime) = $db->selectrow_array("SELECT DATE_FORMAT(UTC_TIMESTAMP(), '%b %e, %Y  %H:%i:%S')");
	{
		my ($isdst) = $db->selectrow_array("SELECT value_ FROM user_params WHERE user_id = $clientid AND name_ = 'dst'");
		$isdst += 0;
		my @tzconv = ("-1200", "-1100", "-1000", "-0900", "-0800", "-0800", "-0700", "-0700", "-0700", "-0600", "-0600", "-0600", "-0600", "-0500", "-0500", "-0500", "-0430", "-0400", "-0400", "-0400", "-0400", "-0400", "-0330", "-0300", "-0300", "-0300", "-0300", "-0300", "-0300", "-0200", "-0100", "-0100", "0000", "0000", "0000", "0000", "0100", "0100", "0100", "0100", "0100", "0100", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0300", "0300", "0300", "0300", "0300", "0330", "0400", "0400", "0400", "0400", "0400", "0400", "0430", "0500", "0500", "0500", "0530", "0530", "0545", "0600", "0600", "0600", "0630", "0700", "0700", "0800", "0800", "0800", "0800", "0800", "0800", "0900", "0900", "0900", "0930", "0930", "1000", "1000", "1000", "1000", "1000", "1000", "1100", "1100", "1200", "1200", "1200", "1200", "1300", "1300", "1400");
		my $ttzone = $tzconv[$utimezone];
		my $tmzone = ($utimezone * 2) + $isdst;
		my @tzzone = split(//, sprintf("%+05d", $ttzone));
		my $tzzzone = $tzzone[0].$tzzone[1].$tzzone[2].":".$tzzone[3].$tzzone[4];		# determine and set current timezone
		my $tzsecoff = 0;
		my $tzdstoff = tzoff($tmzone);
		{
			my $hroff = $tzzone[1].$tzzone[2];
			my $minoff = $tzzone[3].$tzzone[4];
			$tzsecoff = (($tzzone[0] eq "+")?"":"-").(($hroff * 3600) + ($minoff * 60));
			$tzsecoff += $tzdstoff;							# fix DST
		}
		my ($cursec,$curmin,$curhour,$curday,$curmon,$curyear) = localtime(mktime((gmtime)[0..5]) + $tzsecoff);
		$curmon ++;
		$curday = sprintf("%02d",$curday);
		$curmon = sprintf("%02d",$curmon);
		$cursec = sprintf("%02d",$cursec);
		$curmin = sprintf("%02d",$curmin);
		$curhour = sprintf("%02d",$curhour);
		$curyear += 1900;
		my $curdatetime = $smonths[$curmon]." $curday, $curyear $curhour:$curmin:$cursec";
		$datetime = $curdatetime."&nbsp;&nbsp;GMT".$tzzone[0].$tzzone[1].$tzzone[2].":".$tzzone[3].$tzzone[4].(($tzdstoff > 0)?" DST":"");
	}
	print "Content-type: text/html\n\n";
	if (($clientid >= 0) && ($uimode eq "reports") && ($uismode eq "graph")) {
		$templateweb = $selfpath."rtemplate.html";
	}
	open(INF, $templateweb);
	while (<INF>) {
		my $inline = $_;
		chomp ($inline);
		$inline =~ s/--top1class--/$top1class/g;
		$inline =~ s/--mainmenu--/$mainmenu/g;
		$inline =~ s/--submenu--/$submenu/g;
		$inline =~ s/--contents--/$contents/g;
		$inline =~ s/--title--/$pagetitle/g;
		$inline =~ s/--atitle--/$pageatitle/g;
		$inline =~ s/--datetime--/$datetime/g;
		$inline =~ s/--version--/$version/g;
		$inline =~ s/--debug--/$debug/g;
		$inline =~ s/--bodyadd--/$bodyadd/g;
		$inline =~ s/--bottomadd--/$bottomadd/g;
		$inline =~ s/--headadd--/$headadd/g;
		print $inline."\n";
	}
	close(INF);
}

# save session data

if ($SDATA{save}) {
	my $ssd = "";
	$SDATA{save} = 0;
	foreach my $sid (keys %SDATA) {
		$ssd .= "$sid==".$SDATA{$sid}.";;";
	}
	if (exists $SDATA{sid}) {
		$db->do("UPDATE session_data SET data = '$ssd' WHERE id = ".$SDATA{sid});
	} else {
		$db->do("INSERT INTO session_data VALUES (NULL, $sessid, '$ssd')");
	}
}

# get values for HQ report

sub GetTemps {
	my $zid = $_[0];
	my $did = $_[1];
	my $stamp = $_[2];
	my $housedb = $_[3];
	my $siz = $_[4];
	my ($zoneT, $zoneH, $zoneS) = ("", "", "");
	if ($stamp > 0) {
		my $bets = $stamp - 3600;
		{
			my ($sec, $min, $hour, $day, $month, $year) = (localtime($bets))[0,1,2,3,4,5];
			$bets = sprintf("%04d%02d%02d%02d%02d%02d", ($year + 1900), ($month + 1), $day, $hour, $min, $sec);
		}
		my $tots = $stamp + 3600;
		{
			my ($sec, $min, $hour, $day, $month, $year) = (localtime($tots))[0,1,2,3,4,5];
			$tots = sprintf("%04d%02d%02d%02d%02d%02d", ($year + 1900), ($month + 1), $day, $hour, $min, $sec);
		}
		if (($zid > 2) && ($did ne "") && ($stamp > 0)) {
#			my ($zdiff, $zTemp, $zHum) = $db->selectrow_array("SELECT ABS(UNIX_TIMESTAMP(updated) - $stamp) AS sdiff, temperature, humidity FROM $housedb.sensorsdyn WHERE UNIX_TIMESTAMP(updated) BETWEEN $bets AND $tots AND device_id IN ($did) AND temperature IS NOT NULL AND temperature != 0 ORDER BY sdiff LIMIT 1");
			my ($zdiff, $zTemp, $zHum) = $db->selectrow_array("SELECT ABS(UNIX_TIMESTAMP(updated) - $stamp) AS sdiff, temperature, humidity FROM $housedb.sensorsdyn WHERE updated BETWEEN $bets AND $tots AND device_id IN ($did) AND temperature IS NOT NULL AND temperature != 0 ORDER BY sdiff LIMIT 1");
			$zoneT = $zTemp;
			$zoneH = $zHum;
		}
		if ($siz ne "") {
			my @sinops = split(/\,/, $siz);
			my $scnt = 0;
			foreach my $sinid (@sinops) {
				$zoneS = 0;
#				my ($zdiff, $sT) = $db->selectrow_array("SELECT ABS(UNIX_TIMESTAMP(updated) - $stamp) AS sdiff, value_ FROM $housedb.cots_data WHERE UNIX_TIMESTAMP(updated) BETWEEN $bets AND $tots AND name_ = \"$sinid-temperature\" AND value_ IS NOT NULL AND value_ != 0 ORDER BY sdiff LIMIT 1");
				my ($zdiff, $sT) = $db->selectrow_array("SELECT ABS(UNIX_TIMESTAMP(updated) - $stamp) AS sdiff, value_ FROM $housedb.cots_data WHERE updated BETWEEN $bets AND $tots AND name_ = \"$sinid-temperature\" AND value_ IS NOT NULL AND value_ != 0 ORDER BY sdiff LIMIT 1");
				if ($sT > 0) {
					$scnt ++;
					$zoneS += $sT;
				}
				if ($scnt > 0) {
					$zoneS = sprintf("%.3f", $zoneS / $scnt);
				} else {
					$zoneS = "";
				}
			}
		}
	}
	return $zoneT, $zoneH, $zoneS;
}

# func for backwards sort

sub backwards { $b cmp $a }

# func to check and fix date

sub fixdate {
	my $fday = $_[0];
	if ($fday <= 0) {
		$fday = 1;
	}
	my $fmon = $_[1];
	if ((($fmon == 1) || ($fmon == 3) || ($fmon == 5) || ($fmon == 7) || ($fmon == 8) || ($fmon == 10) || ($fmon == 12)) && ($fday > 31)) {
		$fday = 31;
	}
	if ((($fmon == 4) || ($fmon == 6) || ($fmon == 9) || ($fmon == 11)) && ($fday > 30)) {
		$fday = 30;
	}
	if ($fmon == 2) {
		my $fyear = $_[2];
		if (0 == $fyear % 4 and 0 != $fyear % 100 or 0 == $fyear % 400) {
			if ($fday > 29) {
				$fday = 29;
			}
		} else {
			if ($fday > 28) {
				$fday = 28;
			}
		}
	}
	return $fday;
}

# run bg process if needed

if ($forkme) {
	my $pid = fork();
	warn "Fork failed: $!" if !defined $pid;
	if ($pid == 0) {
		open STDIN, "</dev/null";
		open STDOUT, ">/dev/null";
		open STDERR, ">/dev/null";
		system('/var/www/cloud/forkserver.pl &');
		exit;
	}
}

# timezones DST fix

sub tzoff {
	my $tzone = $_[0];
	my $dsret = 0;
	if ($tzone & 1) {		# DST is not needed if zero
		my @dstinfo = ("0", "0", "0", "60:3:0:2:2:11:0:1:2", "60:4:0:1:2:10:0:5:2", "60:3:0:2:2:11:0:1:2", "0", "60:4:0:1:2:10:0:5:2", "60:3:0:2:2:11:0:1:2", "0", "60:3:0:2:2:11:0:1:2", "60:4:0:1:2:10:0:5:2", "0", "0", "60:3:0:2:2:11:0:1:2", "60:3:0:2:2:11:0:1:2", "0", "60:10:6:1:23:3:6:3:23", "60:3:0:2:2:11:0:1:2", "60:10:6:3:23:2:6:3:23", "0", "60:10:6:2:23:3:6:2:23", "60:3:0:2:2:11:0:1:2", "60:10:6:3:23:2:6:3:23", "0", "0", "60:3:6:5:22:10:6:4:23", "60:10:0:1:2:3:0:2:2", "0", "0", "60:3:0:5:0:10:0:5:1", "0", "60:3:0:5:2:10:0:5:3", "0", "60:3:0:5:1:10:0:5:2", "0", "60:3:0:5:2:10:0:5:3", "60:3:0:5:2:10:0:5:3", "60:3:0:5:2:10:0:5:3", "60:3:0:5:2:10:0:5:3", "0", "60:9:0:1:2:4:0:1:2", "60:3:4:5:23:10:5:5:1", "60:3:0:5:3:10:0:5:4", "60:3:6:5:23:10:6:4:23", "0", "60:4:4:1:23:10:4:5:23", "60:3:0:5:2:10:0:5:3", "0", "60:3:0:5:3:10:0:5:4", "60:3:0:5:3:10:0:5:4", "60:3:5:5:2:10:0:5:2", "0", "0", "0", "0", "0", "0", "0", "60:3:6:3:23:9:1:3:23", "0", "60:3:0:5:4:10:0:5:5", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "0", "60:10:0:1:2:4:0:1:3", "0", "0", "60:10:0:1:2:4:0:1:3", "0", "60:10:0:1:2:4:0:1:3", "0", "0", "0", "0", "0", "60:9:0:5:2:4:0:1:3", "0", "60:10:0:4:2:1:0:3:3", "0", "60:9:0:5:0:4:0:1:1", "0");
		my @daysinm = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
		my @dstdet = split(/\:/, $dstinfo[floor($tzone / 2)]);
		if ($dstdet[0] > 0) {	# DST used in zone
			my @gmnow = gmtime(time);
			my ($dstwf, $dstwt) = $db->selectrow_array("SELECT DAYOFWEEK('".sprintf("%04d-%02d-%02d", $gmnow[5] + 1900, $dstdet[1], 1)."'), DAYOFWEEK('".sprintf("%04d-%02d-%02d", $gmnow[5] + 1900, $dstdet[5], 1)."')");
			$dstwf --;
			$dstwt --;
			my ($dstdf, $dstdt) = (0, 0);
			my $weekcnt = 1;
			for my $ii (1 .. $daysinm[$dstdet[1]]) {
				if ($dstdet[2] == $dstwf) {
					$dstdf = $ii;
					if ($weekcnt == $dstdet[3]) {
						last;				# day found!
					} else {
						$weekcnt ++;
					}
				}
				$dstwf ++;
				if ($dstwf == 7) {
					$dstwf = 0;
				}
			}
			$weekcnt = 1;
			for my $ii (1 .. $daysinm[$dstdet[5]]) {
				if ($dstdet[6] == $dstwt) {
					$dstdt = $ii;
					if ($weekcnt == $dstdet[7]) {
						last;				# day found!
					} else {
						$weekcnt ++;
					}
				}
				$dstwt ++;
				if ($dstwt == 7) {
					$dstwt = 0;
				}
			}
			my $dstcur = time();
			my $dsttf = timelocal(0, 0, $dstdet[4], $dstdf, $dstdet[1] - 1, $gmnow[5]);
			my $dsttt = timelocal(0, 0, $dstdet[8], $dstdt, $dstdet[5] - 1, $gmnow[5]);
			if (($dsttf < $dsttt) && (($dstcur > $dsttf) && ($dstcur < $dsttt))) {					# its DST now
				$dsret = $dstdet[0] * 60;
			} elsif (($dsttf > $dsttt) && (($dstcur < $dsttf) && ($dstcur > $dsttt))) {
				$dsret = $dstdet[0] * 60;
			}
		}
	}
	return $dsret;
}

# fix timestamp

sub gettstamp {
	my $tzsecoff = gettzsecoff();
	my ($cursec,$curmin,$curhour,$curday,$curmon,$curyear) = localtime(mktime((gmtime)[0..5]) + $tzsecoff);
	$curmon ++;
	$curday = sprintf("%02d",$curday);
	$curmon = sprintf("%02d",$curmon);
	$cursec = sprintf("%02d",$cursec);
	$curmin = sprintf("%02d",$curmin);
	$curhour = sprintf("%02d",$curhour);
	$curyear += 1900;
	my $tstamp = "$curyear-$curmon-$curday $curhour:$curmin:$cursec";
	return $tstamp;
}

sub getoffset {
	my $tzsecoff = gettzsecoff();
	my $offset = (($tzsecoff < 0)?"-":"").sprintf("%02d%02d", floor((abs($tzsecoff) + 60) / (3600)), (abs($tzsecoff) / 60) % 60);
	return $offset;
}

sub gettzsecoff {
	my ($isdst) = $db->selectrow_array("SELECT value_ FROM user_params WHERE user_id = $clientid AND name_ = 'dst'");
	my ($timezone) = $db->selectrow_array("SELECT timezone FROM users WHERE id = $clientid");
	$isdst += 0;
	my @tzconv = ("-1200", "-1100", "-1000", "-0900", "-0800", "-0800", "-0700", "-0700", "-0700", "-0600", "-0600", "-0600", "-0600", "-0500", "-0500", "-0500", "-0430", "-0400", "-0400", "-0400", "-0400", "-0400", "-0330", "-0300", "-0300", "-0300", "-0300", "-0300", "-0300", "-0200", "-0100", "-0100", "0000", "0000", "0000", "0000", "0100", "0100", "0100", "0100", "0100", "0100", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0200", "0300", "0300", "0300", "0300", "0300", "0330", "0400", "0400", "0400", "0400", "0400", "0400", "0430", "0500", "0500", "0500", "0530", "0530", "0545", "0600", "0600", "0600", "0630", "0700", "0700", "0800", "0800", "0800", "0800", "0800", "0800", "0900", "0900", "0900", "0930", "0930", "1000", "1000", "1000", "1000", "1000", "1000", "1100", "1100", "1200", "1200", "1200", "1200", "1300", "1300", "1400");
	my $ttzone = $tzconv[$timezone];
	my $tmzone = ($timezone * 2) + $isdst;
	my @tzzone = split(//, sprintf("%+05d", $ttzone));
	my $tzzzone = $tzzone[0].$tzzone[1].$tzzone[2].":".$tzzone[3].$tzzone[4];		# determine and set current timezone
	my $tzminoff = 0;
	my $tzdstoff = tzoff($tmzone);
	my $hroff = $tzzone[1].$tzzone[2];
	my $minoff = $tzzone[3].$tzzone[4];
	my $tzsecoff = (($tzzone[0] eq "+")?"":"-").(($hroff * 3600) + ($minoff * 60));
	$tzsecoff += $tzdstoff;
	return $tzsecoff;
}

sub dateLocal {			# local time from 2020-05-28 15:17:05 -like stamp
	my $lstamp = "N/A";
	my $stamp = $_[0];
	my $tzsec = $_[1];
	my $dform = $_[2];
	if ($stamp =~ m/^(\d\d\d\d)\-(\d\d)\-(\d\d) (\d\d)\:(\d\d)\:(\d\d)$/) {
		my ($cursec, $curmin, $curhour, $curday, $curmon, $curyear, $curdow) = localtime(mktime($6, $5, $4, $3, ($2 - 1), ($1 - 1900)) + $tzsec);
		if ($dform == 0) {
			$lstamp = sprintf("%04d-%02d-%02d %02d:%02d:%02d", ($curyear + 1900), ($curmon + 1), $curday, $curhour, $curmin, $cursec);
		} elsif ($dform == 1) {
			$lstamp = sprintf("%s %d, %04d %02d:%02d:%02d", $smonths[$curmon + 1], $curday, ($curyear + 1900), $curhour, $curmin, $cursec);
		} elsif ($dform == 5) {
			$lstamp = sprintf("%s, %s %d, %04d %02d:%02d:%02d", $sdayofweek[$curdow], $smonths[$curmon + 1], $curday, ($curyear + 1900), $curhour, $curmin, $cursec);
		} elsif ($dform == 3) {
			$lstamp = sprintf("%s %d, %02d:%02d:%02d", $smonths[$curmon + 1], $curday, $curhour, $curmin, $cursec);
		} elsif ($dform == 4) {
			$lstamp = sprintf("%s %d, %02d:%02d", $smonths[$curmon + 1], $curday, $curhour, $curmin);
		} elsif ($dform == 6) {
			$lstamp = sprintf("%s %d, %04d %02d:%02d", $smonths[$curmon + 1], $curday, ($curyear + 1900), $curhour, $curmin);
		} elsif ($dform == 7) {
			$lstamp = sprintf("%02d:%02d", $curhour, $curmin);
		} elsif ($dform == 8) {
			$lstamp = sprintf("%04d.%02d.%02d %02d:%02d:%02d", ($curyear + 1900), ($curmon + 1), $curday, $curhour, $curmin, $cursec);
		}
	} elsif ($dform == 2) {
		my ($cursec, $curmin, $curhour, $curday, $curmon, $curyear) = localtime(mktime((gmtime($stamp))[0..5]) + $tzsec);
		$lstamp = sprintf("%02d:%02d:%02d", $curhour, $curmin, $cursec);
	}
	return $lstamp;
}

# exit

$db->disconnect();
exit;
7;
