#!/bin/sh


rc=/lib/rcscripts/sh/files.sh
. $rc || error "Failed to source '$rc'"

rc=/usr/html/axis-cgi/lib/sh-helpers.sh
. $rc || error "Failed to source '$rc'"

ETHTOOL_CMD=$(PATH=/usr/sbin:/sbin:$PATH command -v ethtool 2>/dev/null || :)

CENSOR_PASSWD_EXPR='s/([[:blank:]]*passwd[[:blank:]]*=[[:blank:]]*\[)[[:print:]]*([[:blank:]]*\])/\1 "******" \2/g;
	s/(^.*[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd][[:blank:]]*=).*$/\1 "*****"/g;
	s/(^.*[Pp][Aa][Ss][Ss][[:blank:]]*=).*$/\1 "*****"/g;
	s/(^Passphrase[[:blank:]]*=).*$/\1 "*****"/g;
	s/(^Key[1234][[:blank:]]*=).*$/\1 "*****"/g'


REGEX_PROPERTY_NUMBER='^\(<([0-9]+)>,\)$'

cleanup_tmp_var() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
		error "Wrong number of arguments: cleanup_tmp_var <variable>"

	local dirty_var=$2

	dirty_var=${dirty_var#\(}
	dirty_var=${dirty_var%,\)}
	eval $1=\$dirty_var
}

cleanup_single_quotes() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
		error "Wrong number of arguments: cleanup_single_quotes <variable>"

	local dirty_var=$2

	dirty_var=${dirty_var#*\'}
	dirty_var=${dirty_var%\'*}
	eval $1=\$dirty_var
}

cleanup_property() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
		error "Wrong number of arguments: cleanup_property <variable>"

	local dirty_var=$2

	dirty_var=${dirty_var#*<}
	dirty_var=${dirty_var%>*)}
	eval $1=\$dirty_var
}


dir_empty() {
	[ $# -eq 1 ] && [ "$1" ] || error "dir_empty: missing argument"
	[ -d $1 ] || error "Directory '$1' not found"

	local f ff

	ff=$1/*
	for f in $ff; do
		[ "$f" = "$ff" ] || return 1
		break
	done
}

output_aeconf() {
	[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
		error "output_aeconf: missing argument(s)"

	title $1

	if dir_empty $2; then
		echo "Empty directory $2"
	else
		local f

		for f in $(find $2 -type f); do
			echo $f

			if [ "${f##*.}" = xml ]; then
				sed -e 's/>/>\n/g' $f
			else
				sed -re '1,2d' -e "$CENSOR_PASSWD_EXPR" $f
			fi

			echo
		done
	fi
}

title Server Report Start
printf "Product: "
parhandclient --nocgi get Brand.ProdFullName - RAW 2>&1 || :

if serno=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.ReadSerno 2>&1); then
	cleanup_single_quotes serno "$serno"
	echo "Serial No: $serno"
else
	echo "Failed to get serial number $serno"
fi

f=/sys/devices/soc0/soc_id
[ ! -f $f ] || [ ! -r $f ] || {
	printf "Processor Serial Number: "
	cat $f
}

title /usr/share/axis-release/variables
cat /usr/share/axis-release/variables

title Inactive Firmware Version
if fw_status=$(gdbus call -y -d com.axis.FirmwareManager1 -o /com/axis/FirmwareManager1 \
		-m com.axis.FirmwareManager1.Status 2>&1); then
	if [ -z "${fw_status##*"InactiveFirmwareVersion"*}" ]; then
		echo "$fw_status" |
		sed -re 's/^.*InactiveFirmwareVersion.{4}([[:alnum:]._+-]+).*$/Firmware Rollback: \1/'
	else
		echo "No rollback version available"
	fi
else
	echo "Failed to get firmware status '$fw_status'"
fi

title System information
uname -mrsv 2>&1
printf "Bootloader: "
bootversion 2>&1 || :

f=/etc/release
title $f
if [ -f $f ] && [ -r $f ]; then
	cat $f
else
	echo "Warning: file $f not found or not readable"
fi

h=hasamall_info
! command -v $h >/dev/null 2>&1 || {
	title Board Information
	$h -i BoardID ProductionDate 2>&1 || :
}

! command -v camera_info >/dev/null || {
	title Camera Information
	camera_info --all 2>&1 || :
}

title uptime
uptime 2>&1


title Lifetime Statistics
_usage_=-1
_bootcount_=-1
_rebootcount_=-1

if grep -Eq "^[^[:blank:]]+[[:blank:]]+(/usr)?/lib/persistent[[:blank:]]+" /proc/mounts; then
	gdbus_cmd="gdbus call -y -d com.axis.UsageStatistics1 -o /com/axis/UsageStatistics1 \
	-m org.freedesktop.DBus.Properties.Get com.axis.UsageStatistics1"
	x=$($gdbus_cmd UsageTime | sed -E "s/$REGEX_PROPERTY_NUMBER/\1/") &&
		[ "$x" ] && _usage_=$x || echo "Failed to get UsageTime"
	x=$($gdbus_cmd BootCount | sed -E "s/$REGEX_PROPERTY_NUMBER/\1/") &&
		[ "$x" ] && _bootcount_=$x || echo "Failed to get BootCount"
	x=$($gdbus_cmd RebootCount | sed -E "s/$REGEX_PROPERTY_NUMBER/\1/") &&
		[ "$x" ] && _rebootcount_=$x || echo "Failed to get RebootCount"
fi

if [ $_usage_ -eq -1 ]; then
	echo "Total Uptime: Not supported"
else
	echo "Total Uptime: $(($_usage_ / 86400)) days"
fi

if [ $_bootcount_ -eq -1 ]; then
	echo "Boot-up Counter: Not supported"
else
	echo "Boot-up Counter: $_bootcount_"
fi

if [ $_rebootcount_ -eq -1 ]; then
	echo "Restart Counter: Not supported"
else
	echo "Restart Counter: $_rebootcount_"
fi


title Firmware History
tail -50 /lib/persistent/var/lib/system/system-status/fwhistory 2>&1 || :

print_peak_memory_info() {
	local system= services= addons= acap=
	local memorydir=/sys/fs/cgroup/memory
	local memoryfile=memory.max_usage_in_bytes
	local servicesfile=$memorydir/system.slice/$memoryfile
	local addonsfile=$memorydir/extension.slice/$memoryfile
	local acapfile=$memorydir/extension.slice/extension-addon.slice/$memoryfile

	[ ! -r $memorydir/$memoryfile ] || read system <$memorydir/$memoryfile
	[ ! -r $servicesfile ] || read services <$servicesfile
	[ ! -r $addonsfile ] || read addons <$addonsfile
	[ ! -r $acapfile ] || read acap <$acapfile
	echo "System-Peak:   "$system
	echo "Services-Peak: "$services
	echo "Addons-Peak:   "$addons
	echo "Acaps-Peak:    "$acap
}

if grep -q -w '^memory' /proc/cgroups; then
	[ -d /sys/fs/cgroup/memory ] || error "Memory accounting mount not available"
	title Memory Usage
	print_peak_memory_info
fi

print_card_info() {
	local name= date= type= manfid= oemid= serial= fwrev= hwrev= cid= csd=
	local scr= var

	[ $# -eq 1 ] && [ "$1" ] || error "print_card_info: missing argument"
	[ -d $1 ] || error "Directory '$1' not found"

	for var in name date type manfid oemid serial fwrev hwrev cid csd scr; do
		[ ! -r $1/device/$var ] || read $var <$1/device/$var
	done

	printf "name:  %6s date:   %s\n" ${name:-NA} ${date:-NA}
	printf "type:  %6s manfid: %s\n" ${type:-NA} ${manfid:-NA}
	printf "oemid: %6s serial: %s\n" ${oemid:-NA} ${serial:-NA}
	printf "fwrev: %6s hwrev:  %s\n" ${fwrev:-NA} ${hwrev:-NA}
	printf "cid: %s\n" ${cid:-NA}
	printf "csd: %s\n" ${csd:-NA}
	printf "scr: %s\n" ${scr:-NA}
}

# Check if product has an SD Card slot, and print card info if it does.
[ ! -e /sys/class/mmc_host/mmc0 ] || {
	max_slots=4
	i=0

	title "SD card slot 0"

	sd_base=/sys/block/mmcblk
	if [ ! -d $sd_base$i ]; then
		echo "No SD-card present"
	else
		print_card_info $sd_base$i
	fi
	i=$(($i + 1))

	while [ $i -lt $max_slots ]; do
		[ ! -d $sd_base$i ] || {
			title "SD card slot $i"
			print_card_info $sd_base$i
		}
		i=$(($i + 1))
	done
}

title System log

for lf in /var/log/*; do
	lfn=${lf##*/}
	case $lfn in
		info.log*|warning.log*|error.log*|critical.log*|segfault.log*)
			[ -r $lf ] || {
				echo "Warning: $lf is not readable!"
				continue
			}
			cat $lf || echo "Warning: Failed to read $lf"
			;
	esac
done | sort

psln=/usr/local/syslog.log
[ ! -f $psln ] || {
	title Persistent system log
	sort $psln*
}

title Kernel log
klog

secklog=/usr/bin/secondary-klog
[ ! -x $secklog ] || {
	title Secondary chip kernel log
	$secklog 2>&1 || :
}

pstoreconsole=/sys/fs/pstore/console-ramoops-0
[ ! -r $pstoreconsole ] || {
	title Previous kernel log
	date -r $pstoreconsole
	cat $pstoreconsole
}

ramoops=/sys/fs/pstore/dmesg-ramoops-0
[ ! -r $ramoops ] || {
	title Kernel crash log
	date -r $ramoops
	cat $ramoops
}

title Access log
! log=$(cat /var/log/auth.log* 2>/dev/null) || [ -z "$log" ] ||
	echo "$log" | sort
echo

parhandclient --nocgi --maskpasswords getgroup root - NAMEVALUESECTIONS |
	sed -re "$CENSOR_PASSWD_EXPR"

f=/etc/straightenimage/straightenimage.conf
if [ -f $f ] && [ -r $f ]; then
	title Stream adjustments
	echo "[Straighten Image]"
	cat $f 2>&1 || :
fi

# Check if the product has remotecameracontrol and print connections if it does
remote_d=/etc/remotecameracontrol
[ ! -d $remote_d ] || {
	title Remote camera control connections
	f=$remote_d/connections.conf
	[ ! -r $f ] || sed -re "s/^(Password=).*/\1*****/" $f
}

title Installed certificates
if x=$(gdbus call -y -d com.axis.PolicyKitCert -o /com/axis/PolicyKitCert \
		-m com.axis.PolicyKitCert.ListInstalledCerts 2>&1); then
	x=$(echo "$x" | sed -e "s/^(\[(//;s/)\],)\$//;s/), (/\n/g" |
		sed -e "s/^'\(.*\)', '\(.*\)', '\(.*\)'\$/\1^\2^\3/")
	restoreIFS=$IFS
	IFS="
"
	topidlen=0
	topcnlen=0
	for i in $x; do
		id=${i%%^*}
		idlen=${#id}
		rest=${i#*^}
		cn=${rest%%^*}
		cnlen=${#cn}
		[ $idlen -lt $topidlen ] || topidlen=$idlen
		[ $cnlen -lt $topcnlen ] || topcnlen=$cnlen
	done
	for i in $x; do
		id=${i%%^*}
		rest=${i#*^}
		cn=${rest%%^*}
		fn=${rest#*^}
		printf "%-${topidlen}s  %-${topcnlen}s  %s\n" "$id" "$cn" "$fn"
	done
	IFS=$restoreIFS
else
	echo "Failed to get list of certificates $x"
fi

title Snapshot of the current caching streams

list=$(gdbus call -y -d com.axis.Streamer -o /com/axis/Streamer/Cache \
	-m com.axis.Streamer.Cache.GetStreams)
list=${list#*[}
list=${list%]*}
echo "$list" | sed -e 's#, #\n#g'


title Snapshot of number of current outgoing media streams
num_of_clients=$(gdbus call -y -d com.axis.Streamer -o /com/axis/Streamer \
	-m org.freedesktop.DBus.Properties.Get com.axis.Streamer \
	CurrentNumClients 2>&1 || :)
cleanup_property num_of_clients "$num_of_clients"
echo $num_of_clients

# Arguments: <service> <object>
print_managed_dbus_objects() {
	[ $# -eq 2 ] && [ "$1" ]  && [ "$2" ] ||
		error "print_managed_dbus_objects: missing argument"

	busctl call --json=pretty $1 $2 \
		org.freedesktop.DBus.ObjectManager GetManagedObjects |
		grep -v "\"type\" : "
}

title Snapshot of current outgoing HTTP streams
print_managed_dbus_objects com.axis.Streamer \
	/com/axis/Streamer/HTTP/StreamProperties

title Snapshot of current outgoing RTP streams
print_managed_dbus_objects com.axis.Streamer \
	/com/axis/Streamer/RTP/StreamProperties

onvif_media_conf=/etc/ws/onvif/media/media.conf
[ ! -r $onvif_media_conf ] || {
	title Onvif Media
	cat $onvif_media_conf || :
}

title Snapshot of the current processes
ps T

title Snapshot of the current cpu utilization
top -b -n 1

title systemctl list-units
systemctl list-units --full --no-legend --no-pager

# First argument is the interface to get info from
print_interface_info() {
	[ $# -eq 1 ] && [ "$1" ] || error "print_interface_info: missing argument"

	local reg_dump

	title Settings for $1
	$ETHTOOL_CMD $1 2>&1 || :

	printf "\nDriver information:\n"
	$ETHTOOL_CMD -i $1 2>&1 || :

	printf "\nDevice statistics:\n"
	$ETHTOOL_CMD -S $1 2>&1 || :

	printf "\nRegister dump:\n"
	# Use policykit to execute ethtool
	if reg_dump=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.ExecuteEthtool d $1 2>&1); then
		cleanup_single_quotes reg_dump "$reg_dump"
		echo "$reg_dump" | sed -e 's#\\n$##;s#\\n#\n#g'
	else
		echo "Failed to call com.axis.PolicyKitSystem.ExecuteEthtool $reg_dump"
	fi
}

ifaces=$(ls /sys/class/net | grep -v lo)
for i in $ifaces; do
	print_interface_info $i
done

ip_cmd=/sbin/ip
if [ -x $ip_cmd ]; then
	show_addr_cmd="$ip_cmd address show"
	show_maddr_cmd="$ip_cmd maddress"
	show_route_cmd="$ip_cmd route show"
	show_route6_cmd="$ip_cmd -6 route show"
else
	show_addr_cmd='/sbin/ifconfig -a'
	show_route_cmd='/sbin/route -n'
fi

title Network configuration
$show_addr_cmd

title Routing table
$show_route_cmd

# Check if the product has SFP, and print status if it does.
! command -v sfp_status >/dev/null 2>&1 || {
	title SFP
	sfp_status 2>&1 || echo "Warning! sfp_status returned error $?."
}

title IPv6 routing table
$show_route6_cmd
[ -z "$show_maddr_cmd" ] || {
	title Multicast groups
	$show_maddr_cmd
}

title Network connections
# Use policykit to get netstat information
# netstat -nap -W 2>&1 || :
if netstat_info=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.GetActiveNetworkInfo all 2>&1); then
	cleanup_single_quotes netstat_info "$netstat_info"
	echo "$netstat_info" | sed -e 's#\\n$##;s#\\n#\n#g'
else
	echo "Failed to get netstat info $netstat_info"
fi

title Connection list
QUERY_STRING="generate_header=no" /usr/html/axis-cgi/connection_list.cgi 2>&1 || :

title Network statistics
cat /proc/net/dev

WLAN_STATION_DEV=

# Look for a network interface device which supports WLAN station.
# Sets WLAN_STATION_DEV to the name of the first such device found, if any.
find_wlan_station_dev() {
	local dbus_net dev_list dev_obj_base dev dev_name intro

	dbus_net='-y -d com.axis.Net1 -o /com/axis/Net1'
	dev_list=$(gdbus call $dbus_net -m com.axis.Net1.GetDevices 2>/dev/null || :)
	dev_obj_base=/com/axis/Net1/Device/

	# Loop through devices
	while :; do
		case $dev_list in
			*$dev_obj_base*)
				# Advance to next device in list
				dev_list=${dev_list#*$dev_obj_base}
				;
			*)
				# No more devices in list
				break
				;
		esac

		# Isolate current device
		dev=${dev_list%%$dev_obj_base*}

		# Check if current device is WLAN aka "Type 3"
		case $dev in
			*"'Type': <uint32 3>"*)
				;
			*)
				continue
				;
		esac

		# Introspect device object and look for WLAN station interface
		intro=$(gdbus introspect $dbus_net/Device/${dev%%\'*} 2>/dev/null || :)
		case $intro in
			*com.axis.Net1.Device.WLAN.Station*)
				# Interface found, set WLAN_STATION_DEV
				dev_name=${dev#*\'Name\': <\'}
				dev_name=${dev_name%%\'*}
				WLAN_STATION_DEV=$dev_name
				break
				;
			*)
				;
		esac
	done
}

find_wlan_station_dev
[ -z "$WLAN_STATION_DEV" ] || {
	title Wireless network configuration

	iface=$WLAN_STATION_DEV
	ip_msg="ip utility not found"
	if [ -x $ip_cmd ] && ip_msg=$($ip_cmd -s link show $iface 2>&1); then
		iw_cmd=/usr/sbin/iw
		if [ -x $iw_cmd ]; then
			title iw $iface link
			$iw_cmd $iface link 2>&1 || :

			title iw $iface scan
			# We need to escape %, newline and tab characters in
			# the output of iw, as well as remove the parantheses
			# and single quotes introduced by gdbus.
			gdbus_response=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.ExecuteIw $iface scan 2>&1)
			gdbus_response=${gdbus_response#(\'}
			gdbus_response=${gdbus_response%\',)}
			echo "$gdbus_response" | sed -e "s|\\\n|\n|g" -e "s|\\\t|\t|g" -e "s|%|%%|g"

		else
			echo "Error: iw utility not found"
		fi
	else
		# If ip utility is not able to show the link data, then some-
		# thing may be wrong with the device. For example, the
		# wireless-chip may be detached from the socket.
		echo "Error accessing wireless device $iface settings," \
			"your product may be damaged."
		echo "Error: $ip_msg"
	fi
}

WLAN_AP_DEV=

# Look for a network interface device which supports WLAN access point.
# Sets WLAN_AP_DEV to the name of the first such device found, if any.
find_wlan_ap_dev() {
	local dbus_net dev_list dev_obj_base dev dev_name intro

	dbus_net='-y -d com.axis.Net1 -o /com/axis/Net1'
	dev_list=$(gdbus call $dbus_net -m com.axis.Net1.GetDevices 2>/dev/null || :)
	dev_obj_base=/com/axis/Net1/Device/

	# Loop through devices
	while :; do
		case $dev_list in
			*$dev_obj_base*)
				# Advance to next device in list
				dev_list=${dev_list#*$dev_obj_base}
				;
			*)
				# No more devices in list
				break
				;
		esac

		# Isolate current device
		dev=${dev_list%%$dev_obj_base*}

		# Check if current device is WLAN aka "Type 3"
		case $dev in
			*"'Type': <uint32 3>"*)
				;
			*)
				continue
				;
		esac

		# Introspect device object and look for WLAN access point interface
		intro=$(gdbus introspect $dbus_net/Device/${dev%%\'*} 2>/dev/null || :)
		case $intro in
			*com.axis.Net1.Device.WLAN.AccessPoint*)
				# Interface found, set WLAN_AP_DEV
				dev_name=${dev#*\'Name\': <\'}
				dev_name=${dev_name%%\'*}
				WLAN_AP_DEV=$dev_name
				break
				;
			*)
				;
		esac
	done
}

find_wlan_ap_dev
[ -z "$WLAN_AP_DEV" ] || {
	title Wireless network configuration

	iface=$WLAN_AP_DEV
	iw_cmd=/usr/sbin/iw
	if [ -x $iw_cmd ]; then
		$iw_cmd list || :
		$iw_cmd dev $iface info || :
	else
		echo "Error: iw utility not found"
	fi
}

poe_script=poe_status.sh
! exists $poe_script || $poe_script 2>&1 || :


title /proc/meminfo
cat /proc/meminfo

title /proc/slabinfo
# Use policykit to get slabinfo
# cat /proc/slabinfo
if slabinfo=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.GetSlabinfo 2>&1); then
	cleanup_single_quotes slabinfo "$slabinfo"
	echo "$slabinfo" | sed -e 's#\\n$##;s#\\n#\n#g'
else
	echo "Failed to get slabinfo $slabinfo"
fi

title vmstatus
vmstatus.sh 2>/dev/null

title Filesystems status
df -h 2>&1

title /proc/mounts
cat /proc/mounts

blk_pattern="/dev/sd[a-z]"
blk_devices=$(echo $blk_pattern)
if [ "$blk_devices" != "$blk_pattern" ]; then
	title Disk devices
	ls -l $blk_devices || :

	ifs_bak=$IFS
	IFS=" "

	for dev in $blk_devices; do
		title Disk status $dev

		# Use policykit to execute smartctl
		if smart_status=$(gdbus call -y -d com.axis.PolicyKitSystem -o /com/axis/PolicyKitSystem -m com.axis.PolicyKitSystem.ExecuteSmartctl all $dev 2>&1); then
			cleanup_single_quotes smart_status "$smart_status"
			echo "$smart_status" | sed -e 's/\\n/\n/g' -e 's/\\t/\t/g'
		else
			echo "Failed to call com.axis.PolicyKitSystem.ExecuteSmartctl $smart_status"
		fi
	done

    IFS=$ifs_bak
fi

title Uploaded applications
/usr/sbin/application_report.sh 2>&1 ||
	echo "Failed to execute /usr/sbin/application_report.sh"

# Check if addon-report is available before calling
cmd=addon-report
! command -v $cmd >/dev/null || $cmd || :


# Check if the device has temperature controller
! command -v temperature_status.sh >/dev/null 2>&1 || {
	temp_ctrl_dbus_name=com.axis.TemperatureController
	temp_ctrl_dbus_obj=/com/axis/TemperatureController
	temp_ctrl_dbus_interface=com.axis.TemperatureController
	gdbus_call="gdbus call -y -d $temp_ctrl_dbus_name -o $temp_ctrl_dbus_obj -m"

	nbr_temp_sensors=$($gdbus_call $temp_ctrl_dbus_interface.GetNbrOfTemperatureSensors 2>&1) &&
		cleanup_tmp_var nbr_temp_sensors "$nbr_temp_sensors" || {
			echo "Unable to retrieve number of temperature sensors: $nbr_temp_sensors"
			nbr_temp_sensors=0
		}

	nbr_humidity_sensors=$($gdbus_call $temp_ctrl_dbus_interface.GetNbrOfHumiditySensors 2>&1) &&
		cleanup_tmp_var nbr_humidity_sensors "$nbr_humidity_sensors" || {
			echo "Unable to retrieve number of humidity sensors: $nbr_humidity_sensors"
			nbr_humidity_sensors=0
		}

	nbr_fans=$($gdbus_call $temp_ctrl_dbus_interface.GetNbrOfFans 2>&1) &&
		cleanup_tmp_var nbr_fans "$nbr_fans" || {
			echo "Unable to retrieve number of fans: $nbr_fans"
			nbr_fans=0
		}

	nbr_heaters=$($gdbus_call $temp_ctrl_dbus_interface.GetNbrOfHeaters 2>&1) &&
		cleanup_tmp_var nbr_heaters "$nbr_heaters" || {
			echo "Unable to retrieve number of heaters: $nbr_heaters"
			nbr_heaters=0
		}

	[ $nbr_temp_sensors -lt 1 ] || {
		title Temperatures
		tmp=$(temperature_status.sh 2>&1) && echo "$tmp" ||
			echo "Error reading temperature status: $tmp"
	}

	[ $nbr_humidity_sensors -lt 1 ] || {
		title Humidity
		tmp=$(humidity_status.sh 2>&1) && echo "$tmp" ||
			echo "Error reading humidity status: $tmp"
	}

	[ $nbr_fans -lt 1 ] || {
		title Fan status
		tmp=$(fan_status.sh 2>&1) && echo "$tmp" ||
			echo "Error reading fan status: $tmp"
	}

	[ $nbr_heaters -lt 1 ] || {
		title Heater status
		tmp=$(heater_status.sh 2>&1) && echo "$tmp" ||
			echo "Error reading fan status: $tmp"
	}
}
if ssn=$(gdbus call -y -d com.axis.ImageControl \
	-o /com/axis/ImageControl -m org.freedesktop.DBus.Properties.Get \
	com.axis.ImageControl SensorSerialNumber 2>/dev/null); then
	cleanup_single_quotes ssn "$ssn"
	[ -z "$ssn" ] || {
		title Sensor information
		echo "SN: $ssn"
	}
fi
! command -v light_status.sh >/dev/null 2>&1 || {
	title Light Control
	light_status.sh 2>/dev/null
}

cvs=$(gdbus call -y -d com.axis.CamViewSetup.Setup \
	-o /com/axis/CamViewSetup/Setup \
	-m com.axis.CamViewSetup.Setup.GetCapabilities 1 2>/dev/null || :)

case $cvs in
	*\(3,\ true\)*) ### viewareasetup/absoluteroll.cgi supported, e.g. Koi M3067/68 ###
		if angle=$(gdbus call -y -d com.axis.CamViewSetup.Setup \
			-o /com/axis/CamViewSetup/Setup \
			-m com.axis.CamViewSetup.Setup.GetStatus 1 2>&1); then
				title Digital Roll
				angle=${angle%,[[:blank:]]\[*}
				echo "Angle: ${angle##*,[[:blank:]]}"
		else
			echo "Failed ($angle) to get com.axis.CamViewSetup.Setup.GetStatus"
		fi
		;
	*\(2,\ true\)*) ### viewareasetup/roll.cgi supported, e.g. Serena Q3615/17 ###
		title Pan-Tilt-Rotate PTR
		ptr_state=/lib/persistent/var/lib/ptr_ctrl/ptr_ctrl.state
		cat $ptr_state 2>&1 || echo "Failed to print "
		;
	*)
		# Not supported, do not print anything
		;
esac
for mcu in MC9S08MP16 MC9S08QG8; do
	! systemctl is-enabled $(echo $mcu | tr A-Z a-z).service >/dev/null 2>&1 ||
	[ $(mcu_accessory_status.sh $mcu connected) -lt 1 ] || {
		title $(mcu_accessory_status.sh $mcu title)
		mcu_accessory_status.sh $mcu status
	}
done

! command -v camblock_status.sh >/dev/null 2>&1 || {
	title Camblock-Hardware
	camblock_status.sh 2>/dev/null
}

! command -v camblock_eeprom_status.sh >/dev/null 2>&1 || {
	title Camblock-EEPROM-Hardware
	camblock_eeprom_status.sh 2>/dev/null
}

[ ! -x /usr/libexec/tempctrl-setup ] && [ ! -f /usr/share/tempctrl/conf ] && [ ! -f /lib/rcscripts/sh/rc-tempctrl.sh ] || {
	title MCU status
	if [ ! -r /usr/share/tempctrl/conf ] || [ ! -r /lib/rcscripts/sh/rc-tempctrl.sh ]; then
		echo "Unable to read MCU files"
	else
		{ . /usr/share/tempctrl/conf || { echo "Sourcing /usr/share/tempctrl/conf failed"; ! :; }; } &&
		{ . /lib/rcscripts/sh/rc-tempctrl.sh || { echo "Sourcing /lib/rcscripts/sh/rc-tempctrl.sh failed"; ! :; }; } &&
		{ do_status || { echo "Unable to fetch information"; ! :; }; }
	fi
}

d=/etc/actionengine/user/1
output_aeconf "User defined action templates (user)" $d/actiontemplates
output_aeconf "User defined recipient templates (user)" $d/recipienttemplates
output_aeconf "Action rules (user)" $d/rules
output_aeconf "Action configurations (user)" $d/configurations
output_aeconf "Recipients (user)" $d/recipients

d=/etc/actionengine/legacy/1
output_aeconf "User defined action templates (legacy)" $d/actiontemplates
output_aeconf "User defined recipient templates (legacy)" $d/recipienttemplates
output_aeconf "Action rules (legacy)" $d/rules
output_aeconf "Action configurations (legacy)" $d/configurations
output_aeconf "Recipients (legacy)" $d/recipients

d=/etc/scheduledevents/schedules
if dir_empty $d; then
	echo "Empty directory $d"
else
	title Schedules
	for f in $(find $d -type f); do
		echo $f
		sed '/^$/d' $f
		echo
	done
fi
ssr=/usr/sbin/storage_serverreport.sh
[ ! -x $ssr ] || $ssr 2>&1 || :

rsr=/usr/sbin/recording_serverreport.sh
[ ! -x $rsr ] || $rsr 2>&1 || :

! command -v panopsis_calib_client >/dev/null 2>&1 || {
	title Panopsis Calibration Status
	panopsis_calib_client -e get_calibration_information ||
		echo "Unable to fetch information."
}

titan_fw_v=/lib/firmware/Titan_Drive_APP.version
[ ! -r $titan_fw_v ] || {
	title Titan intelligent BLDC motor firmware
	cat $titan_fw_v 2>/dev/null ||
		echo "Failed to read firmware version."
}

title PTZ Framework
psr=ptzaurus_server_report
! exists $psr || $psr || :
[ ! -x /usr/sbin/evanalyticsd ] || {
	title Embedded Video Analytics Configuration
	eva_conf=/etc/evanalyticsd/detectors.conf
	[ ! -f $eva_conf ] || cat $eva_conf 2>/dev/null ||
		echo "Failed to read $eva_conf."
}
analytic_conf=/usr/local/packages/vmd/localdata/*config.json
if ls $analytic_conf >/dev/null 2>&; then
	title Video Analytics Configuration - vmd
	for file in $analytic_conf; do
		cat $file 2>/dev/null || echo "Failed to read $file."
	done
fi
analytic_conf=/usr/local/packages/motionguard/localdata/*config.json
if ls $analytic_conf >/dev/null 2>&; then
	title Video Analytics Configuration - motionguard
	for file in $analytic_conf; do
		cat $file 2>/dev/null || echo "Failed to read $file."
	done
fi
analytic_conf=/usr/local/packages/fenceguard/localdata/*config.json
if ls $analytic_conf >/dev/null 2>&; then
	title Video Analytics Configuration - fenceguard
	for file in $analytic_conf; do
		cat $file 2>/dev/null || echo "Failed to read $file."
	done
fi
analytic_conf=/usr/local/packages/loiteringguard/localdata/*config.json
if ls $analytic_conf >/dev/null 2>&; then
	title Video Analytics Configuration - loiteringguard
	for file in $analytic_conf; do
		cat $file 2>/dev/null || echo "Failed to read $file."
	done
fi
! command -v tourrecd >/dev/null 2>&1 || {
	title Recorded tours
	rectour_conf=/etc/recordedtour/recordedtour.conf
	sed -re '/^([^=]+=[[:blank:]]*$|(id|camera)[[:blank:]]*=)/d' $rectour_conf |
		sed -e '/^\[/{N;/\n$/d}' 2>/dev/null ||
		echo "Failed to parse $rectour_conf."
}
shi_bin=/usr/sbin/sensorhead_info
[ ! -x $shi_bin ] || {
	title Connected heads
	$shi_bin -report || echo "Unable to fetch information."
}

ptz_counter_script=ptz_counter_report.sh
! exists $ptz_counter_script || $ptz_counter_script || :

wiper_counter_script=wiper_counter_report.sh
! exists $wiper_counter_script || $wiper_counter_script || :

print_memzone_config() {
	local nois_prefix=NumberOfImageSources=
	local lef_file=/etc/sysconfig/le-framework.conf
	local image_sources i mzd_conf

	image_sources=$(grep ^$nois_prefix $lef_file 2>/dev/null) || {
		echo "Failed to read ${nois_prefix%=} from $lef_file"
		return 1
	}

	image_sources=${image_sources#$nois_prefix}

	case $image_sources in
		''|*[!0-9]*)
			echo "Failed parsing ${nois_prefix%=}: Not a value."
			return 1
			;
	esac

	i=0
	while [ $i -lt $image_sources ]; do
		mzd_conf=/etc/memoryzoned/ptz_memoryzone_z${i}_zone.conf
		[ ! -f $mzd_conf ] || cat $mzd_conf 2>/dev/null ||
			echo "Failed to read $mzd_conf."
		i=$(($i + 1))
	done
}

[ ! -x /usr/html/axis-cgi/memoryzones/add.cgi ] || {
	title Memory Zone Configuration
	print_memzone_config
}

title Analytics status

d=/opt/axis-video-scene-provider/usr/misc/log
ff=$d/*_status
for f in $ff; do
	[ $f = "$ff" ] || {
		echo $f
		if [ -r $f ]; then
			cat $f
		else
			echo "Permission denied"
		fi
	}
done

title Hardware Monitoring
systool -c hwmon -v 2>/dev/null || :

title Industrial I/O
systool -b iio -v 2>/dev/null || :

[ ! -f /etc/panorama/panorama-data.conf ] || {
	title Panorama Configuration
	cat /etc/panorama/panorama-data.conf

	print_calibration() {
		[ $# -eq 2 ] && [ "$1" ] && [ "$2" ] ||
			error "print_calibration: Invalid argument(s)"
		title $2
		local calb_list file file_name
		calb_list=$1/ffc_channel_*
		for file in $calb_list; do
			[ ! -e $file ] || {
				file_name=${file##*/}
				echo $file_name
				cat $file 2>/dev/null || echo Failed to read $file.
				echo
			}
		done
	}

	print_calibration /lib/persistent/usr/share/sensor_analysis "Default Calibration"

	print_calibration /lib/persistent/usr/share/stitching "User Specific Calibration"
}

title Axis MCU
systool -c axis-mcu -v 2>/dev/null || :

radar_conf_script=radar_configuration_report.sh
! exists $radar_conf_script || $radar_conf_script || :

regionalsettings_conf=/etc/regionalsettings/regionalsettings.conf
[ ! -r $regionalsettings_conf ] || {
	title Regional settings
	cat $regionalsettings_conf || :
}

lensselection_conf=/etc/lenses/lenses.conf
[ ! -r $lensselection_conf ] || {
	title Lensselection
	cat $lensselection_conf || :
}

remoteptz_conf=/etc/ptzmath/remoteptz.conf
ptz_support=$(parhandclient --nocgi --nolog get \
	Properties.PTZ.PTZ - RAW 2>/dev/null || echo no)
[ ! -r $remoteptz_conf ] || [ $ptz_support != yes ] || {
	title Remoteptz
	cat $remoteptz_conf || :
}

dad_conf=/usr/local/packages/dad/localdata/dad.conf
[ ! -r $dad_conf ] || {
	title Directional Audio Detection
	gpio_audioring_detected=/sys/devices/platform/gpiomap/audioring_detected/value
	[ ! -r $gpio_audioring_detected ] || {
		gpio_value=$(cat $gpio_audioring_detected)
		printf "Audio ring detected: "
		if [ $gpio_value -eq 1 ]; then
			echo yes
		else
		  echo no
		fi
		echo
	}
	audioring_status=/sys/class/spi_master/spi1/spi1.0/status
	[ ! -r $audioring_status ] || {
		printf "Audio ring status: "
		cat $audioring_status
		echo
	}
	cat $dad_conf || :
}

sipd_report_cmd=sipd_serverreport
! exists $sipd_report_cmd || $sipd_report_cmd || :

for script in sr_diskinit.sh \
	sr_diskmanager.sh \
	sr_networksharemanager.sh \
	sr_poemanager.sh \
	sr_devicemanager.sh \
	sr_buzzerd.sh \
	sr_systemmanager.sh; do
	! exists /usr/sbin/$script || /usr/sbin/$script || :
done

nvmem=/sys/bus/nvmem/devices/artpec-efuse0/nvmem
[ ! -e $nvmem ] || {
	title FUSE status
	hexdump -ve '/4 "0x%08x "' $nvmem || :
	echo
}

title Custom Firmware Certificates
if x=$(gdbus call -y -d  com.axis.CustomFirmwareCertificates1 \
	   -o /com/axis/CustomFirmwareCertificates1 \
	   -m com.axis.CustomFirmwareCertificates1.List 2>&1); then
	x=${x#*\[}
	x=${x%\]*}
	echo "$x" | sed -re "s/,[[:blank:]]+/\n/g" | tr -d "'"
else
	echo "Failed to get list of certificates $x"
fi

print_file() {
	[ ! -f $1 ] || [ ! -r $1 ] || {
		echo "### $1 ###"
		echo
		cat $1
		echo
	}
}

fwupgrade_d=/mnt/flash/.fwupgradelogs
[ ! -d $fwupgrade_d ] || {
	title Failed FW Upgrade Logs
	for f in $fwupgrade_d/*; do
		print_file $f
	done
	for f in $fwupgrade_d/varlog/*; do
		print_file $f
	done
}

for f in /usr/share/serverreport.d/*; do
	[ -L $f ] || [ ! -f $f ] || [ ! -r $f ] || [ ! -x $f ] || $f || :
	echo
done
title Server Report End