From fc41bb00e2cd293f3e17976cc46a39527231978f Mon Sep 17 00:00:00 2001 From: Jack Naisbett Date: Fri, 14 Jan 2022 09:36:00 +0000 Subject: [PATCH 01/33] Version bump --- README.md | 4 ++-- connmon.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f368b7b..0b33981 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/91af8db9cd354643a8ef6a7117be90fb)](https://www.codacy.com/app/jackyaz/connmon?utm_source=github.com&utm_medium=referral&utm_content=jackyaz/connmon&utm_campaign=Badge_Grade) ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) -## v3.0.2 -### Updated on 2022-01-06 +## v3.0.3 +### Updated on 2022-01-14 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. diff --git a/connmon.sh b/connmon.sh index f2db048..8560e8c 100644 --- a/connmon.sh +++ b/connmon.sh @@ -28,8 +28,8 @@ ### Start of script variables ### readonly SCRIPT_NAME="connmon" -readonly SCRIPT_VERSION="v3.0.2" -SCRIPT_BRANCH="master" +readonly SCRIPT_VERSION="v3.0.3" +SCRIPT_BRANCH="develop" SCRIPT_REPO="https://jackyaz.io/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME.d" readonly SCRIPT_WEBPAGE_DIR="$(readlink /www/user)" From dac81c9bd17a48f6479811881d7e55a72580b485 Mon Sep 17 00:00:00 2001 From: Jack Naisbett Date: Fri, 14 Jan 2022 09:36:45 +0000 Subject: [PATCH 02/33] Assume https if port is 443 --- connmon.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/connmon.sh b/connmon.sh index 8560e8c..8729a00 100644 --- a/connmon.sh +++ b/connmon.sh @@ -2001,6 +2001,10 @@ SendToInfluxDB(){ NOTIFICATIONS_INFLUXDB_PORT="$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_PORT)" NOTIFICATIONS_INFLUXDB_DB="$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_DB)" NOTIFICATIONS_INFLUXDB_VERSION="$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_VERSION)" + NOTIFICATIONS_INFLUXDB_PROTO="http" + if [ "$NOTIFICATIONS_INFLUXDB_PORT" = "443" ]; then + NOTIFICATIONS_INFLUXDB_PROTO="https" + fi if [ "$NOTIFICATIONS_INFLUXDB_VERSION" = "1.8" ]; then INFLUX_AUTHHEADER="$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_USERNAME):$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_PASSWORD)" @@ -2008,7 +2012,7 @@ SendToInfluxDB(){ INFLUX_AUTHHEADER="$(Conf_Parameters check NOTIFICATIONS_INFLUXDB_APITOKEN)" fi - /usr/sbin/curl -fsL --retry 3 --connect-timeout 15 --output /dev/null -XPOST "http://$NOTIFICATIONS_INFLUXDB_HOST:$NOTIFICATIONS_INFLUXDB_PORT/api/v2/write?bucket=$NOTIFICATIONS_INFLUXDB_DB&precision=s" \ + /usr/sbin/curl -fsL --retry 3 --connect-timeout 15 --output /dev/null -XPOST "$NOTIFICATIONS_INFLUXDB_PROTO://$NOTIFICATIONS_INFLUXDB_HOST:$NOTIFICATIONS_INFLUXDB_PORT/api/v2/write?bucket=$NOTIFICATIONS_INFLUXDB_DB&precision=s" \ --header "Authorization: Token $INFLUX_AUTHHEADER" --header "Accept-Encoding: gzip" \ --data-raw "ping value=$PING $TIMESTAMP jitter value=$JITTER $TIMESTAMP From 7c7e37d8b32b71d0d0af715d6aeb6343f5efece7 Mon Sep 17 00:00:00 2001 From: Jack Naisbett Date: Sun, 16 Jan 2022 11:35:04 +0000 Subject: [PATCH 03/33] Download README and LICENSE if they don't exist locally --- connmon.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/connmon.sh b/connmon.sh index 8729a00..1fcc28f 100644 --- a/connmon.sh +++ b/connmon.sh @@ -1398,9 +1398,15 @@ Process_Upgrade(){ umount /www/start_apply.htm 2>/dev/null mount -o bind /tmp/start_apply.htm /www/start_apply.htm fi + if [ ! -f "$SCRIPT_DIR/README.md" ]; then + Update_File README.md + fi if [ ! -f "$SCRIPT_DIR/CHANGELOG.md" ]; then Update_File CHANGELOG.md fi + if [ ! -f "$SCRIPT_DIR/LICENSE" ]; then + Update_File LICENSE + fi if [ ! -f "$SCRIPT_STORAGE_DIR/connstatstext.js" ]; then echo "Stats last updated: Not yet updated" > /tmp/connstatstitle.txt WriteStats_ToJS /tmp/connstatstitle.txt "$SCRIPT_STORAGE_DIR/connstatstext.js" setConnmonStatsTitle statstitle From 35ab0a32b31a37fb31ffc864c5f4805a3b4f6355 Mon Sep 17 00:00:00 2001 From: "Martinski@GitHub" <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 04:29:05 -0700 Subject: [PATCH 04/33] Update connmonstats_www.asp Made changes to comply with JS dependencies when loading the WebGUI page on the 3006.102.1 F/W version. --- connmonstats_www.asp | 94 +++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/connmonstats_www.asp b/connmonstats_www.asp index 156ee05..4dd0b4b 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -2,53 +2,59 @@ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> - - - - - - - connmon - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + } +} +var $j=jQuery.noConflict();function getCookie(t,e){return null!==cookie.get("conn_"+t)?"string"===e?cookie.get("conn_"+t):"number"===e?+cookie.get("conn_"+t):void 0:"string"===e?"":"number"===e?0:void 0}function setCookie(t,e){cookie.set("conn_"+t,e,3650)}iziToast.settings({title:"connmon",timeout:5e3,resetOnHover:!1,transitionIn:"fadeInRight",transitionOut:"fadeOutRight",position:"bottomRight",messageSize:"16px",theme:"light",displayMode:"replace",layout:2,drag:!1,pauseOnHover:!1});var daysofweek=["Mon","Tues","Wed","Thurs","Fri","Sat","Sun"],pingtestdur=60,arraysortlistlines=[],sortname="Time",sortdir="desc",AltLayout=getCookie("AltLayout","string");""===AltLayout&&(AltLayout="false");var maxNoCharts=27,currentNoCharts=0,ShowLines=getCookie("ShowLines","string"),ShowFill=getCookie("ShowFill","string");""===ShowFill&&(ShowFill="origin");var DragZoom=!0,ChartPan=!1,myinterval,intervalclear=!1,pingtestrunning=!1;Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(t,e){return e};var dataintervallist=["raw","hour","day"],metriclist=["Ping","Jitter","LineQuality"],titlelist=["Ping","Jitter","Quality"],measureunitlist=["ms","ms","%"],chartlist=["daily","weekly","monthly"],timeunitlist=["hour","day","day"],intervallist=[24,7,30],bordercolourlist=["#fc8500","#42ecf5","#fff"],backgroundcolourlist=["rgba(252,133,0,0.5)","rgba(66,236,245,0.5)","rgba(255,255,255,0.5)"];function settingHint(t){t=+t;for(var e=document.getElementsByTagName("a"),n=0;n(* for all
Valid numbers between 0 and 59
comma (,) separate for multiple
dash (-) separate for a range":1===t?"Hour(s) of day to run ping test
* for all
Valid numbers between 0 and 23
comma (,) separate for multiple
dash (-) separate for a range":"My text goes here",0,0)}function resetZoom(){for(var t=0;to||+n[a].replace("*/","")<0)&&(i="true");else if(-1!==n[a].indexOf("-"))if(n[a].startsWith("-"))i="true";else for(var s=n[a].split("-"),r=0;ro||+s[r]<0?i="true":+s[r+1]<+s[r]&&(i="true","hours"===e?showhide("btnfixhours",!0):"mins"===e&&showhide("btnfixmins",!0));else(isNaN(+n[a])||+n[a]>o||+n[a]<0)&&(i="true");return"true"===i?($j(t).addClass("invalid"),!1):($j(t).removeClass("invalid"),!0)}function validateScheduleValue(t){t.name;var e=+t.value,n=0,o=$j("#everyxselect").val();return"hours"===o?n=24:"minutes"===o&&(n=30),n (a."+sortfield+" > b."+sortfield+") ? 1 : ((b."+sortfield+" > a."+sortfield+") ? -1 : 0));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" < b."+sortfield+") ? 1 : ((b."+sortfield+" < a."+sortfield+") ? -1 : 0));"),"desc"):"number"===sorttype?sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000")));'),"asc"):-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000"))); '),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(b."+sortfield+'.replace("m","000")) - parseFloat(a.'+sortfield+'.replace("m","000")));'),"desc"):"date"===sorttype&&(sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),"desc")),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTable()),$j(".sortable").each(function(t,e){e.innerHTML.replace(/ \(.*\)/,"").replace(" ","")===sortname&&("asc"===sortdir?$j(e).html(e.innerHTML+" ↑"):$j(e).html(e.innerHTML+" ↓"))})}function parseLastXData(t){var e=(e=t.split("\n")).filter(Boolean);arraysortlistlines=[];for(var n=0;nUpdated version available: '+t+""),$j("#connmon_version_server").on("mouseover",function(){return overlib(changelog,0,0)}),$j("#connmon_version_server")[0].onmouseout=nd}})}function buildLastXTableNoData(){return'
Data loading...
'}function buildLastXTable(){var t='';if("false"===AltLayout){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+='';for(var e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}else{t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+="",t+='',t+='',t+="",t+="",t+='';for(e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}return t+="",t+="
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+"
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+"
"}function scriptUpdateLayout(){var t=getVersionNumber("local"),e=getVersionNumber("server");$j("#connmon_version_local").text(t),t!==e&&"N/A"!==e&&(-1===e.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text(e),showhide("connmon_version_server",!0),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0))}function initial(){setCurrentPage(),loadCustomSettings(),show_menu(),document.formScriptActions.action_script.value="start_addon_settings;start_connmoncustomactionlist;start_connmonemailpassword",document.formScriptActions.submit(),setTimeout(getCustomactionList,1e4),setTimeout(getEmailpwFile,1e4),getConfFile(),getEmailConfFile(),getStatstitleFile(),getEmailInfo(),getCronFile(),getChangelogFile(),$j("#alternatelayout").prop("checked","false"!==AltLayout),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTableNoData()),d3.csv("/ext/connmon/csv/CompleteResults.htm").then(function(t){parseCSVExport(t)}).catch(function(){errorCSVExport()}),$j("#Time_Format").val(getCookie("Time_Format","number")),redrawAllCharts(),scriptUpdateLayout();var t=getCookie("StartTab","number");0===t&&(t=1),$j("#starttab").val(t),jyNavigate(t,"",5),jyNavigate(1,"Chart",3),jyNavigate(1,"NotificationType",4),jyNavigate(1,"NotificationMethod",6)}function setStartTab(t){setCookie("StartTab",$j(t).val())}function passChecked(t,e){switchType(t,e.checked,!0)}function toggleAlternateLayout(t){setCookie("AltLayout",AltLayout=t.checked.toString()),sortTable(sortname+" "+sortdir.replace("desc","↑").replace("asc","↓").trim())}function statusUpdate(){$j.ajax({url:"/ext/connmon/detect_update.js",dataType:"script",error:function(t){setTimeout(statusUpdate,1e3)},success:function(){"InProgress"===updatestatus?setTimeout(statusUpdate,1e3):(iziToast.destroy(),document.getElementById("imgChkUpdate").style.display="none",showhide("connmon_version_server",!0),"None"!==updatestatus?(customSettings.connmon_version_server=updatestatus,-1===updatestatus.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text("Updated version available: "+updatestatus),iziToast.warning({message:"New version available!"}),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)):(iziToast.info({message:"No updates available"}),$j("#connmon_version_server").text("No updates available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)))}})}function checkUpdate(){document.formScriptActions.action_script.value="start_addon_settings;start_connmoncheckupdate",document.formScriptActions.submit(),showhide("btnChkUpdate",!1),document.getElementById("imgChkUpdate").style.display="",iziToast.info({message:"Checking for updates...",timeout:!1}),setTimeout(statusUpdate,2e3)}function doUpdate(){document.form.action_script.value="start_connmondoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function postConnTest(){currentNoCharts=0,$j("#Time_Format").val(getCookie("Time_Format","number")),getStatstitleFile(),setTimeout(redrawAllCharts,3e3)}function saveStatus(e){$j.ajax({url:"/ext/connmon/detect_save.js",dataType:"script",error:function(t){setTimeout(saveStatus,1e3,e)},success:function(){"InProgress"===savestatus?setTimeout(saveStatus,1e3,e):(showhide("imgSave"+e,!1),"Success"===savestatus&&(iziToast.destroy(),iziToast.success({message:"Save successful"}),showhide("btnSave"+e,!0),loadCustomSettings(),"Navigate3"===e&&postConnTest()))}})}function saveConfig(t){switch(t){case"Navigate3":if(!validateAll())return!1;var e;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),0==+document.form.pingtype.value?document.form.connmon_pingserver.value=document.form.connmon_ipaddr.value:1==+document.form.pingtype.value&&(document.form.connmon_pingserver.value=document.form.connmon_domain.value),"EveryX"===document.form.schedulemode.value&&("hours"===document.form.everyxselect.value?(e=+document.form.everyxvalue.value,document.form.connmon_schmins.value=0,document.form.connmon_schhours.value=24===e?0:"*/"+e):"minutes"===document.form.everyxselect.value&&(document.form.connmon_schhours.value="*",e=+document.form.everyxvalue.value,document.form.connmon_schmins.value="*/"+e)),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Config":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_connmonemailconfig").find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Email":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_emailconfig").find("input,select,textarea").serializeObjectEmail()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonemailconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;default:var n;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t)}}function getConntestResultFile(){$j.ajax({url:"/ext/connmon/ping-result.htm",dataType:"text",cache:!1,error:function(t){setTimeout(getConntestResultFile,500)},success:function(t){t=t.trim().split("\n").join("\n"),$j("#conntest_output").html(t),document.getElementById("conntest_output").parentElement.parentElement.style.display=""}})}function testStatus(e){$j.ajax({url:"/ext/connmon/detect_test.js",dataType:"script",error:function(t){setTimeout(testStatus,1e3,e)},success:function(){"InProgress"===teststatus?setTimeout(testStatus,1e3,e):(showhide("img"+e,!1),iziToast.destroy(),showhide("btn"+e,!0),"Success"===teststatus?iziToast.success({message:"Test successful"}):iziToast.error({message:"Test failed - please check configuration"}))}})}function testNotification(t){confirm("If you have made any changes, you will need to save them first. Do you want to continue?")&&(showhide("btn"+t,!1),document.formScriptActions.action_script.value="start_addon_settings;start_connmon"+t,document.formScriptActions.submit(),showhide("img"+t,!0),setTimeout(testStatus,1e3,t),iziToast.info({message:"Running test...",timeout:!1}))}function everyXToggle(t){t.name;t=t.value;"hours"===t?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"===t&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),validateScheduleValue($j("[name=everyxvalue]")[0])}$j(document).keydown(function(t){keyHandler(t)}),$j(document).keyup(function(t){$j(document).keydown(function(t){keyHandler(t)})}),$j.fn.serializeObject=function(){var s=customSettings,t=this.serializeArray();return $j.each(t,function(){var t,e,n,o,i,a;void 0!==s[this.name]&&-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name?(s[this.name].push||(s[this.name]=[s[this.name]]),s[this.name].push(this.value||"")):-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name&&(s[this.name]=this.value||""),-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),"Mon,Tues,Wed,Thurs,Fri,Sat,Sun"===(e=t.join(","))&&(e="*"),s.connmon_schdays=e),"connmon_notifications_pingtest"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){n.push($j(this).val())}),s.connmon_notifications_pingtest=n.join(",")),"connmon_notifications_pingthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){o.push($j(this).val())}),s.connmon_notifications_pingthreshold=o.join(",")),"connmon_notifications_jitterthreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){i.push($j(this).val())}),s.connmon_notifications_jitterthreshold=i.join(",")),"connmon_notifications_linequalitythreshold"===this.name&&(a=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){a.push($j(this).val())}),s.connmon_notifications_linequalitythreshold=a.join(",")),-1!==this.name.indexOf("connmon_notifications_email_list")&&(s.connmon_notifications_email_list=document.getElementById("connmon_notifications_email_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_pushover_list")&&(s.connmon_notifications_pushover_list=document.getElementById("connmon_notifications_pushover_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_webhook_list")&&(s.connmon_notifications_webhook_list=document.getElementById("connmon_notifications_webhook_list").value.replace(/\n/g,"||||"))}),$j.each(this,function(){var t,e,n,o,i;-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),0===t.length&&(s.connmon_schdays="*")),"connmon_notifications_pingtest"===this.name&&(e=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){e.push($j(this).val())}),0===e.length&&(s.connmon_notifications_pingtest="None")),"connmon_notifications_pingthreshold"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){n.push($j(this).val())}),0===n.length&&(s.connmon_notifications_pingthreshold="None")),"connmon_notifications_jitterthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){o.push($j(this).val())}),0===o.length&&(s.connmon_notifications_jitterthreshold="None")),"connmon_notifications_linequalitythreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){i.push($j(this).val())}),0===i.length&&(s.connmon_notifications_linequalitythreshold="None"))}),s},$j.fn.serializeObjectEmail=function(){var t=customSettings,e=this.serializeArray();return $j.each(e,function(){void 0!==t[this.name]&&-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")?(t[this.name].push||(t[this.name]=[t[this.name]]),t[this.name].push(this.value||"")):-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")&&(t[this.name]=this.value||"")}),t};var pingcount=2;function updateConntest(){pingcount++,$j.ajax({url:"/ext/connmon/detect_connmon.js",dataType:"script",error:function(t){},success:function(){"InProgress"===connmonstatus?(showhide("imgConnTest",!0),showhide("conntest_text",!0),$j("#conntest_text").html("Ping test in progress - "+pingcount+"s elapsed")):"GenerateCSV"===connmonstatus?$j("#conntest_text").html("Retrieving data for charts..."):"Done"===connmonstatus?(clearInterval(myinterval),!1===intervalclear&&(intervalclear=!0,pingcount=2,getConntestResultFile(),$j("#conntest_text").html("Refreshing charts..."),postConnTest())):"LOCKED"===connmonstatus?(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Scheduled ping test already running!"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - scheduled ping test already running!"})):"InvalidServer"===connmonstatus&&(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Specified ping server is not valid"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - Specified ping server is not valid"}))}})}function startConnTestInterval(){pingtestrunning=!(intervalclear=!1),myinterval=setInterval(updateConntest,1e3)}function runPingTest(){showhide("btnRunPingtest",!1),$j("#conntest_output").html(""),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",document.formScriptActions.action_script.value="start_addon_settings;start_connmon",document.formScriptActions.submit(),showhide("imgConnTest",!0),showhide("conntest_text",!1),setTimeout(startConnTestInterval,5e3),iziToast.info({message:"Ping test started",timeout:!1})}function changeAllCharts(t){value=+t.value,name=t.id.substring(0,t.id.indexOf("_")),setCookie(t.id,value);for(var e=0;e
From a1e8bbbfd9bc46a86c91ee0f89f7c5246d73126b Mon Sep 17 00:00:00 2001 From: "Martinski@GitHub" <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 05:05:39 -0700 Subject: [PATCH 05/33] Update README.md Updated version string & date. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0b33981..712cd59 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/91af8db9cd354643a8ef6a7117be90fb)](https://www.codacy.com/app/jackyaz/connmon?utm_source=github.com&utm_medium=referral&utm_content=jackyaz/connmon&utm_campaign=Badge_Grade) ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) -## v3.0.3 -### Updated on 2022-01-14 +## v3.0.4 +### Updated on 2024-July-01 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. From e6d5667501afc8574b2ea85f3380af5b2a67acfe Mon Sep 17 00:00:00 2001 From: "Martinski@GitHub" <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 05:07:12 -0700 Subject: [PATCH 06/33] Update connmon.sh Updated version string. --- connmon.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/connmon.sh b/connmon.sh index 1fcc28f..ae92ed9 100644 --- a/connmon.sh +++ b/connmon.sh @@ -10,6 +10,8 @@ ## https://github.com/jackyaz/connmon ## ## ## ############################################################## +# Last Modified: 2024-Jul-01 +#------------------------------------------------------------- ############## Shellcheck directives ############# # shellcheck disable=SC1090 @@ -28,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="connmon" -readonly SCRIPT_VERSION="v3.0.3" +readonly SCRIPT_VERSION="v3.0.4" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://jackyaz.io/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME.d" From cd426c232364191b1c4ace3e20b2271824af81eb Mon Sep 17 00:00:00 2001 From: "Martinski@GitHub" <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 05:10:52 -0700 Subject: [PATCH 07/33] Updated ASP file. --- connmonstats_www.asp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmonstats_www.asp b/connmonstats_www.asp index 4dd0b4b..666d7f5 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -53,7 +53,7 @@ function loadCustomSettings() { } } } -var $j=jQuery.noConflict();function getCookie(t,e){return null!==cookie.get("conn_"+t)?"string"===e?cookie.get("conn_"+t):"number"===e?+cookie.get("conn_"+t):void 0:"string"===e?"":"number"===e?0:void 0}function setCookie(t,e){cookie.set("conn_"+t,e,3650)}iziToast.settings({title:"connmon",timeout:5e3,resetOnHover:!1,transitionIn:"fadeInRight",transitionOut:"fadeOutRight",position:"bottomRight",messageSize:"16px",theme:"light",displayMode:"replace",layout:2,drag:!1,pauseOnHover:!1});var daysofweek=["Mon","Tues","Wed","Thurs","Fri","Sat","Sun"],pingtestdur=60,arraysortlistlines=[],sortname="Time",sortdir="desc",AltLayout=getCookie("AltLayout","string");""===AltLayout&&(AltLayout="false");var maxNoCharts=27,currentNoCharts=0,ShowLines=getCookie("ShowLines","string"),ShowFill=getCookie("ShowFill","string");""===ShowFill&&(ShowFill="origin");var DragZoom=!0,ChartPan=!1,myinterval,intervalclear=!1,pingtestrunning=!1;Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(t,e){return e};var dataintervallist=["raw","hour","day"],metriclist=["Ping","Jitter","LineQuality"],titlelist=["Ping","Jitter","Quality"],measureunitlist=["ms","ms","%"],chartlist=["daily","weekly","monthly"],timeunitlist=["hour","day","day"],intervallist=[24,7,30],bordercolourlist=["#fc8500","#42ecf5","#fff"],backgroundcolourlist=["rgba(252,133,0,0.5)","rgba(66,236,245,0.5)","rgba(255,255,255,0.5)"];function settingHint(t){t=+t;for(var e=document.getElementsByTagName("a"),n=0;n(* for all
Valid numbers between 0 and 59
comma (,) separate for multiple
dash (-) separate for a range":1===t?"Hour(s) of day to run ping test
* for all
Valid numbers between 0 and 23
comma (,) separate for multiple
dash (-) separate for a range":"My text goes here",0,0)}function resetZoom(){for(var t=0;to||+n[a].replace("*/","")<0)&&(i="true");else if(-1!==n[a].indexOf("-"))if(n[a].startsWith("-"))i="true";else for(var s=n[a].split("-"),r=0;ro||+s[r]<0?i="true":+s[r+1]<+s[r]&&(i="true","hours"===e?showhide("btnfixhours",!0):"mins"===e&&showhide("btnfixmins",!0));else(isNaN(+n[a])||+n[a]>o||+n[a]<0)&&(i="true");return"true"===i?($j(t).addClass("invalid"),!1):($j(t).removeClass("invalid"),!0)}function validateScheduleValue(t){t.name;var e=+t.value,n=0,o=$j("#everyxselect").val();return"hours"===o?n=24:"minutes"===o&&(n=30),n (a."+sortfield+" > b."+sortfield+") ? 1 : ((b."+sortfield+" > a."+sortfield+") ? -1 : 0));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" < b."+sortfield+") ? 1 : ((b."+sortfield+" < a."+sortfield+") ? -1 : 0));"),"desc"):"number"===sorttype?sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000")));'),"asc"):-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000"))); '),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(b."+sortfield+'.replace("m","000")) - parseFloat(a.'+sortfield+'.replace("m","000")));'),"desc"):"date"===sorttype&&(sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),"desc")),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTable()),$j(".sortable").each(function(t,e){e.innerHTML.replace(/ \(.*\)/,"").replace(" ","")===sortname&&("asc"===sortdir?$j(e).html(e.innerHTML+" ↑"):$j(e).html(e.innerHTML+" ↓"))})}function parseLastXData(t){var e=(e=t.split("\n")).filter(Boolean);arraysortlistlines=[];for(var n=0;nUpdated version available: '+t+""),$j("#connmon_version_server").on("mouseover",function(){return overlib(changelog,0,0)}),$j("#connmon_version_server")[0].onmouseout=nd}})}function buildLastXTableNoData(){return'
Data loading...
'}function buildLastXTable(){var t='';if("false"===AltLayout){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+='';for(var e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}else{t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+="",t+='',t+='',t+="",t+="",t+='';for(e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}return t+="",t+="
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+"
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+"
"}function scriptUpdateLayout(){var t=getVersionNumber("local"),e=getVersionNumber("server");$j("#connmon_version_local").text(t),t!==e&&"N/A"!==e&&(-1===e.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text(e),showhide("connmon_version_server",!0),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0))}function initial(){setCurrentPage(),loadCustomSettings(),show_menu(),document.formScriptActions.action_script.value="start_addon_settings;start_connmoncustomactionlist;start_connmonemailpassword",document.formScriptActions.submit(),setTimeout(getCustomactionList,1e4),setTimeout(getEmailpwFile,1e4),getConfFile(),getEmailConfFile(),getStatstitleFile(),getEmailInfo(),getCronFile(),getChangelogFile(),$j("#alternatelayout").prop("checked","false"!==AltLayout),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTableNoData()),d3.csv("/ext/connmon/csv/CompleteResults.htm").then(function(t){parseCSVExport(t)}).catch(function(){errorCSVExport()}),$j("#Time_Format").val(getCookie("Time_Format","number")),redrawAllCharts(),scriptUpdateLayout();var t=getCookie("StartTab","number");0===t&&(t=1),$j("#starttab").val(t),jyNavigate(t,"",5),jyNavigate(1,"Chart",3),jyNavigate(1,"NotificationType",4),jyNavigate(1,"NotificationMethod",6)}function setStartTab(t){setCookie("StartTab",$j(t).val())}function passChecked(t,e){switchType(t,e.checked,!0)}function toggleAlternateLayout(t){setCookie("AltLayout",AltLayout=t.checked.toString()),sortTable(sortname+" "+sortdir.replace("desc","↑").replace("asc","↓").trim())}function statusUpdate(){$j.ajax({url:"/ext/connmon/detect_update.js",dataType:"script",error:function(t){setTimeout(statusUpdate,1e3)},success:function(){"InProgress"===updatestatus?setTimeout(statusUpdate,1e3):(iziToast.destroy(),document.getElementById("imgChkUpdate").style.display="none",showhide("connmon_version_server",!0),"None"!==updatestatus?(customSettings.connmon_version_server=updatestatus,-1===updatestatus.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text("Updated version available: "+updatestatus),iziToast.warning({message:"New version available!"}),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)):(iziToast.info({message:"No updates available"}),$j("#connmon_version_server").text("No updates available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)))}})}function checkUpdate(){document.formScriptActions.action_script.value="start_addon_settings;start_connmoncheckupdate",document.formScriptActions.submit(),showhide("btnChkUpdate",!1),document.getElementById("imgChkUpdate").style.display="",iziToast.info({message:"Checking for updates...",timeout:!1}),setTimeout(statusUpdate,2e3)}function doUpdate(){document.form.action_script.value="start_connmondoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function postConnTest(){currentNoCharts=0,$j("#Time_Format").val(getCookie("Time_Format","number")),getStatstitleFile(),setTimeout(redrawAllCharts,3e3)}function saveStatus(e){$j.ajax({url:"/ext/connmon/detect_save.js",dataType:"script",error:function(t){setTimeout(saveStatus,1e3,e)},success:function(){"InProgress"===savestatus?setTimeout(saveStatus,1e3,e):(showhide("imgSave"+e,!1),"Success"===savestatus&&(iziToast.destroy(),iziToast.success({message:"Save successful"}),showhide("btnSave"+e,!0),loadCustomSettings(),"Navigate3"===e&&postConnTest()))}})}function saveConfig(t){switch(t){case"Navigate3":if(!validateAll())return!1;var e;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),0==+document.form.pingtype.value?document.form.connmon_pingserver.value=document.form.connmon_ipaddr.value:1==+document.form.pingtype.value&&(document.form.connmon_pingserver.value=document.form.connmon_domain.value),"EveryX"===document.form.schedulemode.value&&("hours"===document.form.everyxselect.value?(e=+document.form.everyxvalue.value,document.form.connmon_schmins.value=0,document.form.connmon_schhours.value=24===e?0:"*/"+e):"minutes"===document.form.everyxselect.value&&(document.form.connmon_schhours.value="*",e=+document.form.everyxvalue.value,document.form.connmon_schmins.value="*/"+e)),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Config":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_connmonemailconfig").find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Email":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_emailconfig").find("input,select,textarea").serializeObjectEmail()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonemailconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;default:var n;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t)}}function getConntestResultFile(){$j.ajax({url:"/ext/connmon/ping-result.htm",dataType:"text",cache:!1,error:function(t){setTimeout(getConntestResultFile,500)},success:function(t){t=t.trim().split("\n").join("\n"),$j("#conntest_output").html(t),document.getElementById("conntest_output").parentElement.parentElement.style.display=""}})}function testStatus(e){$j.ajax({url:"/ext/connmon/detect_test.js",dataType:"script",error:function(t){setTimeout(testStatus,1e3,e)},success:function(){"InProgress"===teststatus?setTimeout(testStatus,1e3,e):(showhide("img"+e,!1),iziToast.destroy(),showhide("btn"+e,!0),"Success"===teststatus?iziToast.success({message:"Test successful"}):iziToast.error({message:"Test failed - please check configuration"}))}})}function testNotification(t){confirm("If you have made any changes, you will need to save them first. Do you want to continue?")&&(showhide("btn"+t,!1),document.formScriptActions.action_script.value="start_addon_settings;start_connmon"+t,document.formScriptActions.submit(),showhide("img"+t,!0),setTimeout(testStatus,1e3,t),iziToast.info({message:"Running test...",timeout:!1}))}function everyXToggle(t){t.name;t=t.value;"hours"===t?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"===t&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),validateScheduleValue($j("[name=everyxvalue]")[0])}$j(document).keydown(function(t){keyHandler(t)}),$j(document).keyup(function(t){$j(document).keydown(function(t){keyHandler(t)})}),$j.fn.serializeObject=function(){var s=customSettings,t=this.serializeArray();return $j.each(t,function(){var t,e,n,o,i,a;void 0!==s[this.name]&&-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name?(s[this.name].push||(s[this.name]=[s[this.name]]),s[this.name].push(this.value||"")):-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name&&(s[this.name]=this.value||""),-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),"Mon,Tues,Wed,Thurs,Fri,Sat,Sun"===(e=t.join(","))&&(e="*"),s.connmon_schdays=e),"connmon_notifications_pingtest"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){n.push($j(this).val())}),s.connmon_notifications_pingtest=n.join(",")),"connmon_notifications_pingthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){o.push($j(this).val())}),s.connmon_notifications_pingthreshold=o.join(",")),"connmon_notifications_jitterthreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){i.push($j(this).val())}),s.connmon_notifications_jitterthreshold=i.join(",")),"connmon_notifications_linequalitythreshold"===this.name&&(a=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){a.push($j(this).val())}),s.connmon_notifications_linequalitythreshold=a.join(",")),-1!==this.name.indexOf("connmon_notifications_email_list")&&(s.connmon_notifications_email_list=document.getElementById("connmon_notifications_email_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_pushover_list")&&(s.connmon_notifications_pushover_list=document.getElementById("connmon_notifications_pushover_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_webhook_list")&&(s.connmon_notifications_webhook_list=document.getElementById("connmon_notifications_webhook_list").value.replace(/\n/g,"||||"))}),$j.each(this,function(){var t,e,n,o,i;-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),0===t.length&&(s.connmon_schdays="*")),"connmon_notifications_pingtest"===this.name&&(e=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){e.push($j(this).val())}),0===e.length&&(s.connmon_notifications_pingtest="None")),"connmon_notifications_pingthreshold"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){n.push($j(this).val())}),0===n.length&&(s.connmon_notifications_pingthreshold="None")),"connmon_notifications_jitterthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){o.push($j(this).val())}),0===o.length&&(s.connmon_notifications_jitterthreshold="None")),"connmon_notifications_linequalitythreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){i.push($j(this).val())}),0===i.length&&(s.connmon_notifications_linequalitythreshold="None"))}),s},$j.fn.serializeObjectEmail=function(){var t=customSettings,e=this.serializeArray();return $j.each(e,function(){void 0!==t[this.name]&&-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")?(t[this.name].push||(t[this.name]=[t[this.name]]),t[this.name].push(this.value||"")):-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")&&(t[this.name]=this.value||"")}),t};var pingcount=2;function updateConntest(){pingcount++,$j.ajax({url:"/ext/connmon/detect_connmon.js",dataType:"script",error:function(t){},success:function(){"InProgress"===connmonstatus?(showhide("imgConnTest",!0),showhide("conntest_text",!0),$j("#conntest_text").html("Ping test in progress - "+pingcount+"s elapsed")):"GenerateCSV"===connmonstatus?$j("#conntest_text").html("Retrieving data for charts..."):"Done"===connmonstatus?(clearInterval(myinterval),!1===intervalclear&&(intervalclear=!0,pingcount=2,getConntestResultFile(),$j("#conntest_text").html("Refreshing charts..."),postConnTest())):"LOCKED"===connmonstatus?(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Scheduled ping test already running!"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - scheduled ping test already running!"})):"InvalidServer"===connmonstatus&&(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Specified ping server is not valid"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - Specified ping server is not valid"}))}})}function startConnTestInterval(){pingtestrunning=!(intervalclear=!1),myinterval=setInterval(updateConntest,1e3)}function runPingTest(){showhide("btnRunPingtest",!1),$j("#conntest_output").html(""),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",document.formScriptActions.action_script.value="start_addon_settings;start_connmon",document.formScriptActions.submit(),showhide("imgConnTest",!0),showhide("conntest_text",!1),setTimeout(startConnTestInterval,5e3),iziToast.info({message:"Ping test started",timeout:!1})}function changeAllCharts(t){value=+t.value,name=t.id.substring(0,t.id.indexOf("_")),setCookie(t.id,value);for(var e=0;e(* for all
Valid numbers between 0 and 59
comma (,) separate for multiple
dash (-) separate for a range":1===t?"Hour(s) of day to run ping test
* for all
Valid numbers between 0 and 23
comma (,) separate for multiple
dash (-) separate for a range":"My text goes here",0,0)}function resetZoom(){for(var t=0;to||+n[a].replace("*/","")<0)&&(i="true");else if(-1!==n[a].indexOf("-"))if(n[a].startsWith("-"))i="true";else for(var s=n[a].split("-"),r=0;ro||+s[r]<0?i="true":+s[r+1]<+s[r]&&(i="true","hours"===e?showhide("btnfixhours",!0):"mins"===e&&showhide("btnfixmins",!0));else(isNaN(+n[a])||+n[a]>o||+n[a]<0)&&(i="true");return"true"===i?($j(t).addClass("invalid"),!1):($j(t).removeClass("invalid"),!0)}function validateScheduleValue(t){t.name;var e=+t.value,n=0,o=$j("#everyxselect").val();return"hours"===o?n=24:"minutes"===o&&(n=30),n (a."+sortfield+" > b."+sortfield+") ? 1 : ((b."+sortfield+" > a."+sortfield+") ? -1 : 0));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" < b."+sortfield+") ? 1 : ((b."+sortfield+" < a."+sortfield+") ? -1 : 0));"),"desc"):"number"===sorttype?sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000")));'),"asc"):-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000"))); '),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(b."+sortfield+'.replace("m","000")) - parseFloat(a.'+sortfield+'.replace("m","000")));'),"desc"):"date"===sorttype&&(sortdir=-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),"asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),"desc")),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTable()),$j(".sortable").each(function(t,e){e.innerHTML.replace(/ \(.*\)/,"").replace(" ","")===sortname&&("asc"===sortdir?$j(e).html(e.innerHTML+" ↑"):$j(e).html(e.innerHTML+" ↓"))})}function parseLastXData(t){var e=(e=t.split("\n")).filter(Boolean);arraysortlistlines=[];for(var n=0;nUpdated version available: '+t+""),$j("#connmon_version_server").on("mouseover",function(){return overlib(changelog,0,0)}),$j("#connmon_version_server")[0].onmouseout=nd}})}function buildLastXTableNoData(){return'
Data loading...
'}function buildLastXTable(){var t='';if("false"===AltLayout){t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+='',t+='',t+="",t+="",t+="",t+='';for(var e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}else{t+='',t+='',t+='',t+='',t+='',t+='',t+='',t+="",t+='',t+='',t+='',t+="",t+='',t+='',t+="",t+="",t+='';for(e=0;e',t+="",t+="",t+="",t+="",t+="",t+="",t+=""}return t+="",t+="
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+"
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
"+arraysortlistlines[e].Time+""+arraysortlistlines[e].Ping+""+arraysortlistlines[e].Jitter+""+arraysortlistlines[e].LineQuality+""+arraysortlistlines[e].Target+""+arraysortlistlines[e].Duration+"
"}function scriptUpdateLayout(){var t=getVersionNumber("local"),e=getVersionNumber("server");$j("#connmon_version_local").text(t),t!==e&&"N/A"!==e&&(-1===e.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text(e),showhide("connmon_version_server",!0),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0))}function initial(){setCurrentPage(),loadCustomSettings(),show_menu(),document.formScriptActions.action_script.value="start_addon_settings;start_connmoncustomactionlist;start_connmonemailpassword",document.formScriptActions.submit(),setTimeout(getCustomactionList,1e4),setTimeout(getEmailpwFile,1e4),getConfFile(),getEmailConfFile(),getStatstitleFile(),getEmailInfo(),getCronFile(),getChangelogFile(),$j("#alternatelayout").prop("checked","false"!==AltLayout),$j("#sortTableContainer").empty(),$j("#sortTableContainer").append(buildLastXTableNoData()),d3.csv("/ext/connmon/csv/CompleteResults.htm").then(function(t){parseCSVExport(t)}).catch(function(){errorCSVExport()}),$j("#Time_Format").val(getCookie("Time_Format","number")),redrawAllCharts(),scriptUpdateLayout();var t=getCookie("StartTab","number");0===t&&(t=1),$j("#starttab").val(t),jyNavigate(t,"",5),jyNavigate(1,"Chart",3),jyNavigate(1,"NotificationType",4),jyNavigate(1,"NotificationMethod",6)}function setStartTab(t){setCookie("StartTab",$j(t).val())}function passChecked(t,e){switchType(t,e.checked,!0)}function toggleAlternateLayout(t){setCookie("AltLayout",AltLayout=t.checked.toString()),sortTable(sortname+" "+sortdir.replace("desc","↑").replace("asc","↓").trim())}function statusUpdate(){$j.ajax({url:"/ext/connmon/detect_update.js",dataType:"script",error:function(t){setTimeout(statusUpdate,1e3)},success:function(){"InProgress"===updatestatus?setTimeout(statusUpdate,1e3):(iziToast.destroy(),document.getElementById("imgChkUpdate").style.display="none",showhide("connmon_version_server",!0),"None"!==updatestatus?(customSettings.connmon_version_server=updatestatus,-1===updatestatus.indexOf("hotfix")?getVersionChangelogFile():$j("#connmon_version_server").text("Updated version available: "+updatestatus),iziToast.warning({message:"New version available!"}),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)):(iziToast.info({message:"No updates available"}),$j("#connmon_version_server").text("No updates available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)))}})}function checkUpdate(){document.formScriptActions.action_script.value="start_addon_settings;start_connmoncheckupdate",document.formScriptActions.submit(),showhide("btnChkUpdate",!1),document.getElementById("imgChkUpdate").style.display="",iziToast.info({message:"Checking for updates...",timeout:!1}),setTimeout(statusUpdate,2e3)}function doUpdate(){document.form.action_script.value="start_connmondoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function postConnTest(){currentNoCharts=0,$j("#Time_Format").val(getCookie("Time_Format","number")),getStatstitleFile(),setTimeout(redrawAllCharts,3e3)}function saveStatus(e){$j.ajax({url:"/ext/connmon/detect_save.js",dataType:"script",error:function(t){setTimeout(saveStatus,1e3,e)},success:function(){"InProgress"===savestatus?setTimeout(saveStatus,1e3,e):(showhide("imgSave"+e,!1),"Success"===savestatus&&(iziToast.destroy(),iziToast.success({message:"Save successful"}),showhide("btnSave"+e,!0),loadCustomSettings(),"Navigate3"===e&&postConnTest()))}})}function saveConfig(t){switch(t){case"Navigate3":if(!validateAll())return!1;var e;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),0==+document.form.pingtype.value?document.form.connmon_pingserver.value=document.form.connmon_ipaddr.value:1==+document.form.pingtype.value&&(document.form.connmon_pingserver.value=document.form.connmon_domain.value),"EveryX"===document.form.schedulemode.value&&("hours"===document.form.everyxselect.value?(e=+document.form.everyxvalue.value,document.form.connmon_schmins.value=0,document.form.connmon_schhours.value=24===e?0:"*/"+e):"minutes"===document.form.everyxselect.value&&(document.form.connmon_schhours.value="*",e=+document.form.everyxvalue.value,document.form.connmon_schmins.value="*/"+e)),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Config":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_connmonemailconfig").find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;case"NotificationMethodNavigate1Email":(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#table_emailconfig").find("input,select,textarea").serializeObjectEmail()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonemailconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t);break;default:var n;(n=$j("#"+t).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($j("#"+t).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+t,!1),showhide("imgSave"+t,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,t)}}function getConntestResultFile(){$j.ajax({url:"/ext/connmon/ping-result.htm",dataType:"text",cache:!1,error:function(t){setTimeout(getConntestResultFile,500)},success:function(t){t=t.trim().split("\n").join("\n"),$j("#conntest_output").html(t),document.getElementById("conntest_output").parentElement.parentElement.style.display=""}})}function testStatus(e){$j.ajax({url:"/ext/connmon/detect_test.js",dataType:"script",error:function(t){setTimeout(testStatus,1e3,e)},success:function(){"InProgress"===teststatus?setTimeout(testStatus,1e3,e):(showhide("img"+e,!1),iziToast.destroy(),showhide("btn"+e,!0),"Success"===teststatus?iziToast.success({message:"Test successful"}):iziToast.error({message:"Test failed - please check configuration"}))}})}function testNotification(t){confirm("If you have made any changes, you will need to save them first. Do you want to continue?")&&(showhide("btn"+t,!1),document.formScriptActions.action_script.value="start_addon_settings;start_connmon"+t,document.formScriptActions.submit(),showhide("img"+t,!0),setTimeout(testStatus,1e3,t),iziToast.info({message:"Running test...",timeout:!1}))}function everyXToggle(t){t.name;t=t.value;"hours"===t?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"===t&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),validateScheduleValue($j("[name=everyxvalue]")[0])}$j(document).keydown(function(t){keyHandler(t)}),$j(document).keyup(function(t){$j(document).keydown(function(t){keyHandler(t)})}),$j.fn.serializeObject=function(){var s=customSettings,t=this.serializeArray();return $j.each(t,function(){var t,e,n,o,i,a;void 0!==s[this.name]&&-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name?(s[this.name].push||(s[this.name]=[s[this.name]]),s[this.name].push(this.value||"")):-1!==this.name.indexOf("connmon")&&-1===this.name.indexOf("version")&&-1===this.name.indexOf("ipaddr")&&-1===this.name.indexOf("domain")&&-1===this.name.indexOf("schdays")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("pushover_list")&&-1===this.name.indexOf("webhook_list")&&"connmon_notifications_pingtest"!==this.name&&"connmon_notifications_pingthreshold"!==this.name&&"connmon_notifications_jitterthreshold"!==this.name&&"connmon_notifications_linequalitythreshold"!==this.name&&(s[this.name]=this.value||""),-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),"Mon,Tues,Wed,Thurs,Fri,Sat,Sun"===(e=t.join(","))&&(e="*"),s.connmon_schdays=e),"connmon_notifications_pingtest"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){n.push($j(this).val())}),s.connmon_notifications_pingtest=n.join(",")),"connmon_notifications_pingthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){o.push($j(this).val())}),s.connmon_notifications_pingthreshold=o.join(",")),"connmon_notifications_jitterthreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){i.push($j(this).val())}),s.connmon_notifications_jitterthreshold=i.join(",")),"connmon_notifications_linequalitythreshold"===this.name&&(a=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){a.push($j(this).val())}),s.connmon_notifications_linequalitythreshold=a.join(",")),-1!==this.name.indexOf("connmon_notifications_email_list")&&(s.connmon_notifications_email_list=document.getElementById("connmon_notifications_email_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_pushover_list")&&(s.connmon_notifications_pushover_list=document.getElementById("connmon_notifications_pushover_list").value.replace(/\n/g,"||||")),-1!==this.name.indexOf("connmon_notifications_webhook_list")&&(s.connmon_notifications_webhook_list=document.getElementById("connmon_notifications_webhook_list").value.replace(/\n/g,"||||"))}),$j.each(this,function(){var t,e,n,o,i;-1!==this.name.indexOf("schdays")&&(t=[],$j.each($j('input[name="connmon_schdays"]:checked'),function(){t.push($j(this).val())}),0===t.length&&(s.connmon_schdays="*")),"connmon_notifications_pingtest"===this.name&&(e=[],$j.each($j('input[name="connmon_notifications_pingtest"]:checked'),function(){e.push($j(this).val())}),0===e.length&&(s.connmon_notifications_pingtest="None")),"connmon_notifications_pingthreshold"===this.name&&(n=[],$j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'),function(){n.push($j(this).val())}),0===n.length&&(s.connmon_notifications_pingthreshold="None")),"connmon_notifications_jitterthreshold"===this.name&&(o=[],$j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'),function(){o.push($j(this).val())}),0===o.length&&(s.connmon_notifications_jitterthreshold="None")),"connmon_notifications_linequalitythreshold"===this.name&&(i=[],$j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'),function(){i.push($j(this).val())}),0===i.length&&(s.connmon_notifications_linequalitythreshold="None"))}),s},$j.fn.serializeObjectEmail=function(){var t=customSettings,e=this.serializeArray();return $j.each(e,function(){void 0!==t[this.name]&&-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")?(t[this.name].push||(t[this.name]=[t[this.name]]),t[this.name].push(this.value||"")):-1!==this.name.indexOf("email_")&&-1===this.name.indexOf("show_pass")&&(t[this.name]=this.value||"")}),t};var pingcount=2;function updateConntest(){pingcount++,$j.ajax({url:"/ext/connmon/detect_connmon.js",dataType:"script",error:function(t){},success:function(){"InProgress"===connmonstatus?(showhide("imgConnTest",!0),showhide("conntest_text",!0),$j("#conntest_text").html("Ping test in progress - "+pingcount+"s elapsed")):"GenerateCSV"===connmonstatus?$j("#conntest_text").html("Retrieving data for charts..."):"Done"===connmonstatus?(clearInterval(myinterval),!1===intervalclear&&(intervalclear=!0,pingcount=2,getConntestResultFile(),$j("#conntest_text").html("Refreshing charts..."),postConnTest())):"LOCKED"===connmonstatus?(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Scheduled ping test already running!"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - scheduled ping test already running!"})):"InvalidServer"===connmonstatus&&(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$j("#conntest_text").html("Specified ping server is not valid"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - Specified ping server is not valid"}))}})}function startConnTestInterval(){pingtestrunning=!(intervalclear=!1),myinterval=setInterval(updateConntest,1e3)}function runPingTest(){showhide("btnRunPingtest",!1),$j("#conntest_output").html(""),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",document.formScriptActions.action_script.value="start_addon_settings;start_connmon",document.formScriptActions.submit(),showhide("imgConnTest",!0),showhide("conntest_text",!1),setTimeout(startConnTestInterval,5e3),iziToast.info({message:"Ping test started",timeout:!1})}function changeAllCharts(t){value=+t.value,name=t.id.substring(0,t.id.indexOf("_")),setCookie(t.id,value);for(var e=0;e From b24d12009bfac614346d1070bfe53e220bda59e1 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:21:58 -0700 Subject: [PATCH 08/33] Update README.md Corrected next version string. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 712cd59..12a16e0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/91af8db9cd354643a8ef6a7117be90fb)](https://www.codacy.com/app/jackyaz/connmon?utm_source=github.com&utm_medium=referral&utm_content=jackyaz/connmon&utm_campaign=Badge_Grade) ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) -## v3.0.4 +## v3.0.3 ### Updated on 2024-July-01 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. From d98af7ef2f08276d3d80d9c49bd5995b6b0fdbd4 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 1 Jul 2024 17:22:16 -0700 Subject: [PATCH 09/33] Update connmon.sh Corrected next version string. --- connmon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmon.sh b/connmon.sh index ae92ed9..3d1302b 100644 --- a/connmon.sh +++ b/connmon.sh @@ -30,7 +30,7 @@ ### Start of script variables ### readonly SCRIPT_NAME="connmon" -readonly SCRIPT_VERSION="v3.0.4" +readonly SCRIPT_VERSION="v3.0.3" SCRIPT_BRANCH="develop" SCRIPT_REPO="https://jackyaz.io/$SCRIPT_NAME/$SCRIPT_BRANCH" readonly SCRIPT_DIR="/jffs/addons/$SCRIPT_NAME.d" From 2d35b6181bd7fc2158fcece46653ffec687bda96 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 15 Jul 2024 00:23:42 -0700 Subject: [PATCH 10/33] Fixed "Reset Database" functionality Fixed the "Reset Database" functionality on the CLI menu where the database file was correctly reset but the result was not reflected on the webGUI page where "old" entries were still shown as if the database had not been reset. --- README.md | 2 +- connmon.sh | 61 ++++++++++++++++++++++++++++++++++++-------- connmonstats_www.asp | 10 +++++--- connmonstats_www.js | 21 ++++++++++++--- 4 files changed, 74 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 12a16e0..92c0375 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) ## v3.0.3 -### Updated on 2024-July-01 +### Updated on 2024-July-14 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. diff --git a/connmon.sh b/connmon.sh index 3d1302b..716ed73 100644 --- a/connmon.sh +++ b/connmon.sh @@ -10,7 +10,7 @@ ## https://github.com/jackyaz/connmon ## ## ## ############################################################## -# Last Modified: 2024-Jul-01 +# Last Modified: 2024-Jul-14 #------------------------------------------------------------- ############## Shellcheck directives ############# @@ -1023,14 +1023,25 @@ OutputTimeMode(){ esac } -WriteStats_ToJS(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Jul-14] ## +##----------------------------------------## +WriteStats_ToJS() +{ + if [ $# -lt 4 ] ; then return 1 ; fi + echo "function $3(){" > "$2" html='document.getElementById("'"$4"'").innerHTML="' - while IFS='' read -r line || [ -n "$line" ]; do - html="${html}${line}\\r\\n" + + while IFS='' read -r line || [ -n "$line" ] + do html="${html}${line}\r\n" done < "$1" html="$html"'"' - printf "%s\\r\\n}\\r\\n" "$html" >> "$2" + + if [ $# -lt 5 ] || [ -z "$5" ] + then printf "%s\r\n}\r\n" "$html" >> "$2" + else printf "%s;\r\n%s\r\n}\r\n" "$html" "$5" >> "$2" + fi } #$1 fieldname $2 tablename $3 frequency (hours) $4 length (days) $5 outputfile $6 outputfrequency $7 sqlfile $8 timestamp @@ -1327,12 +1338,18 @@ Generate_LastXResults(){ mv /tmp/conn-lastx.csv "$SCRIPT_STORAGE_DIR/lastx.csv" } -Reset_DB(){ + +##----------------------------------------## +## Modified by Martinski W. [2024-Jul-14] ## +##----------------------------------------## +Reset_DB() +{ SIZEAVAIL="$(df -P -k "$SCRIPT_STORAGE_DIR" | awk '{print $4}' | tail -n 1)" SIZEDB="$(ls -l "$SCRIPT_STORAGE_DIR/connstats.db" | awk '{print $5}')" - SIZEAVAIL="$(echo "$SIZEAVAIL" | awk '{printf("%s", $1*1024);}')" + SIZEAVAIL="$(echo "$SIZEAVAIL" | awk '{printf("%s", $1 * 1024);}')" - if [ "$(echo "$SIZEAVAIL $SIZEDB" | awk '{print ($1 < $2)}')" -eq 1 ]; then + if [ "$(echo "$SIZEAVAIL $SIZEDB" | awk '{print ($1 < $2)}')" -eq 1 ] + then Print_Output true "Database size exceeds available space. $(ls -lh "$SCRIPT_STORAGE_DIR/connstats.db" | awk '{print $5}')B is required to create backup." "$ERR" return 1 else @@ -1341,11 +1358,30 @@ Reset_DB(){ Print_Output true "Database backup failed, please check storage device" "$WARN" fi + Print_Output false "Please wait..." "$PASS" echo "DELETE FROM [connstats];" > /tmp/connmon-stats.sql "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql rm -f /tmp/connmon-stats.sql + ## Clear/Reset all CSV files ## + Generate_CSVs + + ## Show "reset" messages on webGUI ## + timeDateNow="$(/bin/date +"%c")" + extraJScode='databaseResetDone += 1;' + echo "Resetting stats: $timeDateNow" > /tmp/connstatstitle.txt + WriteStats_ToJS /tmp/connstatstitle.txt "$SCRIPT_STORAGE_DIR/connstatstext.js" setConnmonStatsTitle statstitle "$extraJScode" + rm -f /tmp/connstatstitle.txt + sleep 2 Print_Output true "Database reset complete" "$WARN" + { + sleep 4 + timeDateNow="$(/bin/date +"%c")" + extraJScode='databaseResetDone = 0;' + echo "Stats were reset: $timeDateNow" > /tmp/connstatstitle.txt + WriteStats_ToJS /tmp/connstatstitle.txt "$SCRIPT_STORAGE_DIR/connstatstext.js" setConnmonStatsTitle statstitle "$extraJScode" + rm -f /tmp/connstatstitle.txt + } & fi } @@ -3221,8 +3257,10 @@ Menu_Install(){ MainMenu } -Menu_Startup(){ - if [ -z "$1" ]; then +Menu_Startup() +{ + if [ $# -eq 0 ] || [ -z "$1" ] + then Print_Output true "Missing argument for startup, not starting $SCRIPT_NAME" "$WARN" exit 1 elif [ "$1" != "force" ]; then @@ -3747,7 +3785,8 @@ fi CSV_OUTPUT_DIR="$SCRIPT_STORAGE_DIR/csv" USER_SCRIPT_DIR="$SCRIPT_STORAGE_DIR/userscripts.d" -if [ -z "$1" ]; then +if [ $# -eq 0 ] || [ -z "$1" ] +then NTP_Ready Entware_Ready if [ ! -f /opt/bin/sqlite3 ]; then diff --git a/connmonstats_www.asp b/connmonstats_www.asp index 666d7f5..cac756f 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -1,5 +1,4 @@ - + @@ -35,8 +34,9 @@ diff --git a/connmonstats_www.js b/connmonstats_www.js index fd2ccec..a7af6b7 100644 --- a/connmonstats_www.js +++ b/connmonstats_www.js @@ -868,7 +868,6 @@ function redrawAllCharts() { } } - function sortTable(sorttext) { sortname = sorttext.replace('↑', '').replace('↓', '').trim(); var sorttype = 'number'; @@ -1369,15 +1368,29 @@ function getConfFile() { }); } -function getStatstitleFile() { +/**----------------------------------------**/ +/** Modified by Martinski W. [2024-Jul-14] **/ +/**----------------------------------------**/ +let databaseResetDone = 0; +function getStatstitleFile() +{ $j.ajax({ url: '/ext/connmon/connstatstext.js', dataType: 'script', error: function (xhr) { - setTimeout(getStatstitleFile, 1000); + setTimeout(getStatstitleFile, 2000); }, - success: function () { + success: function() + { setConnmonStatsTitle(); + if (databaseResetDone == 1) + { + currentNoCharts = 0; + $j('#Time_Format').val(getCookie('Time_Format', 'number')); + redrawAllCharts(); + databaseResetDone += 1; + } + setTimeout(getStatstitleFile, 4000); } }); } From c272dd5d3f031547f4457427ed0641984630746f Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 15 Jul 2024 00:42:43 -0700 Subject: [PATCH 11/33] Numerical comparison operator. Updated numerical comparison operator. --- connmonstats_www.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connmonstats_www.js b/connmonstats_www.js index a7af6b7..141a9c8 100644 --- a/connmonstats_www.js +++ b/connmonstats_www.js @@ -1383,7 +1383,7 @@ function getStatstitleFile() success: function() { setConnmonStatsTitle(); - if (databaseResetDone == 1) + if (databaseResetDone === 1) { currentNoCharts = 0; $j('#Time_Format').val(getCookie('Time_Format', 'number')); From 22970c85b529f604043e1cbe10156b81dc34b9c5 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Mon, 15 Jul 2024 18:07:16 -0700 Subject: [PATCH 12/33] Updated for 3.0.3 Release Added latest fixes for the 3.0.3 release version. --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 150400a..c3fa56f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v3.0.3 +14 July 2024 +* FIXED: Errors when loading the webGUI page on the 3006.102.1 F/W version. +* FIXED: Incorrect results when computing the free space available of a large-capacity USB-attached drive. This was preventing the user from resetting the database using the CLI menu. +* FIXED: "Reset Database" functionality on the CLI menu was correctly resetting the database file but the result was not reflected on the webGUI page where "old" entries were still shown as if the database had not been reset. + ## v3.0.2 06 January 2022 * FIXED: Only download CHANGELOG on upgrade if it doesn't exist From dfaf62a190a5d5130c4cda86116e8bdc4207d447 Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:15:37 -0700 Subject: [PATCH 13/33] Code improvement. Removed/modified code related to "var $j = jQuery.noConflict();" which is now considered obsolete. --- CHANGELOG.md | 3 +- README.md | 2 +- connmonstats_www.asp | 9 +- connmonstats_www.js | 287 +++++++++++++++++++++---------------------- 4 files changed, 150 insertions(+), 151 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3fa56f..9cd7753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # Changelog ## v3.0.3 -14 July 2024 +18 August 2024 * FIXED: Errors when loading the webGUI page on the 3006.102.1 F/W version. * FIXED: Incorrect results when computing the free space available of a large-capacity USB-attached drive. This was preventing the user from resetting the database using the CLI menu. * FIXED: "Reset Database" functionality on the CLI menu was correctly resetting the database file but the result was not reflected on the webGUI page where "old" entries were still shown as if the database had not been reset. +* CHANGED: Modified code related to "var $j = jQuery.noConflict();" which is now considered obsolete. ## v3.0.2 06 January 2022 diff --git a/README.md b/README.md index 92c0375..04426eb 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) ## v3.0.3 -### Updated on 2024-July-14 +### Updated on 2024-Aug-18 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. diff --git a/connmonstats_www.asp b/connmonstats_www.asp index cac756f..27f8b14 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -14,7 +14,8 @@ - + + @@ -22,8 +23,6 @@ - - @@ -36,7 +35,7 @@ diff --git a/connmonstats_www.js b/connmonstats_www.js index 141a9c8..21f9078 100644 --- a/connmonstats_www.js +++ b/connmonstats_www.js @@ -1,4 +1,3 @@ -var $j = jQuery.noConflict(); //avoid conflicts on John's fork (state.js) iziToast.settings({ title: 'connmon', @@ -162,27 +161,27 @@ function toggleFill() { function keyHandler(e) { switch (e.keyCode) { case 82: - $j(document).off('keydown'); + $(document).off('keydown'); resetZoom(); break; case 68: - $j(document).off('keydown'); + $(document).off('keydown'); toggleDragZoom(document.form.btnDragZoom); break; case 70: - $j(document).off('keydown'); + $(document).off('keydown'); toggleFill(); break; case 76: - $j(document).off('keydown'); + $(document).off('keydown'); toggleLines(); break; } } -$j(document).keydown(function (e) { keyHandler(e); }); -$j(document).keyup(function (e) { - $j(document).keydown(function (e) { +$(document).keydown(function (e) { keyHandler(e); }); +$(document).keyup(function (e) { + $(document).keydown(function (e) { keyHandler(e); }); }); @@ -191,11 +190,11 @@ function validateIP(forminput) { var inputvalue = forminput.value; var inputname = forminput.name; if (/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(inputvalue)) { - $j(forminput).removeClass('invalid'); + $(forminput).removeClass('invalid'); return true; } else { - $j(forminput).addClass('invalid'); + $(forminput).addClass('invalid'); return false; } } @@ -204,11 +203,11 @@ function validateDomain(forminput) { var inputvalue = forminput.value; var inputname = forminput.name; if (/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$/.test(inputvalue)) { - $j(forminput).removeClass('invalid'); + $(forminput).removeClass('invalid'); return true; } else { - $j(forminput).addClass('invalid'); + $(forminput).addClass('invalid'); return false; } } @@ -218,11 +217,11 @@ function validateNumberSetting(forminput, upperlimit, lowerlimit) { var inputvalue = forminput.value * 1; if (inputvalue > upperlimit || inputvalue < lowerlimit) { - $j(forminput).addClass('invalid'); + $(forminput).addClass('invalid'); return false; } else { - $j(forminput).removeClass('invalid'); + $(forminput).removeClass('invalid'); return true; } } @@ -333,11 +332,11 @@ function validateSchedule(forminput, hoursmins) { } if (validationfailed === 'true') { - $j(forminput).addClass('invalid'); + $(forminput).addClass('invalid'); return false; } else { - $j(forminput).removeClass('invalid'); + $(forminput).removeClass('invalid'); return true; } } @@ -349,7 +348,7 @@ function validateScheduleValue(forminput) { var upperlimit = 0; var lowerlimit = 1; - var unittype = $j('#everyxselect').val(); + var unittype = $('#everyxselect').val(); if (unittype === 'hours') { upperlimit = 24; @@ -359,11 +358,11 @@ function validateScheduleValue(forminput) { } if (inputvalue > upperlimit || inputvalue < lowerlimit || forminput.value.length < 1) { - $j(forminput).addClass('invalid'); + $(forminput).addClass('invalid'); return false; } else { - $j(forminput).removeClass('invalid'); + $(forminput).removeClass('invalid'); return true; } } @@ -580,10 +579,10 @@ function drawChartNoData(txtchartname, texttodisplay) { } function drawChart(txtchartname, txttitle, txtunity, bordercolourname, backgroundcolourname) { - var chartperiod = getChartPeriod($j('#' + txtchartname + '_Period option:selected').val()); - var chartinterval = getChartInterval($j('#' + txtchartname + '_Interval option:selected').val()); - var txtunitx = timeunitlist[$j('#' + txtchartname + '_Period option:selected').val()]; - var numunitx = intervallist[$j('#' + txtchartname + '_Period option:selected').val()]; + var chartperiod = getChartPeriod($('#' + txtchartname + '_Period option:selected').val()); + var chartinterval = getChartInterval($('#' + txtchartname + '_Interval option:selected').val()); + var txtunitx = timeunitlist[$('#' + txtchartname + '_Period option:selected').val()]; + var numunitx = intervallist[$('#' + txtchartname + '_Period option:selected').val()]; var zoompanxaxismax = moment(); var chartxaxismax = null; var chartxaxismin = moment().subtract(numunitx, txtunitx + 's'); @@ -597,8 +596,8 @@ function drawChart(txtchartname, txttitle, txtunity, bordercolourname, backgroun var chartData = dataobject.map(function (d) { return { x: d.Time, y: d.Value }; }); var objchartname = window['LineChart_' + txtchartname]; - var timeaxisformat = getTimeFormat($j('#Time_Format option:selected').val(), 'axis'); - var timetooltipformat = getTimeFormat($j('#Time_Format option:selected').val(), 'tooltip'); + var timeaxisformat = getTimeFormat($('#Time_Format option:selected').val(), 'axis'); + var timetooltipformat = getTimeFormat($('#Time_Format option:selected').val(), 'tooltip'); if (chartinterval === 'day') { charttype = 'bar'; @@ -667,7 +666,7 @@ function drawChart(txtchartname, txttitle, txtunity, bordercolourname, backgroun } }], yAxes: [{ - type: getChartScale($j('#' + txtchartname + '_Scale option:selected').val()), + type: getChartScale($('#' + txtchartname + '_Scale option:selected').val()), gridLines: { display: false, color: '#282828' }, scaleLabel: { display: false, labelString: txtunity }, ticks: { @@ -813,15 +812,15 @@ function changePeriod(e) { value = e.value * 1; name = e.id.substring(0, e.id.indexOf('_')); if (value === 2) { - $j('select[id="' + name + '_Period"] option:contains(24)').text('Today'); + $('select[id="' + name + '_Period"] option:contains(24)').text('Today'); } else { - $j('select[id="' + name + '_Period"] option:contains("Today")').text('Last 24 hours'); + $('select[id="' + name + '_Period"] option:contains("Today")').text('Last 24 hours'); } } function getLastXFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/lastx.htm', dataType: 'text', cache: false, @@ -847,10 +846,10 @@ function setGlobalDataset(txtchartname, dataobject) { iziToast.success({ message: 'Ping test complete' }); } for (var i = 0; i < metriclist.length; i++) { - $j('#' + metriclist[i] + '_Interval').val(getCookie(metriclist[i] + '_Interval', 'number')); + $('#' + metriclist[i] + '_Interval').val(getCookie(metriclist[i] + '_Interval', 'number')); changePeriod(document.getElementById(metriclist[i] + '_Interval')); - $j('#' + metriclist[i] + '_Period').val(getCookie(metriclist[i] + '_Period', 'number')); - $j('#' + metriclist[i] + '_Scale').val(getCookie(metriclist[i] + '_Scale', 'number')); + $('#' + metriclist[i] + '_Period').val(getCookie(metriclist[i] + '_Period', 'number')); + $('#' + metriclist[i] + '_Scale').val(getCookie(metriclist[i] + '_Scale', 'number')); drawChart(metriclist[i], titlelist[i], measureunitlist[i], bordercolourlist[i], backgroundcolourlist[i]); } getLastXFile(); @@ -924,16 +923,16 @@ function sortTable(sorttext) { } } - $j('#sortTableContainer').empty(); - $j('#sortTableContainer').append(buildLastXTable()); + $('#sortTableContainer').empty(); + $('#sortTableContainer').append(buildLastXTable()); - $j('.sortable').each(function (index, element) { + $('.sortable').each(function (index, element) { if (element.innerHTML.replace(/ \(.*\)/, '').replace(' ', '') === sortname) { if (sortdir === 'asc') { - $j(element).html(element.innerHTML + ' ↑'); + $(element).html(element.innerHTML + ' ↑'); } else { - $j(element).html(element.innerHTML + ' ↓'); + $(element).html(element.innerHTML + ' ↓'); } } }); @@ -962,10 +961,10 @@ function parseLastXData(data) { sortTable(sortname + ' ' + sortdir.replace('desc', '↑').replace('asc', '↓').trim()); } -$j.fn.serializeObject = function () { +$.fn.serializeObject = function () { var o = customSettings; var a = this.serializeArray(); - $j.each(a, function () { + $.each(a, function () { if (o[this.name] !== undefined && this.name.indexOf('connmon') !== -1 && this.name.indexOf('version') === -1 && this.name.indexOf('ipaddr') === -1 && this.name.indexOf('domain') === -1 && this.name.indexOf('schdays') === -1 && this.name.indexOf('pushover_list') === -1 && this.name.indexOf('pushover_list') === -1 && this.name.indexOf('webhook_list') === -1 && this.name !== 'connmon_notifications_pingtest' && this.name !== 'connmon_notifications_pingthreshold' && this.name !== 'connmon_notifications_jitterthreshold' && this.name !== 'connmon_notifications_linequalitythreshold') { @@ -981,8 +980,8 @@ $j.fn.serializeObject = function () { } if (this.name.indexOf('schdays') !== -1) { var schdays = []; - $j.each($j('input[name="connmon_schdays"]:checked'), function () { - schdays.push($j(this).val()); + $.each($('input[name="connmon_schdays"]:checked'), function () { + schdays.push($(this).val()); }); var schdaysstring = schdays.join(','); if (schdaysstring === 'Mon,Tues,Wed,Thurs,Fri,Sat,Sun') { @@ -992,29 +991,29 @@ $j.fn.serializeObject = function () { } if (this.name === 'connmon_notifications_pingtest') { var pingtesttypes = []; - $j.each($j('input[name="connmon_notifications_pingtest"]:checked'), function () { - pingtesttypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_pingtest"]:checked'), function () { + pingtesttypes.push($(this).val()); }); o['connmon_notifications_pingtest'] = pingtesttypes.join(','); } if (this.name === 'connmon_notifications_pingthreshold') { var pingthresholdtypes = []; - $j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'), function () { - pingthresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_pingthreshold"]:checked'), function () { + pingthresholdtypes.push($(this).val()); }); o['connmon_notifications_pingthreshold'] = pingthresholdtypes.join(','); } if (this.name === 'connmon_notifications_jitterthreshold') { var jitterthresholdtypes = []; - $j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'), function () { - jitterthresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_jitterthreshold"]:checked'), function () { + jitterthresholdtypes.push($(this).val()); }); o['connmon_notifications_jitterthreshold'] = jitterthresholdtypes.join(','); } if (this.name === 'connmon_notifications_linequalitythreshold') { var linequalitythresholdtypes = []; - $j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'), function () { - linequalitythresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_linequalitythreshold"]:checked'), function () { + linequalitythresholdtypes.push($(this).val()); }); o['connmon_notifications_linequalitythreshold'] = linequalitythresholdtypes.join(','); } @@ -1029,11 +1028,11 @@ $j.fn.serializeObject = function () { } }); - $j.each(this, function () { + $.each(this, function () { if (this.name.indexOf('schdays') !== -1) { var schdays = []; - $j.each($j('input[name="connmon_schdays"]:checked'), function () { - schdays.push($j(this).val()); + $.each($('input[name="connmon_schdays"]:checked'), function () { + schdays.push($(this).val()); }); if (schdays.length === 0) { o['connmon_schdays'] = '*'; @@ -1041,8 +1040,8 @@ $j.fn.serializeObject = function () { } if (this.name === 'connmon_notifications_pingtest') { var pingtesttypes = []; - $j.each($j('input[name="connmon_notifications_pingtest"]:checked'), function () { - pingtesttypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_pingtest"]:checked'), function () { + pingtesttypes.push($(this).val()); }); if (pingtesttypes.length === 0) { o['connmon_notifications_pingtest'] = 'None'; @@ -1050,8 +1049,8 @@ $j.fn.serializeObject = function () { } if (this.name === 'connmon_notifications_pingthreshold') { var pingthresholdtypes = []; - $j.each($j('input[name="connmon_notifications_pingthreshold"]:checked'), function () { - pingthresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_pingthreshold"]:checked'), function () { + pingthresholdtypes.push($(this).val()); }); if (pingthresholdtypes.length === 0) { o['connmon_notifications_pingthreshold'] = 'None'; @@ -1059,8 +1058,8 @@ $j.fn.serializeObject = function () { } if (this.name === 'connmon_notifications_jitterthreshold') { var jitterthresholdtypes = []; - $j.each($j('input[name="connmon_notifications_jitterthreshold"]:checked'), function () { - jitterthresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_jitterthreshold"]:checked'), function () { + jitterthresholdtypes.push($(this).val()); }); if (jitterthresholdtypes.length === 0) { o['connmon_notifications_jitterthreshold'] = 'None'; @@ -1068,8 +1067,8 @@ $j.fn.serializeObject = function () { } if (this.name === 'connmon_notifications_linequalitythreshold') { var linequalitythresholdtypes = []; - $j.each($j('input[name="connmon_notifications_linequalitythreshold"]:checked'), function () { - linequalitythresholdtypes.push($j(this).val()); + $.each($('input[name="connmon_notifications_linequalitythreshold"]:checked'), function () { + linequalitythresholdtypes.push($(this).val()); }); if (linequalitythresholdtypes.length === 0) { o['connmon_notifications_linequalitythreshold'] = 'None'; @@ -1079,10 +1078,10 @@ $j.fn.serializeObject = function () { return o; }; -$j.fn.serializeObjectEmail = function () { +$.fn.serializeObjectEmail = function () { var o = customSettings; var a = this.serializeArray(); - $j.each(a, function () { + $.each(a, function () { if (o[this.name] !== undefined && this.name.indexOf('email_') !== -1 && this.name.indexOf('show_pass') === -1) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; @@ -1117,20 +1116,20 @@ function errorCSVExport() { function jyNavigate(tab, type, tabslength) { for (var i = 1; i <= tabslength; i++) { if (tab === 0) { - $j('#' + type + 'Navigate' + i).show(); - $j('#btn' + type + 'Navigate' + i).css('background', ''); - $j('#btn' + type + 'Navigate0').css({ 'background': '#085F96', 'background': '-webkit-linear-gradient(#09639C 0%,#003047 100%)', 'background': '-o-linear-gradient(#09639C 0%,#003047 100%)', 'background': 'linear-gradient(#09639C 0%,#003047 100%)' }); + $('#' + type + 'Navigate' + i).show(); + $('#btn' + type + 'Navigate' + i).css('background', ''); + $('#btn' + type + 'Navigate0').css({ 'background': '#085F96', 'background': '-webkit-linear-gradient(#09639C 0%,#003047 100%)', 'background': '-o-linear-gradient(#09639C 0%,#003047 100%)', 'background': 'linear-gradient(#09639C 0%,#003047 100%)' }); } else { if (i === tab) { - $j('#' + type + 'Navigate' + i).show(); - $j('#btn' + type + 'Navigate' + i).css({ 'background': '#085F96', 'background': '-webkit-linear-gradient(#09639C 0%,#003047 100%)', 'background': '-o-linear-gradient(#09639C 0%,#003047 100%)', 'background': 'linear-gradient(#09639C 0%,#003047 100%)' }); + $('#' + type + 'Navigate' + i).show(); + $('#btn' + type + 'Navigate' + i).css({ 'background': '#085F96', 'background': '-webkit-linear-gradient(#09639C 0%,#003047 100%)', 'background': '-o-linear-gradient(#09639C 0%,#003047 100%)', 'background': 'linear-gradient(#09639C 0%,#003047 100%)' }); } else { - $j('#' + type + 'Navigate' + i).hide(); - $j('#btn' + type + 'Navigate' + i).css('background', ''); + $('#' + type + 'Navigate' + i).hide(); + $('#btn' + type + 'Navigate' + i).css('background', ''); } - $j('#btn' + type + 'Navigate0').css('background', ''); + $('#btn' + type + 'Navigate0').css('background', ''); } } } @@ -1145,28 +1144,28 @@ function automaticTestEnableDisable(forminput) { if (inputvalue === 'false') { for (var i = 0; i < fieldnames.length; i++) { - $j('input[name=' + prefix + '_' + fieldnames[i] + ']').addClass('disabled'); - $j('input[name=' + prefix + '_' + fieldnames[i] + ']').prop('disabled', true); + $('input[name=' + prefix + '_' + fieldnames[i] + ']').addClass('disabled'); + $('input[name=' + prefix + '_' + fieldnames[i] + ']').prop('disabled', true); } for (var i = 0; i < daysofweek.length; i++) { - $j('#' + prefix + '_' + daysofweek[i].toLowerCase()).prop('disabled', true); + $('#' + prefix + '_' + daysofweek[i].toLowerCase()).prop('disabled', true); } for (var i = 0; i < fieldnames2.length; i++) { - $j('[name=' + fieldnames2[i] + ']').addClass('disabled'); - $j('[name=' + fieldnames2[i] + ']').prop('disabled', true); + $('[name=' + fieldnames2[i] + ']').addClass('disabled'); + $('[name=' + fieldnames2[i] + ']').prop('disabled', true); } } else if (inputvalue === 'true') { for (var i = 0; i < fieldnames.length; i++) { - $j('input[name=' + prefix + '_' + fieldnames[i] + ']').removeClass('disabled'); - $j('input[name=' + prefix + '_' + fieldnames[i] + ']').prop('disabled', false); + $('input[name=' + prefix + '_' + fieldnames[i] + ']').removeClass('disabled'); + $('input[name=' + prefix + '_' + fieldnames[i] + ']').prop('disabled', false); } for (var i = 0; i < daysofweek.length; i++) { - $j('#' + prefix + '_' + daysofweek[i].toLowerCase()).prop('disabled', false); + $('#' + prefix + '_' + daysofweek[i].toLowerCase()).prop('disabled', false); } for (var i = 0; i < fieldnames2.length; i++) { - $j('[name=' + fieldnames2[i] + ']').removeClass('disabled'); - $j('[name=' + fieldnames2[i] + ']').prop('disabled', false); + $('[name=' + fieldnames2[i] + ']').removeClass('disabled'); + $('[name=' + fieldnames2[i] + ']').prop('disabled', false); } } } @@ -1178,11 +1177,11 @@ function scheduleModeToggle(forminput) { if (inputvalue === 'EveryX') { showhide('schfrequency', true); showhide('schcustom', false); - if ($j('#everyxselect').val() === 'hours') { + if ($('#everyxselect').val() === 'hours') { showhide('spanxhours', true); showhide('spanxminutes', false); } - else if ($j('#everyxselect').val() === 'minutes') { + else if ($('#everyxselect').val() === 'minutes') { showhide('spanxhours', false); showhide('spanxminutes', true); } @@ -1194,7 +1193,7 @@ function scheduleModeToggle(forminput) { } function getEmailConfFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/email_config.htm', dataType: 'text', cache: false, @@ -1222,20 +1221,20 @@ function getEmailConfFile() { } function getCustomactionInfo() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/customactioninfo.htm', dataType: 'text', error: function (xhr) { setTimeout(getCustomactionInfo, 1000); }, success: function (data) { - $j('#customaction_details').append('\n' + data); + $('#customaction_details').append('\n' + data); } }); } function getCustomactionList() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/customactionlist.htm', dataType: 'text', cache: false, @@ -1243,14 +1242,14 @@ function getCustomactionList() { setTimeout(getCustomactionList, 1000); }, success: function (data) { - $j('#customaction_details').html(data); + $('#customaction_details').html(data); getCustomactionInfo(); } }); } function getEmailpwFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/password.htm', dataType: 'text', cache: false, @@ -1269,7 +1268,7 @@ function getEmailpwFile() { } function getConfFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/config.htm', dataType: 'text', cache: false, @@ -1300,38 +1299,38 @@ function getConfFile() { else if (settingname.indexOf('schdays') !== -1) { if (settingvalue === '*') { for (var i2 = 0; i2 < daysofweek.length; i2++) { - $j('#connmon_' + daysofweek[i2].toLowerCase()).prop('checked', true); + $('#connmon_' + daysofweek[i2].toLowerCase()).prop('checked', true); } } else { var schdayarray = settingvalue.split(','); for (var i2 = 0; i2 < schdayarray.length; i2++) { - $j('#connmon_' + schdayarray[i2].toLowerCase()).prop('checked', true); + $('#connmon_' + schdayarray[i2].toLowerCase()).prop('checked', true); } } } else if (settingname === 'notifications_pingtest') { var pingtesttypearray = settingvalue.split(','); for (var i2 = 0; i2 < pingtesttypearray.length; i2++) { - $j('#connmon_pingtest_' + pingtesttypearray[i2].toLowerCase()).prop('checked', true); + $('#connmon_pingtest_' + pingtesttypearray[i2].toLowerCase()).prop('checked', true); } } else if (settingname === 'notifications_pingthreshold') { var pingthresholdtypearray = settingvalue.split(','); for (var i2 = 0; i2 < pingthresholdtypearray.length; i2++) { - $j('#connmon_pingthreshold_' + pingthresholdtypearray[i2].toLowerCase()).prop('checked', true); + $('#connmon_pingthreshold_' + pingthresholdtypearray[i2].toLowerCase()).prop('checked', true); } } else if (settingname === 'notifications_jitterthreshold') { var jitterthresholdtypearray = settingvalue.split(','); for (var i2 = 0; i2 < jitterthresholdtypearray.length; i2++) { - $j('#connmon_jitterthreshold_' + jitterthresholdtypearray[i2].toLowerCase()).prop('checked', true); + $('#connmon_jitterthreshold_' + jitterthresholdtypearray[i2].toLowerCase()).prop('checked', true); } } else if (settingname === 'notifications_linequalitythreshold') { var linequalitythresholdtypearray = settingvalue.split(','); for (var i2 = 0; i2 < linequalitythresholdtypearray.length; i2++) { - $j('#connmon_linequalitythreshold_' + linequalitythresholdtypearray[i2].toLowerCase()).prop('checked', true); + $('#connmon_linequalitythreshold_' + linequalitythresholdtypearray[i2].toLowerCase()).prop('checked', true); } } else if (settingname.indexOf('notifications_email_list') !== -1 || settingname.indexOf('notifications_pushover_list') !== -1 || settingname.indexOf('notifications_webhook_list') !== -1) { @@ -1342,7 +1341,7 @@ function getConfFile() { } if (settingname.indexOf('automated') !== -1) { - automaticTestEnableDisable($j('#connmon_auto_' + document.form.connmon_automated.value)[0]); + automaticTestEnableDisable($('#connmon_auto_' + document.form.connmon_automated.value)[0]); } if (settingname.indexOf('pingduration') !== -1) { @@ -1350,20 +1349,20 @@ function getConfFile() { } } - if ($j('[name=connmon_schhours]').val().indexOf('/') !== -1 && $j('[name=connmon_schmins]').val() * 1 === 0) { + if ($('[name=connmon_schhours]').val().indexOf('/') !== -1 && $('[name=connmon_schmins]').val() * 1 === 0) { document.form.schedulemode.value = 'EveryX'; document.form.everyxselect.value = 'hours'; - document.form.everyxvalue.value = $j('[name=connmon_schhours]').val().split('/')[1]; + document.form.everyxvalue.value = $('[name=connmon_schhours]').val().split('/')[1]; } - else if ($j('[name=connmon_schmins]').val().indexOf('/') !== -1 && $j('[name=connmon_schhours]').val() === '*') { + else if ($('[name=connmon_schmins]').val().indexOf('/') !== -1 && $('[name=connmon_schhours]').val() === '*') { document.form.schedulemode.value = 'EveryX'; document.form.everyxselect.value = 'minutes'; - document.form.everyxvalue.value = $j('[name=connmon_schmins]').val().split('/')[1]; + document.form.everyxvalue.value = $('[name=connmon_schmins]').val().split('/')[1]; } else { document.form.schedulemode.value = 'Custom'; } - scheduleModeToggle($j('#schmode_' + $j('[name=schedulemode]:checked').val().toLowerCase())[0]); + scheduleModeToggle($('#schmode_' + $('[name=schedulemode]:checked').val().toLowerCase())[0]); } }); } @@ -1374,7 +1373,7 @@ function getConfFile() { let databaseResetDone = 0; function getStatstitleFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/connstatstext.js', dataType: 'script', error: function (xhr) { @@ -1386,7 +1385,7 @@ function getStatstitleFile() if (databaseResetDone === 1) { currentNoCharts = 0; - $j('#Time_Format').val(getCookie('Time_Format', 'number')); + $('#Time_Format').val(getCookie('Time_Format', 'number')); redrawAllCharts(); databaseResetDone += 1; } @@ -1396,7 +1395,7 @@ function getStatstitleFile() } function getCronFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/cron.js', dataType: 'text', error: function (xhr) { @@ -1409,20 +1408,20 @@ function getCronFile() { } function getEmailInfo() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/emailinfo.htm', dataType: 'text', error: function (xhr) { setTimeout(getEmailInfo, 1000); }, success: function (data) { - $j('#emailinfo').html(data); + $('#emailinfo').html(data); } }); } function getChangelogFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/changelog.htm', dataType: 'text', cache: false, @@ -1430,7 +1429,7 @@ function getChangelogFile() { setTimeout(getChangelogFile, 5000); }, success: function (data) { - $j('#divchangelog').html(data); + $('#divchangelog').html(data); } }); } @@ -1453,7 +1452,7 @@ function getVersionNumber(versiontype) { } function getVersionChangelogFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/detect_changelog.js', dataType: 'script', error: function (xhr) { @@ -1461,9 +1460,9 @@ function getVersionChangelogFile() { }, success: function () { var serverver = getVersionNumber('server'); - $j('#connmon_version_server').html('Updated version available: ' + serverver + ''); - $j('#connmon_version_server').on('mouseover', function () { return overlib(changelog, 0, 0); }); - $j('#connmon_version_server')[0].onmouseout = nd; + $('#connmon_version_server').html('Updated version available: ' + serverver + ''); + $('#connmon_version_server').on('mouseover', function () { return overlib(changelog, 0, 0); }); + $('#connmon_version_server')[0].onmouseout = nd; } }); } @@ -1549,14 +1548,14 @@ function buildLastXTable() { function scriptUpdateLayout() { var localver = getVersionNumber('local'); var serverver = getVersionNumber('server'); - $j('#connmon_version_local').text(localver); + $('#connmon_version_local').text(localver); if (localver !== serverver && serverver !== 'N/A') { if (serverver.indexOf('hotfix') === -1) { getVersionChangelogFile(); } else { - $j('#connmon_version_server').text(serverver); + $('#connmon_version_server').text(serverver); } showhide('connmon_version_server', true); showhide('btnChkUpdate', false); @@ -1578,16 +1577,16 @@ function initial() { getEmailInfo(); getCronFile(); getChangelogFile(); - $j('#alternatelayout').prop('checked', AltLayout === 'false' ? false : true); - $j('#sortTableContainer').empty(); - $j('#sortTableContainer').append(buildLastXTableNoData()); + $('#alternatelayout').prop('checked', AltLayout === 'false' ? false : true); + $('#sortTableContainer').empty(); + $('#sortTableContainer').append(buildLastXTableNoData()); d3.csv('/ext/connmon/csv/CompleteResults.htm').then(function (data) { parseCSVExport(data); }).catch(function () { errorCSVExport(); }); - $j('#Time_Format').val(getCookie('Time_Format', 'number')); + $('#Time_Format').val(getCookie('Time_Format', 'number')); redrawAllCharts(); scriptUpdateLayout(); var starttab = getCookie('StartTab', 'number'); if (starttab === 0) { starttab = 1; } - $j('#starttab').val(starttab); + $('#starttab').val(starttab); jyNavigate(starttab, '', 5); jyNavigate(1, 'Chart', 3); jyNavigate(1, 'NotificationType', 4); @@ -1595,7 +1594,7 @@ function initial() { } function setStartTab(dropdown) { - setCookie('StartTab', $j(dropdown).val()); + setCookie('StartTab', $(dropdown).val()); } function passChecked(obj, showobj) { @@ -1609,7 +1608,7 @@ function toggleAlternateLayout(checkbox) { } function statusUpdate() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/detect_update.js', dataType: 'script', error: function (xhr) { @@ -1629,7 +1628,7 @@ function statusUpdate() { getVersionChangelogFile(); } else { - $j('#connmon_version_server').text('Updated version available: ' + updatestatus); + $('#connmon_version_server').text('Updated version available: ' + updatestatus); } iziToast.warning({ message: 'New version available!' }); showhide('btnChkUpdate', false); @@ -1637,7 +1636,7 @@ function statusUpdate() { } else { iziToast.info({ message: 'No updates available' }); - $j('#connmon_version_server').text('No updates available'); + $('#connmon_version_server').text('No updates available'); showhide('btnChkUpdate', true); showhide('btnDoUpdate', false); } @@ -1664,13 +1663,13 @@ function doUpdate() { function postConnTest() { currentNoCharts = 0; - $j('#Time_Format').val(getCookie('Time_Format', 'number')); + $('#Time_Format').val(getCookie('Time_Format', 'number')); getStatstitleFile(); setTimeout(redrawAllCharts, 3000); } function saveStatus(section) { - $j.ajax({ + $.ajax({ url: '/ext/connmon/detect_save.js', dataType: 'script', error: function (xhr) { @@ -1698,7 +1697,7 @@ function saveConfig(section) { switch (section) { case 'Navigate3': if (validateAll()) { - var disabledfields = $j('#' + section).find('[disabled]'); + var disabledfields = $('#' + section).find('[disabled]'); disabledfields.prop('disabled', false); if (document.form.pingtype.value * 1 === 0) { @@ -1725,7 +1724,7 @@ function saveConfig(section) { document.form.connmon_schmins.value = '*/' + everyxvalue; } } - document.getElementById('amng_custom').value = JSON.stringify($j('#' + section).find('input,select,textarea').serializeObject()); + document.getElementById('amng_custom').value = JSON.stringify($('#' + section).find('input,select,textarea').serializeObject()); document.formScriptActions.action_script.value = 'start_addon_settings;start_connmonconfig'; document.formScriptActions.submit(); disabledfields.prop('disabled', true); @@ -1739,9 +1738,9 @@ function saveConfig(section) { } break; case 'NotificationMethodNavigate1Config': - var disabledfields = $j('#' + section).find('[disabled]'); + var disabledfields = $('#' + section).find('[disabled]'); disabledfields.prop('disabled', false); - document.getElementById('amng_custom').value = JSON.stringify($j('#table_connmonemailconfig').find('input,select,textarea').serializeObject()); + document.getElementById('amng_custom').value = JSON.stringify($('#table_connmonemailconfig').find('input,select,textarea').serializeObject()); document.formScriptActions.action_script.value = 'start_addon_settings;start_connmonconfig'; document.formScriptActions.submit(); disabledfields.prop('disabled', true); @@ -1751,9 +1750,9 @@ function saveConfig(section) { setTimeout(saveStatus, 5000, section); break; case 'NotificationMethodNavigate1Email': - var disabledfields = $j('#' + section).find('[disabled]'); + var disabledfields = $('#' + section).find('[disabled]'); disabledfields.prop('disabled', false); - document.getElementById('amng_custom').value = JSON.stringify($j('#table_emailconfig').find('input,select,textarea').serializeObjectEmail()); + document.getElementById('amng_custom').value = JSON.stringify($('#table_emailconfig').find('input,select,textarea').serializeObjectEmail()); document.formScriptActions.action_script.value = 'start_addon_settings;start_connmonemailconfig'; document.formScriptActions.submit(); disabledfields.prop('disabled', true); @@ -1763,9 +1762,9 @@ function saveConfig(section) { setTimeout(saveStatus, 5000, section); break; default: - var disabledfields = $j('#' + section).find('[disabled]'); + var disabledfields = $('#' + section).find('[disabled]'); disabledfields.prop('disabled', false); - document.getElementById('amng_custom').value = JSON.stringify($j('#' + section).find('input,select,textarea').serializeObject()); + document.getElementById('amng_custom').value = JSON.stringify($('#' + section).find('input,select,textarea').serializeObject()); document.formScriptActions.action_script.value = 'start_addon_settings;start_connmonconfig'; document.formScriptActions.submit(); disabledfields.prop('disabled', true); @@ -1778,7 +1777,7 @@ function saveConfig(section) { } function getConntestResultFile() { - $j.ajax({ + $.ajax({ url: '/ext/connmon/ping-result.htm', dataType: 'text', cache: false, @@ -1788,14 +1787,14 @@ function getConntestResultFile() { success: function (data) { var lines = data.trim().split('\n'); data = lines.join('\n'); - $j('#conntest_output').html(data); + $('#conntest_output').html(data); document.getElementById('conntest_output').parentElement.parentElement.style.display = ''; } }); } function testStatus(testname) { - $j.ajax({ + $.ajax({ url: '/ext/connmon/detect_test.js', dataType: 'script', error: function (xhr) { @@ -1844,13 +1843,13 @@ function everyXToggle(forminput) { showhide('spanxminutes', true); } - validateScheduleValue($j('[name=everyxvalue]')[0]); + validateScheduleValue($('[name=everyxvalue]')[0]); } var pingcount = 2; function updateConntest() { pingcount++; - $j.ajax({ + $.ajax({ url: '/ext/connmon/detect_connmon.js', dataType: 'script', error: function (xhr) { @@ -1860,10 +1859,10 @@ function updateConntest() { if (connmonstatus === 'InProgress') { showhide('imgConnTest', true); showhide('conntest_text', true); - $j('#conntest_text').html('Ping test in progress - ' + pingcount + 's elapsed'); + $('#conntest_text').html('Ping test in progress - ' + pingcount + 's elapsed'); } else if (connmonstatus === 'GenerateCSV') { - $j('#conntest_text').html('Retrieving data for charts...'); + $('#conntest_text').html('Retrieving data for charts...'); } else if (connmonstatus === 'Done') { clearInterval(myinterval); @@ -1871,7 +1870,7 @@ function updateConntest() { intervalclear = true; pingcount = 2; getConntestResultFile(); - $j('#conntest_text').html('Refreshing charts...'); + $('#conntest_text').html('Refreshing charts...'); postConnTest(); } } @@ -1879,7 +1878,7 @@ function updateConntest() { pingcount = 2; clearInterval(myinterval); showhide('imgConnTest', false); - $j('#conntest_text').html('Scheduled ping test already running!'); + $('#conntest_text').html('Scheduled ping test already running!'); showhide('conntest_text', true); showhide('btnRunPingtest', true); document.getElementById('conntest_output').parentElement.parentElement.style.display = 'none'; @@ -1890,7 +1889,7 @@ function updateConntest() { pingcount = 2; clearInterval(myinterval); showhide('imgConnTest', false); - $j('#conntest_text').html('Specified ping server is not valid'); + $('#conntest_text').html('Specified ping server is not valid'); showhide('conntest_text', true); showhide('btnRunPingtest', true); document.getElementById('conntest_output').parentElement.parentElement.style.display = 'none'; @@ -1909,7 +1908,7 @@ function startConnTestInterval() { function runPingTest() { showhide('btnRunPingtest', false); - $j('#conntest_output').html(''); + $('#conntest_output').html(''); document.getElementById('conntest_output').parentElement.parentElement.style.display = 'none'; document.formScriptActions.action_script.value = 'start_addon_settings;start_connmon'; document.formScriptActions.submit(); From 0c97b851143daf78701e09b8d2e6909b9651b2ad Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:58:02 -0700 Subject: [PATCH 14/33] Fixed issue reported by Codacy Fixed an issue reported by the Codacy Static Analysis check: Function "buildLastXTable()" was used before it was defined. --- connmonstats_www.asp | 2 +- connmonstats_www.js | 134 +++++++++++++++++++++---------------------- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/connmonstats_www.asp b/connmonstats_www.asp index 27f8b14..b746b5a 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -53,7 +53,7 @@ function loadCustomSettings() { } } -function getCookie(e,t){if(null!==cookie.get("conn_"+e)){if("string"===t)return cookie.get("conn_"+e);if("number"===t)return 1*cookie.get("conn_"+e)}else{if("string"===t)return"";if("number"===t)return 0}}function setCookie(e,t){cookie.set("conn_"+e,t,3650)}iziToast.settings({title:"connmon",timeout:5e3,resetOnHover:!1,transitionIn:"fadeInRight",transitionOut:"fadeOutRight",position:"bottomRight",messageSize:"16px",theme:"light",displayMode:"replace",layout:2,drag:!1,pauseOnHover:!1});var daysofweek=["Mon","Tues","Wed","Thurs","Fri","Sat","Sun"],pingtestdur=60,arraysortlistlines=[],sortname="Time",sortdir="desc",AltLayout=getCookie("AltLayout","string");""===AltLayout&&(AltLayout="false");var maxNoCharts=27,currentNoCharts=0,ShowLines=getCookie("ShowLines","string"),ShowFill=getCookie("ShowFill","string");""===ShowFill&&(ShowFill="origin");var DragZoom=!0,ChartPan=!1,myinterval,intervalclear=!1,pingtestrunning=!1;Chart.defaults.global.defaultFontColor="#CCC",Chart.Tooltip.positioners.cursor=function(e,t){return t};var dataintervallist=["raw","hour","day"],metriclist=["Ping","Jitter","LineQuality"],titlelist=["Ping","Jitter","Quality"],measureunitlist=["ms","ms","%"],chartlist=["daily","weekly","monthly"],timeunitlist=["hour","day","day"],intervallist=[24,7,30],bordercolourlist=["#fc8500","#42ecf5","#fff"],backgroundcolourlist=["rgba(252,133,0,0.5)","rgba(66,236,245,0.5)","rgba(255,255,255,0.5)"];function settingHint(e){e*=1;for(var t=document.getElementsByTagName("a"),n=0;n* for all
Valid numbers between 0 and 23
comma (,) separate for multiple
dash (-) separate for a range"),2===e&&(i="Minute(s) of day to run ping test
(* for all
Valid numbers between 0 and 59
comma (,) separate for multiple
dash (-) separate for a range"),overlib(i,0,0)}function resetZoom(){for(var e=0;et||i0)o="true";else if(""===n[a])o="true";else if(n[a].startsWith("*/"))(isNaN(1*n[a].replace("*/",""))||1*n[a].replace("*/","")>i||1*n[a].replace("*/","")<0)&&(o="true");else if(-1!==n[a].indexOf("-"))if(n[a].startsWith("-"))o="true";else for(var s=n[a].split("-"),r=0;ri||1*s[r]<0?o="true":1*s[r+1]<1*s[r]&&(o="true","hours"===t?showhide("btnfixhours",!0):"mins"===t&&showhide("btnfixmins",!0));else(isNaN(1*n[a])||1*n[a]>i||1*n[a]<0)&&(o="true");return"true"===o?($(e).addClass("invalid"),!1):($(e).removeClass("invalid"),!0)}function validateScheduleValue(e){e.name;var t=1*e.value,n=0,i=$("#everyxselect").val();return"hours"===i?n=24:"minutes"===i&&(n=30),t>n||t<1||e.value.length<1?($(e).addClass("invalid"),!1):($(e).removeClass("invalid"),!0)}function validateAll(){var e=!1;return validateIP(document.form.connmon_ipaddr)||(e=!0),validateDomain(document.form.connmon_domain)||(e=!0),validateNumberSetting(document.form.connmon_pingduration,60,10)||(e=!0),validateNumberSetting(document.form.connmon_lastxresults,100,10)||(e=!0),validateNumberSetting(document.form.connmon_daystokeep,365,30)||(e=!0),"EveryX"===document.form.schedulemode.value?validateScheduleValue(document.form.everyxvalue)||(e=!0):"Custom"===document.form.schedulemode.value&&(validateSchedule(document.form.connmon_schhours,"hours")||(e=!0),validateSchedule(document.form.connmon_schmins,"mins")||(e=!0)),!e||(alert("Validation for some fields failed. Please correct invalid values and try again."),!1)}function fixCron(e){if("hours"===e){var t=document.form.connmon_schhours.value;document.form.connmon_schhours.value=t.split("-")[0]+"-23,0-"+t.split("-")[1],validateSchedule(document.form.connmon_schhours,"hours")}else if("mins"===e){t=document.form.connmon_schmins.value;document.form.connmon_schmins.value=t.split("-")[0]+"-59,0-"+t.split("-")[1],validateSchedule(document.form.connmon_schmins,"mins")}}function changePingType(e){var t=1*e.value;e.name;0===t?(document.getElementById("rowip").style.display="",document.getElementById("rowdomain").style.display="none"):(document.getElementById("rowip").style.display="none",document.getElementById("rowdomain").style.display="")}function getTimeFormat(e,t){var n;return e*=1,"axis"===t?0===e?n={millisecond:"HH:mm:ss.SSS",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm"}:1===e&&(n={millisecond:"h:mm:ss.SSS A",second:"h:mm:ss A",minute:"h:mm A",hour:"h A"}):"tooltip"===t&&(0===e?n="YYYY-MM-DD HH:mm:ss":1===e&&(n="YYYY-MM-DD h:mm:ss A")),n}function logarithmicFormatter(e,t,n){var i=this.options.scaleLabel.labelString;if("logarithmic"!==this.type)return isNaN(e)?e+" "+i:round(e,2).toFixed(2)+" "+i;var o=this.options.ticks.labels||{},a=o.index||["min","max"],s=o.significand||[1,2,5],r=e/Math.pow(10,Math.floor(Chart.helpers.log10(e))),l=!0===o.removeEmptyLines?void 0:"",c="";return 0===t?c="min":t===n.length-1&&(c="max"),"all"===o||-1!==s.indexOf(r)||-1!==a.indexOf(t)||-1!==a.indexOf(c)?0===e?"0 "+i:isNaN(e)?e+" "+i:round(e,2).toFixed(2)+" "+i:l}function getLimit(e,t,n,i){var o,a=0;return o="x"===t?e.map((function(e){return e.x})):e.map((function(e){return e.y})),a="max"===n?Math.max.apply(Math,o):Math.min.apply(Math,o),"max"===n&&0===a&&!1===i&&(a=1),a}function getYAxisMax(e){if("LineQuality"===e)return 100}function getAverage(e){for(var t=0,n=0;n (a."+sortfield+" > b."+sortfield+") ? 1 : ((b."+sortfield+" > a."+sortfield+") ? -1 : 0));"),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" < b."+sortfield+") ? 1 : ((b."+sortfield+" < a."+sortfield+") ? -1 : 0));"),sortdir="desc"):"number"===sorttype?-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000")));'),sortdir="asc"):-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000"))); '),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(b."+sortfield+'.replace("m","000")) - parseFloat(a.'+sortfield+'.replace("m","000")));'),sortdir="desc"):"date"===sorttype&&(-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),sortdir="desc")),$("#sortTableContainer").empty(),$("#sortTableContainer").append(buildLastXTable()),$(".sortable").each((function(e,t){t.innerHTML.replace(/ \(.*\)/,"").replace(" ","")===sortname&&("asc"===sortdir?$(t).html(t.innerHTML+" ↑"):$(t).html(t.innerHTML+" ↓"))}))}function parseLastXData(e){var t=e.split("\n");t=t.filter(Boolean),arraysortlistlines=[];for(var n=0;nUpdated version available: '+e+""),$("#connmon_version_server").on("mouseover",(function(){return overlib(changelog,0,0)})),$("#connmon_version_server")[0].onmouseout=nd}})}function buildLastXTableNoData(){return"",'',"Data loading...","","","",'
Data loading...
'}function buildLastXTable(){var e='';if("false"===AltLayout){e+='',e+='',e+='',e+='',e+='',e+='',e+='',e+="",e+='',e+='',e+='',e+='',e+='',e+="",e+="",e+="",e+='';for(var t=0;t',e+="",e+="",e+="",e+="",e+="",e+="",e+=""}else{e+='',e+='',e+='',e+='',e+='',e+='',e+='',e+="",e+='',e+='',e+='',e+="",e+='',e+='',e+="",e+="",e+='';for(t=0;t',e+="",e+="",e+="",e+="",e+="",e+="",e+=""}return e+="",e+="
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
"+arraysortlistlines[t].Time+""+arraysortlistlines[t].Target+""+arraysortlistlines[t].Duration+""+arraysortlistlines[t].Ping+""+arraysortlistlines[t].Jitter+""+arraysortlistlines[t].LineQuality+"
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
"+arraysortlistlines[t].Time+""+arraysortlistlines[t].Ping+""+arraysortlistlines[t].Jitter+""+arraysortlistlines[t].LineQuality+""+arraysortlistlines[t].Target+""+arraysortlistlines[t].Duration+"
"}function scriptUpdateLayout(){var e=getVersionNumber("local"),t=getVersionNumber("server");$("#connmon_version_local").text(e),e!==t&&"N/A"!==t&&(-1===t.indexOf("hotfix")?getVersionChangelogFile():$("#connmon_version_server").text(t),showhide("connmon_version_server",!0),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0))}function initial(){setCurrentPage(),loadCustomSettings(),show_menu(),document.formScriptActions.action_script.value="start_addon_settings;start_connmoncustomactionlist;start_connmonemailpassword",document.formScriptActions.submit(),setTimeout(getCustomactionList,1e4),setTimeout(getEmailpwFile,1e4),getConfFile(),getEmailConfFile(),getStatstitleFile(),getEmailInfo(),getCronFile(),getChangelogFile(),$("#alternatelayout").prop("checked","false"!==AltLayout),$("#sortTableContainer").empty(),$("#sortTableContainer").append(buildLastXTableNoData()),d3.csv("/ext/connmon/csv/CompleteResults.htm").then((function(e){parseCSVExport(e)})).catch((function(){errorCSVExport()})),$("#Time_Format").val(getCookie("Time_Format","number")),redrawAllCharts(),scriptUpdateLayout();var e=getCookie("StartTab","number");0===e&&(e=1),$("#starttab").val(e),jyNavigate(e,"",5),jyNavigate(1,"Chart",3),jyNavigate(1,"NotificationType",4),jyNavigate(1,"NotificationMethod",6)}function setStartTab(e){setCookie("StartTab",$(e).val())}function passChecked(e,t){switchType(e,t.checked,!0)}function toggleAlternateLayout(e){setCookie("AltLayout",AltLayout=e.checked.toString()),sortTable(sortname+" "+sortdir.replace("desc","↑").replace("asc","↓").trim())}function statusUpdate(){$.ajax({url:"/ext/connmon/detect_update.js",dataType:"script",error:function(e){setTimeout(statusUpdate,1e3)},success:function(){"InProgress"===updatestatus?setTimeout(statusUpdate,1e3):(iziToast.destroy(),document.getElementById("imgChkUpdate").style.display="none",showhide("connmon_version_server",!0),"None"!==updatestatus?(customSettings.connmon_version_server=updatestatus,-1===updatestatus.indexOf("hotfix")?getVersionChangelogFile():$("#connmon_version_server").text("Updated version available: "+updatestatus),iziToast.warning({message:"New version available!"}),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)):(iziToast.info({message:"No updates available"}),$("#connmon_version_server").text("No updates available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)))}})}function checkUpdate(){document.formScriptActions.action_script.value="start_addon_settings;start_connmoncheckupdate",document.formScriptActions.submit(),showhide("btnChkUpdate",!1),document.getElementById("imgChkUpdate").style.display="",iziToast.info({message:"Checking for updates...",timeout:!1}),setTimeout(statusUpdate,2e3)}function doUpdate(){document.form.action_script.value="start_connmondoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function postConnTest(){currentNoCharts=0,$("#Time_Format").val(getCookie("Time_Format","number")),getStatstitleFile(),setTimeout(redrawAllCharts,3e3)}function saveStatus(e){$.ajax({url:"/ext/connmon/detect_save.js",dataType:"script",error:function(t){setTimeout(saveStatus,1e3,e)},success:function(){"InProgress"===savestatus?setTimeout(saveStatus,1e3,e):(showhide("imgSave"+e,!1),"Success"===savestatus&&(iziToast.destroy(),iziToast.success({message:"Save successful"}),showhide("btnSave"+e,!0),loadCustomSettings(),"Navigate3"===e&&postConnTest()))}})}function saveConfig(e){switch(e){case"Navigate3":if(!validateAll())return!1;if((n=$("#"+e).find("[disabled]")).prop("disabled",!1),1*document.form.pingtype.value==0?document.form.connmon_pingserver.value=document.form.connmon_ipaddr.value:1*document.form.pingtype.value==1&&(document.form.connmon_pingserver.value=document.form.connmon_domain.value),"EveryX"===document.form.schedulemode.value)if("hours"===document.form.everyxselect.value){var t=1*document.form.everyxvalue.value;document.form.connmon_schmins.value=0,document.form.connmon_schhours.value=24===t?0:"*/"+t}else if("minutes"===document.form.everyxselect.value){document.form.connmon_schhours.value="*";t=1*document.form.everyxvalue.value;document.form.connmon_schmins.value="*/"+t}document.getElementById("amng_custom").value=JSON.stringify($("#"+e).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;case"NotificationMethodNavigate1Config":(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#table_connmonemailconfig").find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;case"NotificationMethodNavigate1Email":(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#table_emailconfig").find("input,select,textarea").serializeObjectEmail()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonemailconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;default:var n;(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#"+e).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break}}function getConntestResultFile(){$.ajax({url:"/ext/connmon/ping-result.htm",dataType:"text",cache:!1,error:function(e){setTimeout(getConntestResultFile,500)},success:function(e){var t=e.trim().split("\n");e=t.join("\n"),$("#conntest_output").html(e),document.getElementById("conntest_output").parentElement.parentElement.style.display=""}})}function testStatus(e){$.ajax({url:"/ext/connmon/detect_test.js",dataType:"script",error:function(t){setTimeout(testStatus,1e3,e)},success:function(){"InProgress"===teststatus?setTimeout(testStatus,1e3,e):(showhide("img"+e,!1),iziToast.destroy(),showhide("btn"+e,!0),"Success"===teststatus?iziToast.success({message:"Test successful"}):iziToast.error({message:"Test failed - please check configuration"}))}})}function testNotification(e){confirm("If you have made any changes, you will need to save them first. Do you want to continue?")&&(showhide("btn"+e,!1),document.formScriptActions.action_script.value="start_addon_settings;start_connmon"+e,document.formScriptActions.submit(),showhide("img"+e,!0),setTimeout(testStatus,1e3,e),iziToast.info({message:"Running test...",timeout:!1}))}function everyXToggle(e){e.name;var t=e.value;"hours"===t?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"===t&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),validateScheduleValue($("[name=everyxvalue]")[0])}var pingcount=2;function updateConntest(){pingcount++,$.ajax({url:"/ext/connmon/detect_connmon.js",dataType:"script",error:function(e){},success:function(){"InProgress"===connmonstatus?(showhide("imgConnTest",!0),showhide("conntest_text",!0),$("#conntest_text").html("Ping test in progress - "+pingcount+"s elapsed")):"GenerateCSV"===connmonstatus?$("#conntest_text").html("Retrieving data for charts..."):"Done"===connmonstatus?(clearInterval(myinterval),!1===intervalclear&&(intervalclear=!0,pingcount=2,getConntestResultFile(),$("#conntest_text").html("Refreshing charts..."),postConnTest())):"LOCKED"===connmonstatus?(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$("#conntest_text").html("Scheduled ping test already running!"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - scheduled ping test already running!"})):"InvalidServer"===connmonstatus&&(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$("#conntest_text").html("Specified ping server is not valid"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - Specified ping server is not valid"}))}})}function startConnTestInterval(){intervalclear=!1,pingtestrunning=!0,myinterval=setInterval(updateConntest,1e3)}function runPingTest(){showhide("btnRunPingtest",!1),$("#conntest_output").html(""),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",document.formScriptActions.action_script.value="start_addon_settings;start_connmon",document.formScriptActions.submit(),showhide("imgConnTest",!0),showhide("conntest_text",!1),setTimeout(startConnTestInterval,5e3),iziToast.info({message:"Ping test started",timeout:!1})}function changeAllCharts(e){value=1*e.value,name=e.id.substring(0,e.id.indexOf("_")),setCookie(e.id,value);for(var t=0;t* for all
Valid numbers between 0 and 23
comma (,) separate for multiple
dash (-) separate for a range"),2===e&&(i="Minute(s) of day to run ping test
(* for all
Valid numbers between 0 and 59
comma (,) separate for multiple
dash (-) separate for a range"),overlib(i,0,0)}function resetZoom(){for(var e=0;et||i0)o="true";else if(""===n[a])o="true";else if(n[a].startsWith("*/"))(isNaN(1*n[a].replace("*/",""))||1*n[a].replace("*/","")>i||1*n[a].replace("*/","")<0)&&(o="true");else if(-1!==n[a].indexOf("-"))if(n[a].startsWith("-"))o="true";else for(var s=n[a].split("-"),r=0;ri||1*s[r]<0?o="true":1*s[r+1]<1*s[r]&&(o="true","hours"===t?showhide("btnfixhours",!0):"mins"===t&&showhide("btnfixmins",!0));else(isNaN(1*n[a])||1*n[a]>i||1*n[a]<0)&&(o="true");return"true"===o?($(e).addClass("invalid"),!1):($(e).removeClass("invalid"),!0)}function validateScheduleValue(e){e.name;var t=1*e.value,n=0,i=$("#everyxselect").val();return"hours"===i?n=24:"minutes"===i&&(n=30),t>n||t<1||e.value.length<1?($(e).addClass("invalid"),!1):($(e).removeClass("invalid"),!0)}function validateAll(){var e=!1;return validateIP(document.form.connmon_ipaddr)||(e=!0),validateDomain(document.form.connmon_domain)||(e=!0),validateNumberSetting(document.form.connmon_pingduration,60,10)||(e=!0),validateNumberSetting(document.form.connmon_lastxresults,100,10)||(e=!0),validateNumberSetting(document.form.connmon_daystokeep,365,30)||(e=!0),"EveryX"===document.form.schedulemode.value?validateScheduleValue(document.form.everyxvalue)||(e=!0):"Custom"===document.form.schedulemode.value&&(validateSchedule(document.form.connmon_schhours,"hours")||(e=!0),validateSchedule(document.form.connmon_schmins,"mins")||(e=!0)),!e||(alert("Validation for some fields failed. Please correct invalid values and try again."),!1)}function fixCron(e){if("hours"===e){var t=document.form.connmon_schhours.value;document.form.connmon_schhours.value=t.split("-")[0]+"-23,0-"+t.split("-")[1],validateSchedule(document.form.connmon_schhours,"hours")}else if("mins"===e){t=document.form.connmon_schmins.value;document.form.connmon_schmins.value=t.split("-")[0]+"-59,0-"+t.split("-")[1],validateSchedule(document.form.connmon_schmins,"mins")}}function changePingType(e){var t=1*e.value;e.name;0===t?(document.getElementById("rowip").style.display="",document.getElementById("rowdomain").style.display="none"):(document.getElementById("rowip").style.display="none",document.getElementById("rowdomain").style.display="")}function getTimeFormat(e,t){var n;return e*=1,"axis"===t?0===e?n={millisecond:"HH:mm:ss.SSS",second:"HH:mm:ss",minute:"HH:mm",hour:"HH:mm"}:1===e&&(n={millisecond:"h:mm:ss.SSS A",second:"h:mm:ss A",minute:"h:mm A",hour:"h A"}):"tooltip"===t&&(0===e?n="YYYY-MM-DD HH:mm:ss":1===e&&(n="YYYY-MM-DD h:mm:ss A")),n}function logarithmicFormatter(e,t,n){var i=this.options.scaleLabel.labelString;if("logarithmic"!==this.type)return isNaN(e)?e+" "+i:round(e,2).toFixed(2)+" "+i;var o=this.options.ticks.labels||{},a=o.index||["min","max"],s=o.significand||[1,2,5],r=e/Math.pow(10,Math.floor(Chart.helpers.log10(e))),l=!0===o.removeEmptyLines?void 0:"",c="";return 0===t?c="min":t===n.length-1&&(c="max"),"all"===o||-1!==s.indexOf(r)||-1!==a.indexOf(t)||-1!==a.indexOf(c)?0===e?"0 "+i:isNaN(e)?e+" "+i:round(e,2).toFixed(2)+" "+i:l}function getLimit(e,t,n,i){var o,a=0;return o="x"===t?e.map((function(e){return e.x})):e.map((function(e){return e.y})),a="max"===n?Math.max.apply(Math,o):Math.min.apply(Math,o),"max"===n&&0===a&&!1===i&&(a=1),a}function getYAxisMax(e){if("LineQuality"===e)return 100}function getAverage(e){for(var t=0,n=0;n',e+='',e+='',e+='',e+='',e+='',e+='',e+="",e+='Time',e+='Target',e+='Duration (s)',e+='Ping (ms)',e+='Jitter (ms)',e+="Line Quality (%)",e+="",e+="",e+='';for(var t=0;t',e+=""+arraysortlistlines[t].Time+"",e+=""+arraysortlistlines[t].Target+"",e+=""+arraysortlistlines[t].Duration+"",e+=""+arraysortlistlines[t].Ping+"",e+=""+arraysortlistlines[t].Jitter+"",e+=""+arraysortlistlines[t].LineQuality+"",e+=""}else{e+='',e+='',e+='',e+='',e+='',e+='',e+='',e+="",e+='Time',e+='Ping (ms)',e+='Jitter (ms)',e+="Line Quality (%)",e+='Target',e+='Duration (s)',e+="",e+="",e+='';for(t=0;t',e+=""+arraysortlistlines[t].Time+"",e+=""+arraysortlistlines[t].Ping+"",e+=""+arraysortlistlines[t].Jitter+"",e+=""+arraysortlistlines[t].LineQuality+"",e+=""+arraysortlistlines[t].Target+"",e+=""+arraysortlistlines[t].Duration+"",e+=""}return e+="",e+=""}function sortTable(sorttext){sortname=sorttext.replace("↑","").replace("↓","").trim();var sorttype="number",sortfield=sortname;switch(sortname){case"Time":sorttype="date";break;case"Target":sorttype="string";break}"string"===sorttype?-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" > b."+sortfield+") ? 1 : ((b."+sortfield+" > a."+sortfield+") ? -1 : 0));"),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => (a."+sortfield+" < b."+sortfield+") ? 1 : ((b."+sortfield+" < a."+sortfield+") ? -1 : 0));"),sortdir="desc"):"number"===sorttype?-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000")));'),sortdir="asc"):-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(a."+sortfield+'.replace("m","000")) - parseFloat(b.'+sortfield+'.replace("m","000"))); '),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => parseFloat(b."+sortfield+'.replace("m","000")) - parseFloat(a.'+sortfield+'.replace("m","000")));'),sortdir="desc"):"date"===sorttype&&(-1===sorttext.indexOf("↓")&&-1===sorttext.indexOf("↑")||-1!==sorttext.indexOf("↓")?(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(a."+sortfield+") - new Date(b."+sortfield+"));"),sortdir="asc"):(eval("arraysortlistlines = arraysortlistlines.sort((a,b) => new Date(b."+sortfield+") - new Date(a."+sortfield+"));"),sortdir="desc")),$("#sortTableContainer").empty(),$("#sortTableContainer").append(buildLastXTable()),$(".sortable").each((function(e,t){t.innerHTML.replace(/ \(.*\)/,"").replace(" ","")===sortname&&("asc"===sortdir?$(t).html(t.innerHTML+" ↑"):$(t).html(t.innerHTML+" ↓"))}))}function parseLastXData(e){var t=e.split("\n");t=t.filter(Boolean),arraysortlistlines=[];for(var n=0;nUpdated version available: '+e+""),$("#connmon_version_server").on("mouseover",(function(){return overlib(changelog,0,0)})),$("#connmon_version_server")[0].onmouseout=nd}})}function buildLastXTableNoData(){return"",'',"Data loading...","","","",'
Data loading...
'}function scriptUpdateLayout(){var e=getVersionNumber("local"),t=getVersionNumber("server");$("#connmon_version_local").text(e),e!==t&&"N/A"!==t&&(-1===t.indexOf("hotfix")?getVersionChangelogFile():$("#connmon_version_server").text(t),showhide("connmon_version_server",!0),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0))}function initial(){setCurrentPage(),loadCustomSettings(),show_menu(),document.formScriptActions.action_script.value="start_addon_settings;start_connmoncustomactionlist;start_connmonemailpassword",document.formScriptActions.submit(),setTimeout(getCustomactionList,1e4),setTimeout(getEmailpwFile,1e4),getConfFile(),getEmailConfFile(),getStatstitleFile(),getEmailInfo(),getCronFile(),getChangelogFile(),$("#alternatelayout").prop("checked","false"!==AltLayout),$("#sortTableContainer").empty(),$("#sortTableContainer").append(buildLastXTableNoData()),d3.csv("/ext/connmon/csv/CompleteResults.htm").then((function(e){parseCSVExport(e)})).catch((function(){errorCSVExport()})),$("#Time_Format").val(getCookie("Time_Format","number")),redrawAllCharts(),scriptUpdateLayout();var e=getCookie("StartTab","number");0===e&&(e=1),$("#starttab").val(e),jyNavigate(e,"",5),jyNavigate(1,"Chart",3),jyNavigate(1,"NotificationType",4),jyNavigate(1,"NotificationMethod",6)}function setStartTab(e){setCookie("StartTab",$(e).val())}function passChecked(e,t){switchType(e,t.checked,!0)}function toggleAlternateLayout(e){setCookie("AltLayout",AltLayout=e.checked.toString()),sortTable(sortname+" "+sortdir.replace("desc","↑").replace("asc","↓").trim())}function statusUpdate(){$.ajax({url:"/ext/connmon/detect_update.js",dataType:"script",error:function(e){setTimeout(statusUpdate,1e3)},success:function(){"InProgress"===updatestatus?setTimeout(statusUpdate,1e3):(iziToast.destroy(),document.getElementById("imgChkUpdate").style.display="none",showhide("connmon_version_server",!0),"None"!==updatestatus?(customSettings.connmon_version_server=updatestatus,-1===updatestatus.indexOf("hotfix")?getVersionChangelogFile():$("#connmon_version_server").text("Updated version available: "+updatestatus),iziToast.warning({message:"New version available!"}),showhide("btnChkUpdate",!1),showhide("btnDoUpdate",!0)):(iziToast.info({message:"No updates available"}),$("#connmon_version_server").text("No updates available"),showhide("btnChkUpdate",!0),showhide("btnDoUpdate",!1)))}})}function checkUpdate(){document.formScriptActions.action_script.value="start_addon_settings;start_connmoncheckupdate",document.formScriptActions.submit(),showhide("btnChkUpdate",!1),document.getElementById("imgChkUpdate").style.display="",iziToast.info({message:"Checking for updates...",timeout:!1}),setTimeout(statusUpdate,2e3)}function doUpdate(){document.form.action_script.value="start_connmondoupdate",document.form.action_wait.value=10,showLoading(),document.form.submit()}function postConnTest(){currentNoCharts=0,$("#Time_Format").val(getCookie("Time_Format","number")),getStatstitleFile(),setTimeout(redrawAllCharts,3e3)}function saveStatus(e){$.ajax({url:"/ext/connmon/detect_save.js",dataType:"script",error:function(t){setTimeout(saveStatus,1e3,e)},success:function(){"InProgress"===savestatus?setTimeout(saveStatus,1e3,e):(showhide("imgSave"+e,!1),"Success"===savestatus&&(iziToast.destroy(),iziToast.success({message:"Save successful"}),showhide("btnSave"+e,!0),loadCustomSettings(),"Navigate3"===e&&postConnTest()))}})}function saveConfig(e){switch(e){case"Navigate3":if(!validateAll())return!1;if((n=$("#"+e).find("[disabled]")).prop("disabled",!1),1*document.form.pingtype.value==0?document.form.connmon_pingserver.value=document.form.connmon_ipaddr.value:1*document.form.pingtype.value==1&&(document.form.connmon_pingserver.value=document.form.connmon_domain.value),"EveryX"===document.form.schedulemode.value)if("hours"===document.form.everyxselect.value){var t=1*document.form.everyxvalue.value;document.form.connmon_schmins.value=0,document.form.connmon_schhours.value=24===t?0:"*/"+t}else if("minutes"===document.form.everyxselect.value){document.form.connmon_schhours.value="*";t=1*document.form.everyxvalue.value;document.form.connmon_schmins.value="*/"+t}document.getElementById("amng_custom").value=JSON.stringify($("#"+e).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;case"NotificationMethodNavigate1Config":(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#table_connmonemailconfig").find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;case"NotificationMethodNavigate1Email":(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#table_emailconfig").find("input,select,textarea").serializeObjectEmail()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonemailconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break;default:var n;(n=$("#"+e).find("[disabled]")).prop("disabled",!1),document.getElementById("amng_custom").value=JSON.stringify($("#"+e).find("input,select,textarea").serializeObject()),document.formScriptActions.action_script.value="start_addon_settings;start_connmonconfig",document.formScriptActions.submit(),n.prop("disabled",!0),showhide("btnSave"+e,!1),showhide("imgSave"+e,!0),iziToast.info({message:"Saving...",timeout:!1}),setTimeout(saveStatus,5e3,e);break}}function getConntestResultFile(){$.ajax({url:"/ext/connmon/ping-result.htm",dataType:"text",cache:!1,error:function(e){setTimeout(getConntestResultFile,500)},success:function(e){var t=e.trim().split("\n");e=t.join("\n"),$("#conntest_output").html(e),document.getElementById("conntest_output").parentElement.parentElement.style.display=""}})}function testStatus(e){$.ajax({url:"/ext/connmon/detect_test.js",dataType:"script",error:function(t){setTimeout(testStatus,1e3,e)},success:function(){"InProgress"===teststatus?setTimeout(testStatus,1e3,e):(showhide("img"+e,!1),iziToast.destroy(),showhide("btn"+e,!0),"Success"===teststatus?iziToast.success({message:"Test successful"}):iziToast.error({message:"Test failed - please check configuration"}))}})}function testNotification(e){confirm("If you have made any changes, you will need to save them first. Do you want to continue?")&&(showhide("btn"+e,!1),document.formScriptActions.action_script.value="start_addon_settings;start_connmon"+e,document.formScriptActions.submit(),showhide("img"+e,!0),setTimeout(testStatus,1e3,e),iziToast.info({message:"Running test...",timeout:!1}))}function everyXToggle(e){e.name;var t=e.value;"hours"===t?(showhide("spanxhours",!0),showhide("spanxminutes",!1)):"minutes"===t&&(showhide("spanxhours",!1),showhide("spanxminutes",!0)),validateScheduleValue($("[name=everyxvalue]")[0])}var pingcount=2;function updateConntest(){pingcount++,$.ajax({url:"/ext/connmon/detect_connmon.js",dataType:"script",error:function(e){},success:function(){"InProgress"===connmonstatus?(showhide("imgConnTest",!0),showhide("conntest_text",!0),$("#conntest_text").html("Ping test in progress - "+pingcount+"s elapsed")):"GenerateCSV"===connmonstatus?$("#conntest_text").html("Retrieving data for charts..."):"Done"===connmonstatus?(clearInterval(myinterval),!1===intervalclear&&(intervalclear=!0,pingcount=2,getConntestResultFile(),$("#conntest_text").html("Refreshing charts..."),postConnTest())):"LOCKED"===connmonstatus?(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$("#conntest_text").html("Scheduled ping test already running!"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - scheduled ping test already running!"})):"InvalidServer"===connmonstatus&&(pingcount=2,clearInterval(myinterval),showhide("imgConnTest",!1),$("#conntest_text").html("Specified ping server is not valid"),showhide("conntest_text",!0),showhide("btnRunPingtest",!0),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",iziToast.destroy(),iziToast.error({message:"Ping test failed - Specified ping server is not valid"}))}})}function startConnTestInterval(){intervalclear=!1,pingtestrunning=!0,myinterval=setInterval(updateConntest,1e3)}function runPingTest(){showhide("btnRunPingtest",!1),$("#conntest_output").html(""),document.getElementById("conntest_output").parentElement.parentElement.style.display="none",document.formScriptActions.action_script.value="start_addon_settings;start_connmon",document.formScriptActions.submit(),showhide("imgConnTest",!0),showhide("conntest_text",!1),setTimeout(startConnTestInterval,5e3),iziToast.info({message:"Ping test started",timeout:!1})}function changeAllCharts(e){value=1*e.value,name=e.id.substring(0,e.id.indexOf("_")),setCookie(e.id,value);for(var t=0;t diff --git a/connmonstats_www.js b/connmonstats_www.js index 21f9078..b87ddc9 100644 --- a/connmonstats_www.js +++ b/connmonstats_www.js @@ -867,6 +867,73 @@ function redrawAllCharts() { } } +function buildLastXTable() { + var tablehtml = ''; + + if (AltLayout === 'false') { + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + for (var i = 0; i < arraysortlistlines.length; i++) { + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + } + } + else { + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + for (var i = 0; i < arraysortlistlines.length; i++) { + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + tablehtml += ''; + } + } + + tablehtml += ''; + tablehtml += '
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
' + arraysortlistlines[i].Time + '' + arraysortlistlines[i].Target + '' + arraysortlistlines[i].Duration + '' + arraysortlistlines[i].Ping + '' + arraysortlistlines[i].Jitter + '' + arraysortlistlines[i].LineQuality + '
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
' + arraysortlistlines[i].Time + '' + arraysortlistlines[i].Ping + '' + arraysortlistlines[i].Jitter + '' + arraysortlistlines[i].LineQuality + '' + arraysortlistlines[i].Target + '' + arraysortlistlines[i].Duration + '
'; + return tablehtml; +} + function sortTable(sorttext) { sortname = sorttext.replace('↑', '').replace('↓', '').trim(); var sorttype = 'number'; @@ -1478,73 +1545,6 @@ function buildLastXTableNoData() { return tablehtml; } -function buildLastXTable() { - var tablehtml = ''; - - if (AltLayout === 'false') { - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - for (var i = 0; i < arraysortlistlines.length; i++) { - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - } - } - else { - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - for (var i = 0; i < arraysortlistlines.length; i++) { - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - tablehtml += ''; - } - } - - tablehtml += ''; - tablehtml += '
TimeTargetDuration (s)Ping (ms)Jitter (ms)Line Quality (%)
' + arraysortlistlines[i].Time + '' + arraysortlistlines[i].Target + '' + arraysortlistlines[i].Duration + '' + arraysortlistlines[i].Ping + '' + arraysortlistlines[i].Jitter + '' + arraysortlistlines[i].LineQuality + '
TimePing (ms)Jitter (ms)Line Quality (%)TargetDuration (s)
' + arraysortlistlines[i].Time + '' + arraysortlistlines[i].Ping + '' + arraysortlistlines[i].Jitter + '' + arraysortlistlines[i].LineQuality + '' + arraysortlistlines[i].Target + '' + arraysortlistlines[i].Duration + '
'; - return tablehtml; -} - function scriptUpdateLayout() { var localver = getVersionNumber('local'); var serverver = getVersionNumber('server'); From e9767088b1fa2b90b96671a7e423a1744164fe2d Mon Sep 17 00:00:00 2001 From: Martinski <119833648+Martinski4GitHub@users.noreply.github.com> Date: Sun, 22 Dec 2024 19:49:07 -0800 Subject: [PATCH 15/33] Functionality Improvements 1) IMPROVED: Modified all SQLite3 calls to capture and log errors in the system log. 2) IMPROVED: Modified SQLite3 configuration parameters to improve the trimming of records from the database and then perform "garbage collection" of deleted entries to reclaim unused space & avoid excessive fragmentation. 3) IMPROVED: Modified SQLite3 configuration parameters to improve the processing database records. 4) IMPROVED: Modified code to set the corresponding priority level of log entries when calling the built-in logger utility. 5) IMPROVED: Modified the startup call made in the post-mount script to check if the USB-disk partition passed as argument has Entware installed. 6) IMPROVED: Added code to show the current database file size information on the CLI menu and the webGUI page. 7) IMPROVED: Added code to show the "JFFS Available" space information for the "Data Storage Location" option on the CLI menu and the webGUI page. This allows users to see if/when the "JFFS Available" space is getting too low to store the database and additional supporting files (CSV, HMT, configs) when the "Data Storage Location" is set to JFFS. 8) IMPROVED: Miscellaneous coding improvements & fine-tuning. --- CHANGELOG.md | 12 +- README.md | 2 +- connmon.sh | 2773 ++++++++++++++++++++++++++++++------------ connmonstats_www.asp | 518 ++++---- connmonstats_www.js | 170 ++- 5 files changed, 2365 insertions(+), 1110 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cd7753..bf3d7e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,19 @@ # Changelog ## v3.0.3 -18 August 2024 +22 December 2024 * FIXED: Errors when loading the webGUI page on the 3006.102.1 F/W version. -* FIXED: Incorrect results when computing the free space available of a large-capacity USB-attached drive. This was preventing the user from resetting the database using the CLI menu. +* FIXED: Bug giving incorrect results when computing the free space available of a large-capacity USB-attached drive. This was preventing the user from resetting the database using the CLI menu. * FIXED: "Reset Database" functionality on the CLI menu was correctly resetting the database file but the result was not reflected on the webGUI page where "old" entries were still shown as if the database had not been reset. +* IMPROVED: Modified all SQLite3 calls to capture and log errors in the system log. +* IMPROVED: Modified SQLite3 configuration parameters to improve the trimming of records from the database and then perform "garbage collection" of deleted entries to reclaim unused space & avoid excessive fragmentation. +* IMPROVED: Modified SQLite3 configuration parameters to improve the processing database records. +* IMPROVED: Modified code to set the corresponding priority level of log entries when calling the built-in logger utility. +* IMPROVED: Modified the startup call made in the post-mount script to check if the USB-disk partition passed as argument has Entware installed. +* IMPROVED: Added code to show the current database file size information on the CLI menu and the webGUI page. +* IMPROVED: Added code to show the "JFFS Available" space information for the "Data Storage Location" option on the CLI menu and the webGUI page. * CHANGED: Modified code related to "var $j = jQuery.noConflict();" which is now considered obsolete. +* IMPROVED: Various code improvements & fine-tuning. ## v3.0.2 06 January 2022 diff --git a/README.md b/README.md index 04426eb..6e2c319 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ ![Shellcheck](https://github.com/jackyaz/connmon/actions/workflows/shellcheck.yml/badge.svg) ## v3.0.3 -### Updated on 2024-Aug-18 +### Updated on 2024-Dec-22 ## About connmon is an internet connection monitoring tool for AsusWRT Merlin with charts for daily, weekly and monthly summaries. diff --git a/connmon.sh b/connmon.sh index 716ed73..2a630a5 100644 --- a/connmon.sh +++ b/connmon.sh @@ -10,7 +10,7 @@ ## https://github.com/jackyaz/connmon ## ## ## ############################################################## -# Last Modified: 2024-Jul-14 +# Last Modified: 2024-Dec-22 #------------------------------------------------------------- ############## Shellcheck directives ############# @@ -24,8 +24,12 @@ # shellcheck disable=SC2059 # shellcheck disable=SC2086 # shellcheck disable=SC2155 +# shellcheck disable=SC2174 # shellcheck disable=SC2181 # shellcheck disable=SC3003 +# shellcheck disable=SC3018 +# shellcheck disable=SC3043 +# shellcheck disable=SC3045 ############################################################## ### Start of script variables ### @@ -44,6 +48,19 @@ readonly EMAIL_CONF="$EMAIL_DIR/email.conf" readonly EMAIL_REGEX="^(([A-Za-z0-9]+((\.|\-|\_|\+)?[A-Za-z0-9]?)*[A-Za-z0-9]+)|[A-Za-z0-9]+)@(([A-Za-z0-9]+)+((\.|\-|\_)?([A-Za-z0-9]+)+)*)+\.([A-Za-z]{2,})+$" [ -z "$(nvram get odmpid)" ] && ROUTER_MODEL="$(nvram get productid)" || ROUTER_MODEL="$(nvram get odmpid)" [ -f /opt/bin/sqlite3 ] && SQLITE3_PATH=/opt/bin/sqlite3 || SQLITE3_PATH=/usr/sbin/sqlite3 + +##-------------------------------------## +## Added by Martinski W. [2024-Nov-23] ## +##-------------------------------------## +# For daily CRON job to trim database # +readonly defTrimDB_Hour=3 +readonly defTrimDB_Mins=1 + +readonly oneKByte=1024 +readonly oneMByte=1048576 +readonly oneGByte=1073741824 +readonly SHARE_TEMP_DIR="/opt/share/tmp" + ### End of script variables ### ### Start of output format variables ### @@ -55,17 +72,43 @@ readonly BOLD="\\e[1m" readonly SETTING="${BOLD}\\e[36m" readonly UNDERLINE="\\e[4m" readonly CLEARFORMAT="\\e[0m" + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +readonly REDct="\033[1;31m\033[1m" +readonly GRNct="\033[1;32m\033[1m" +readonly CLEARct="\033[0m" + ### End of output format variables ### +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## # $1 = print to syslog, $2 = message to print, $3 = log level -Print_Output(){ - if [ "$1" = "true" ]; then - logger -t "$SCRIPT_NAME" "$2" +Print_Output() +{ + local prioStr prioNum + if [ $# -gt 2 ] && [ -n "$3" ] + then prioStr="$3" + else prioStr="NOTICE" fi - printf "${BOLD}${3}%s${CLEARFORMAT}\\n\\n" "$2" + if [ "$1" = "true" ] + then + case "$prioStr" in + "$CRIT") prioNum=2 ;; + "$ERR") prioNum=3 ;; + "$WARN") prioNum=4 ;; + "$PASS") prioNum=6 ;; #INFO# + *) prioNum=5 ;; #NOTICE# + esac + logger -t "$SCRIPT_NAME" -p $prioNum "$2" + fi + printf "${BOLD}${3}%s${CLEARFORMAT}\n\n" "$2" } -Firmware_Version_Check(){ +Firmware_Version_Check() +{ if nvram get rc_support | grep -qF "am_addons"; then return 0 else @@ -74,10 +117,13 @@ Firmware_Version_Check(){ } ### Code for these functions inspired by https://github.com/Adamm00 - credit to @Adamm ### -Check_Lock(){ - if [ -f "/tmp/$SCRIPT_NAME.lock" ]; then +Check_Lock() +{ + if [ -f "/tmp/$SCRIPT_NAME.lock" ] + then ageoflock="$(($(/bin/date "+%s") - $(/bin/date "+%s" -r "/tmp/$SCRIPT_NAME.lock")))" - if [ "$ageoflock" -gt 600 ]; then + if [ "$ageoflock" -gt 600 ] #10 minutes# + then Print_Output true "Stale lock file found (>600 seconds old) - purging lock" "$ERR" kill "$(sed -n '1p' "/tmp/$SCRIPT_NAME.lock")" >/dev/null 2>&1 Clear_Lock @@ -85,7 +131,8 @@ Check_Lock(){ return 0 else Print_Output true "Lock file found (age: $ageoflock seconds) - ping test likely currently running" "$ERR" - if [ -z "$1" ]; then + if [ $# -eq 0 ] || [ -z "$1" ] + then exit 1 else if [ "$1" = "webui" ]; then @@ -101,14 +148,16 @@ Check_Lock(){ fi } -Clear_Lock(){ +Clear_Lock() +{ rm -f "/tmp/$SCRIPT_NAME.lock" 2>/dev/null return 0 } ############################################################################ -Set_Version_Custom_Settings(){ +Set_Version_Custom_Settings() +{ SETTINGSFILE="/jffs/addons/custom_settings.txt" case "$1" in local) @@ -140,7 +189,8 @@ Set_Version_Custom_Settings(){ esac } -Update_Check(){ +Update_Check() +{ echo 'var updatestatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_update.js" doupdate="false" localver="$(grep "SCRIPT_VERSION=" "/jffs/scripts/$SCRIPT_NAME" | grep -m1 -oE 'v[0-9]{1,2}([.][0-9]{1,2})([.][0-9]{1,2})')" @@ -168,8 +218,10 @@ Update_Check(){ echo "$doupdate,$localver,$serverver" } -Update_Version(){ - if [ -z "$1" ]; then +Update_Version() +{ + if [ $# -eq 0 ] || [ -z "$1" ] + then updatecheckresult="$(Update_Check)" isupdate="$(echo "$updatecheckresult" | cut -f1 -d',')" localver="$(echo "$updatecheckresult" | cut -f2 -d',')" @@ -183,7 +235,8 @@ Update_Version(){ Print_Output true "MD5 hash of $SCRIPT_NAME does not match - hotfix available - $serverver" "$PASS" fi - if [ "$isupdate" != "false" ]; then + if [ "$isupdate" != "false" ] + then printf "\\n${BOLD}Do you want to continue with the update? (y/n)${CLEARFORMAT} " read -r confirm case "$confirm" in @@ -215,7 +268,8 @@ Update_Version(){ fi fi - if [ "$1" = "force" ]; then + if [ "$1" = "force" ] + then serverver="$(/usr/sbin/curl -fsL --retry 3 --connect-timeout 15 "$SCRIPT_REPO/version/$SCRIPT_NAME.sh" | grep "SCRIPT_VERSION=" | grep -m1 -oE 'v[0-9]{1,2}([.][0-9]{1,2})([.][0-9]{1,2})')" Print_Output true "Downloading latest version ($serverver) of $SCRIPT_NAME" "$PASS" Update_File CHANGELOG.md @@ -228,22 +282,28 @@ Update_Version(){ Set_Version_Custom_Settings local "$serverver" Set_Version_Custom_Settings server "$serverver" Clear_Lock - if [ -z "$2" ]; then + if [ $# -lt 2 ] || [ -z "$2" ] + then PressEnter exec "$0" - elif [ "$2" = "unattended" ]; then + elif [ "$2" = "unattended" ] + then exec "$0" postupdate fi exit 0 fi } -Update_File(){ - if [ "$1" = "connmonstats_www.asp" ]; then +Update_File() +{ + if [ "$1" = "connmonstats_www.asp" ] + then tmpfile="/tmp/$1" Download_File "$SCRIPT_REPO/files/$1" "$tmpfile" - if ! diff -q "$tmpfile" "$SCRIPT_DIR/$1" >/dev/null 2>&1; then - if [ -f "$SCRIPT_DIR/$1" ]; then + if ! diff -q "$tmpfile" "$SCRIPT_DIR/$1" >/dev/null 2>&1 + then + if [ -f "$SCRIPT_DIR/$1" ] + then Get_WebUI_Page "$SCRIPT_DIR/$1" sed -i "\\~$MyPage~d" /tmp/menuTree.js rm -f "$SCRIPT_WEBPAGE_DIR/$MyPage" 2>/dev/null @@ -253,7 +313,8 @@ Update_File(){ Mount_WebUI fi rm -f "$tmpfile" - elif [ "$1" = "shared-jy.tar.gz" ]; then + elif [ "$1" = "shared-jy.tar.gz" ] + then if [ ! -f "$SHARED_DIR/$1.md5" ]; then Download_File "$SHARED_REPO/$1" "$SHARED_DIR/$1" Download_File "$SHARED_REPO/$1.md5" "$SHARED_DIR/$1.md5" @@ -271,14 +332,16 @@ Update_File(){ Print_Output true "New version of $1 downloaded" "$PASS" fi fi - elif [ "$1" = "CHANGELOG.md" ]; then + elif [ "$1" = "CHANGELOG.md" ] + then tmpfile="/tmp/$1" Download_File "$SCRIPT_REPO/files/$1" "$tmpfile" if ! diff -q "$tmpfile" "$SCRIPT_DIR/$1" >/dev/null 2>&1; then Download_File "$SCRIPT_REPO/files/$1" "$SCRIPT_DIR/$1" fi rm -f "$tmpfile" - elif [ "$1" = "README.md" ] || [ "$1" = "LICENSE" ]; then + elif [ "$1" = "README.md" ] || [ "$1" = "LICENSE" ] + then tmpfile="/tmp/$1" Download_File "$SCRIPT_REPO/files/$1" "$tmpfile" if ! diff -q "$tmpfile" "$SCRIPT_DIR/$1" >/dev/null 2>&1; then @@ -298,7 +361,8 @@ Validate_Number(){ fi } -Validate_IP(){ +Validate_IP() +{ if expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; then for i in 1 2 3 4; do if [ "$(echo "$1" | cut -d. -f$i)" -gt 255 ]; then @@ -312,7 +376,8 @@ Validate_IP(){ fi } -Validate_Domain(){ +Validate_Domain() +{ if ! nslookup "$1" >/dev/null 2>&1; then Print_Output false "$1 cannot be resolved by nslookup, please ensure you enter a valid domain name" "$ERR" return 1 @@ -321,46 +386,67 @@ Validate_Domain(){ fi } -Conf_FromSettings(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Conf_FromSettings() +{ SETTINGSFILE="/jffs/addons/custom_settings.txt" TMPFILE="/tmp/connmon_settings.txt" - if [ -f "$SETTINGSFILE" ]; then - if [ "$(grep "connmon_" $SETTINGSFILE | grep -v "version" -c)" -gt 0 ]; then + + if [ -f "$SETTINGSFILE" ] + then + if [ "$(grep "connmon_" $SETTINGSFILE | grep -v "version" -c)" -gt 0 ] + then Print_Output true "Updated settings from WebUI found, merging into $SCRIPT_CONF" "$PASS" - cp -a "$SCRIPT_CONF" "$SCRIPT_CONF.bak" + cp -a "$SCRIPT_CONF" "${SCRIPT_CONF}.bak" grep "connmon_" "$SETTINGSFILE" | grep -v "version" > "$TMPFILE" sed -i "s/connmon_//g;s/ /=/g" "$TMPFILE" - while IFS='' read -r line || [ -n "$line" ]; do + while IFS='' read -r line || [ -n "$line" ] + do SETTINGNAME="$(echo "$line" | cut -f1 -d'=' | awk '{print toupper($1)}')" SETTINGVALUE="$(echo "$line" | cut -f2 -d'=')" - if [ "$SETTINGNAME" = "NOTIFICATIONS_PUSHOVER_LIST" ] || [ "$SETTINGNAME" = "NOTIFICATIONS_WEBHOOK_LIST" ] || [ "$SETTINGNAME" = "NOTIFICATIONS_EMAIL_LIST" ]; then + if [ "$SETTINGNAME" = "NOTIFICATIONS_EMAIL_LIST" ] || \ + [ "$SETTINGNAME" = "NOTIFICATIONS_WEBHOOK_LIST" ] || \ + [ "$SETTINGNAME" = "NOTIFICATIONS_PUSHOVER_LIST" ] + then SETTINGVALUE="$(echo "$SETTINGVALUE" | sed 's~||||~,~g')" fi sed -i "s~$SETTINGNAME=.*~$SETTINGNAME=$SETTINGVALUE~" "$SCRIPT_CONF" done < "$TMPFILE" grep 'connmon_version' "$SETTINGSFILE" > "$TMPFILE" sed -i "\\~connmon_~d" "$SETTINGSFILE" - mv "$SETTINGSFILE" "$SETTINGSFILE.bak" - cat "$SETTINGSFILE.bak" "$TMPFILE" > "$SETTINGSFILE" + mv -f "$SETTINGSFILE" "${SETTINGSFILE}.bak" + cat "${SETTINGSFILE}.bak" "$TMPFILE" > "$SETTINGSFILE" rm -f "$TMPFILE" - rm -f "$SETTINGSFILE.bak" - - ScriptStorageLocation "$(ScriptStorageLocation check)" - Create_Symlinks - - if AutomaticMode check; then - if diff "$SCRIPT_CONF" "$SCRIPT_CONF.bak" | grep -q "^SCH"; then - Auto_Cron delete 2>/dev/null - Auto_Cron create 2>/dev/null + rm -f "${SETTINGSFILE}.bak" + + if diff "$SCRIPT_CONF" "${SCRIPT_CONF}.bak" | grep -q "STORAGELOCATION=" + then + STORAGEtype="$(ScriptStorageLocation check)" + if [ "$STORAGEtype" = "jffs" ] + then + ## Check if enough free space is available in JFFS ## + if _Check_JFFS_SpaceAvailable_ "$SCRIPT_STORAGE_DIR" + then ScriptStorageLocation jffs + else ScriptStorageLocation usb + fi + elif [ "$STORAGEtype" = "usb" ] + then + ScriptStorageLocation usb fi - else + Create_Symlinks + fi + if diff "$SCRIPT_CONF" "${SCRIPT_CONF}.bak" | grep -qE "(SCHDAYS|SCHHOUR|SCHMINS|AUTOMATICMODE=)" + then Auto_Cron delete 2>/dev/null + AutomaticMode check && Auto_Cron create 2>/dev/null + _UpdateAutomaticModeState_ fi - - if diff "$SCRIPT_CONF" "$SCRIPT_CONF.bak" | grep -q "OUTPUTTIMEMODE=\|DAYSTOKEEP=\|LASTXRESULTS="; then + if diff "$SCRIPT_CONF" "${SCRIPT_CONF}.bak" | grep -qE "(OUTPUTTIMEMODE=|DAYSTOKEEP=|LASTXRESULTS=)" + then Generate_CSVs fi - Print_Output true "Merge of updated settings from WebUI completed successfully" "$PASS" else Print_Output false "No updated settings from WebUI found, no merge into $SCRIPT_CONF necessary" "$PASS" @@ -368,10 +454,12 @@ Conf_FromSettings(){ fi } -EmailConf_FromSettings(){ +EmailConf_FromSettings() +{ SETTINGSFILE="/jffs/addons/custom_settings.txt" TMPFILE="/tmp/email_settings.txt" - if [ -f "$SETTINGSFILE" ]; then + if [ -f "$SETTINGSFILE" ] + then Print_Output true "Updated email settings from WebUI found, merging into $EMAIL_CONF" "$PASS" cp -a "$EMAIL_CONF" "$EMAIL_CONF.bak" grep "email_" "$SETTINGSFILE" > "$TMPFILE" @@ -391,7 +479,11 @@ EmailConf_FromSettings(){ fi } -Create_Dirs(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Create_Dirs() +{ if [ ! -d "$SCRIPT_DIR" ]; then mkdir -p "$SCRIPT_DIR" fi @@ -423,9 +515,16 @@ Create_Dirs(){ if [ ! -d "$USER_SCRIPT_DIR" ]; then mkdir -p "$USER_SCRIPT_DIR" fi + + if [ ! -d "$SHARE_TEMP_DIR" ] + then + mkdir -m 777 -p "$SHARE_TEMP_DIR" + export SQLITE_TMPDIR TMPDIR + fi } -Create_Symlinks(){ +Create_Symlinks() +{ ln -sf "$SCRIPT_STORAGE_DIR/connstatstext.js" "$SCRIPT_WEB_DIR/connstatstext.js" 2>/dev/null ln -sf "$SCRIPT_STORAGE_DIR/lastx.csv" "$SCRIPT_WEB_DIR/lastx.htm" 2>/dev/null @@ -444,17 +543,32 @@ Create_Symlinks(){ fi } -Conf_Exists(){ - if [ -f "$SCRIPT_CONF" ]; then +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Conf_Exists() +{ + local PINGFREQUENCY AUTOMATEDopt + + if [ -f "$SCRIPT_CONF" ] + then dos2unix "$SCRIPT_CONF" chmod 0644 "$SCRIPT_CONF" sed -i -e 's/"//g' "$SCRIPT_CONF" - - if grep -q "SCHEDULESTART" "$SCRIPT_CONF"; then - if ! grep -q "AUTOMATED" "$SCRIPT_CONF"; then - echo "AUTOMATED=true" >> "$SCRIPT_CONF" - fi - if ! grep -q "SCHDAYS" "$SCRIPT_CONF"; then + if grep -q "^AUTOMATED=.*" "$SCRIPT_CONF" + then + AUTOMATEDopt="$(Conf_Parameters check AUTOMATED)" + sed -i 's/^AUTOMATED=.*$/AUTOMATICMODE='"$AUTOMATEDopt"'/' "$SCRIPT_CONF" + fi + if ! grep -q "^AUTOMATICMODE=" "$SCRIPT_CONF"; then + echo "AUTOMATICMODE=true" >> "$SCRIPT_CONF" + fi + if ! grep -q "^PINGDURATION=" "$SCRIPT_CONF"; then + echo "PINGDURATION=30" >> "$SCRIPT_CONF" + fi + if grep -q "SCHEDULESTART" "$SCRIPT_CONF" + then + if ! grep -q "^SCHDAYS=" "$SCRIPT_CONF"; then echo "SCHDAYS=*" >> "$SCRIPT_CONF" fi echo "SCHHOURS=*" >> "$SCRIPT_CONF" @@ -474,8 +588,11 @@ Conf_Exists(){ if ! grep -q "EXCLUDEFROMQOS" "$SCRIPT_CONF"; then echo "EXCLUDEFROMQOS=true" >> "$SCRIPT_CONF" fi - - if ! grep -q "NOTIFICATIONS" "$SCRIPT_CONF"; then + if ! grep -q "^STORAGELOCATION=" "$SCRIPT_CONF"; then + echo "STORAGELOCATION=jffs" >> "$SCRIPT_CONF" + fi + if ! grep -q "NOTIFICATIONS" "$SCRIPT_CONF" + then { echo "NOTIFICATIONS_EMAIL=false" echo "NOTIFICATIONS_WEBHOOK=false" @@ -508,210 +625,301 @@ Conf_Exists(){ return 0 else - { echo "PINGSERVER=8.8.8.8"; echo "OUTPUTTIMEMODE=unix"; echo "STORAGELOCATION=jffs"; echo "PINGDURATION=60"; echo "AUTOMATED=true"; echo "SCHDAYS=*"; echo "SCHHOURS=*"; echo "SCHMINS=*/3"; echo "DAYSTOKEEP=30"; echo "LASTXRESULTS=10"; echo "EXCLUDEFROMQOS=true"; - echo "NOTIFICATIONS_EMAIL=false"; echo "NOTIFICATIONS_WEBHOOK=false"; echo "NOTIFICATIONS_PUSHOVER=false"; echo "NOTIFICATIONS_CUSTOM=false"; echo "NOTIFICATIONS_HEALTHCHECK=false"; echo "NOTIFICATIONS_INFLUXDB=false"; - echo "NOTIFICATIONS_PINGTEST=None"; echo "NOTIFICATIONS_PINGTHRESHOLD=None"; echo "NOTIFICATIONS_JITTERTHRESHOLD=None"; echo "NOTIFICATIONS_LINEQUALITYTHRESHOLD=None"; echo "NOTIFICATIONS_PINGTHRESHOLD_VALUE=30"; echo "NOTIFICATIONS_JITTERTHRESHOLD_VALUE=15"; echo "NOTIFICATIONS_LINEQUALITYTHRESHOLD_VALUE=75"; - echo "NOTIFICATIONS_EMAIL_LIST="; echo "NOTIFICATIONS_HEALTHCHECK_UUID="; echo "NOTIFICATIONS_WEBHOOK_LIST="; echo "NOTIFICATIONS_PUSHOVER_LIST="; echo "NOTIFICATIONS_PUSHOVER_API="; echo "NOTIFICATIONS_PUSHOVER_USERKEY="; echo "NOTIFICATIONS_INFLUXDB_HOST="; echo "NOTIFICATIONS_INFLUXDB_PORT=8086"; echo "NOTIFICATIONS_INFLUXDB_DB=connmon"; - echo "NOTIFICATIONS_INFLUXDB_VERSION=1.8"; echo "NOTIFICATIONS_INFLUXDB_USERNAME="; echo "NOTIFICATIONS_INFLUXDB_PASSWORD="; echo "NOTIFICATIONS_INFLUXDB_APITOKEN="; } > "$SCRIPT_CONF" + { + echo "PINGSERVER=8.8.8.8"; echo "OUTPUTTIMEMODE=unix" + echo "STORAGELOCATION=jffs"; echo "PINGDURATION=30"; echo "AUTOMATICMODE=true" + echo "SCHDAYS=*"; echo "SCHHOURS=*"; echo "SCHMINS=*/3" + echo "DAYSTOKEEP=30"; echo "LASTXRESULTS=10"; echo "EXCLUDEFROMQOS=true" + echo "NOTIFICATIONS_EMAIL=false"; echo "NOTIFICATIONS_WEBHOOK=false" + echo "NOTIFICATIONS_PUSHOVER=false"; echo "NOTIFICATIONS_CUSTOM=false" + echo "NOTIFICATIONS_HEALTHCHECK=false"; echo "NOTIFICATIONS_INFLUXDB=false" + echo "NOTIFICATIONS_PINGTEST=None"; echo "NOTIFICATIONS_PINGTHRESHOLD=None" + echo "NOTIFICATIONS_JITTERTHRESHOLD=None"; echo "NOTIFICATIONS_LINEQUALITYTHRESHOLD=None" + echo "NOTIFICATIONS_PINGTHRESHOLD_VALUE=30"; echo "NOTIFICATIONS_JITTERTHRESHOLD_VALUE=15" + echo "NOTIFICATIONS_LINEQUALITYTHRESHOLD_VALUE=75" + echo "NOTIFICATIONS_EMAIL_LIST="; echo "NOTIFICATIONS_HEALTHCHECK_UUID=" + echo "NOTIFICATIONS_WEBHOOK_LIST="; echo "NOTIFICATIONS_PUSHOVER_LIST=" + echo "NOTIFICATIONS_PUSHOVER_API="; echo "NOTIFICATIONS_PUSHOVER_USERKEY=" + echo "NOTIFICATIONS_INFLUXDB_HOST="; echo "NOTIFICATIONS_INFLUXDB_PORT=8086" + echo "NOTIFICATIONS_INFLUXDB_DB=connmon" + echo "NOTIFICATIONS_INFLUXDB_VERSION=1.8"; echo "NOTIFICATIONS_INFLUXDB_USERNAME=" + echo "NOTIFICATIONS_INFLUXDB_PASSWORD="; echo "NOTIFICATIONS_INFLUXDB_APITOKEN=" + } > "$SCRIPT_CONF" return 1 fi } -PingServer(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +PingServer() +{ case "$1" in update) - while true; do + exitOK=false + exitEsc=false + while true + do ScriptHeader - printf "\\n${BOLD}Current ping destination: %s${CLEARFORMAT}\\n\\n" "$(PingServer check)" - printf "1. Enter IP Address\\n" - printf "2. Enter Domain\\n" - printf "\\ne. Go back\\n" - printf "\\n${BOLD}Choose an option:${CLEARFORMAT} " + printf "\n${BOLD}Current ping destination: ${GRNct}%s${CLEARFORMAT}\n\n" "$(PingServer check)" + if "$exitOK" + then PressEnter ; break + fi + printf "1. Enter IP Address\n" + printf "2. Enter Domain Name\n" + printf "e. Return to Main Menu\n" + printf "\n${BOLD}Choose an option:${CLEARFORMAT} " read -r pingoption + case "$pingoption" in 1) - while true; do - printf "\\n${BOLD}Please enter an IP address, or enter e to go back:${CLEARFORMAT} " + while true + do + printf "\n${BOLD}Please enter an IP address (e=Exit):${CLEARFORMAT} " read -r ipoption - if [ "$ipoption" = "e" ]; then + if [ "$ipoption" = "e" ] + then break - elif Validate_IP "$ipoption"; then + elif Validate_IP "$ipoption" + then sed -i 's/^PINGSERVER=.*$/PINGSERVER='"$ipoption"'/' "$SCRIPT_CONF" - break + exitOK=true ; break fi done ;; 2) - while true; do - printf "\\n${BOLD}Please enter a domain name, or enter e to go back:${CLEARFORMAT} " + while true + do + printf "\n${BOLD}Please enter a domain name (e=Exit):${CLEARFORMAT} " read -r domainoption - if [ "$domainoption" = "e" ]; then + if [ "$domainoption" = "e" ] + then break - elif Validate_Domain "$domainoption"; then + elif Validate_Domain "$domainoption" + then sed -i 's/^PINGSERVER=.*$/PINGSERVER='"$domainoption"'/' "$SCRIPT_CONF" - break + exitOK=true ; break fi done ;; - e) - printf "\\n" - break + e) exitEsc=true ; break ;; *) - printf "\\n${BOLD}${ERR}Please choose a valid option${CLEARFORMAT}\\n\\n" + printf "\n${BOLD}${ERR}Please choose a valid option.${CLEARFORMAT}\n\n" PressEnter ;; esac done + echo ;; check) PINGSERVER="$(Conf_Parameters check PINGSERVER)" - echo "$PINGSERVER" + echo "${PINGSERVER:=8.8.8.8}" ;; esac } -PingDuration(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +PingDuration() +{ case "$1" in update) - pingdur=0 - exitmenu="" - ScriptHeader - while true; do - printf "\\n${BOLD}Please enter the desired test duration (10-60 seconds):${CLEARFORMAT} " + pingSecs="$(PingDuration check)" + exitLoop=false + while true + do + ScriptHeader + printf "${BOLD}Current number of seconds for ping tests: ${GRNct}${pingSecs}${CLEARct}\n" + printf "\n${BOLD}Please enter the maximum number of seconds\nto run the ping tests [10-60] (e=Exit):${CLEARFORMAT} " read -r pingdur_choice - - if [ "$pingdur_choice" = "e" ]; then - exitmenu="exit" + if [ -z "$pingdur_choice" ] && \ + echo "$pingSecs" | grep -qE "^([1-9][0-9])$" && \ + [ "$pingSecs" -ge 10 ] && [ "$pingSecs" -le 60 ] + then + exitLoop=true + break + elif [ "$pingdur_choice" = "e" ] + then + exitLoop=true break - elif ! Validate_Number "$pingdur_choice"; then - printf "\\n${ERR}Please enter a valid number (10-60)${CLEARFORMAT}\\n" - elif [ "$pingdur_choice" -lt 10 ] || [ "$pingdur_choice" -gt 60 ]; then - printf "\\n${ERR}Please enter a number between 10 and 60${CLEARFORMAT}\\n" + elif ! Validate_Number "$pingdur_choice" + then + printf "\n${ERR}Please enter a valid number [10-60].${CLEARFORMAT}\n" + PressEnter + elif [ "$pingdur_choice" -lt 10 ] || [ "$pingdur_choice" -gt 60 ] + then + printf "\n${ERR}Please enter a number between 10 and 60.${CLEARFORMAT}\n" + PressEnter else - pingdur="$pingdur_choice" - printf "\\n" + pingSecs="$pingdur_choice" break fi done - if [ "$exitmenu" != "exit" ]; then - sed -i 's/^PINGDURATION=.*$/PINGDURATION='"$pingdur"'/' "$SCRIPT_CONF" - return 0 + if "$exitLoop" + then + echo ; return 1 else - printf "\\n" - return 1 + PINGDURATION="$pingSecs" + sed -i 's/^PINGDURATION=.*$/PINGDURATION='"$PINGDURATION"'/' "$SCRIPT_CONF" + echo ; return 0 fi ;; check) PINGDURATION="$(Conf_Parameters check PINGDURATION)" - echo "$PINGDURATION" + echo "${PINGDURATION:=30}" ;; esac } -DaysToKeep(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +DaysToKeep() +{ case "$1" in update) - daystokeep=30 - exitmenu="" - ScriptHeader - while true; do - printf "\\n${BOLD}Please enter the desired number of days\\nto keep data for (30-365 days):${CLEARFORMAT} " + daysToKeep="$(DaysToKeep check)" + exitLoop=false + while true + do + ScriptHeader + printf "${BOLD}Current number of days to keep data: ${GRNct}${daysToKeep}${CLEARct}\n" + printf "\n${BOLD}Please enter the maximum number of days\nto keep the data for [5-365] (e=Exit):${CLEARFORMAT} " read -r daystokeep_choice - - if [ "$daystokeep_choice" = "e" ]; then - exitmenu="exit" + if [ -z "$daystokeep_choice" ] && \ + echo "$daysToKeep" | grep -qE "^([1-9][0-9]{0,2})$" && \ + [ "$daysToKeep" -ge 5 ] && [ "$daysToKeep" -le 365 ] + then + exitLoop=true + break + elif [ "$daystokeep_choice" = "e" ] + then + exitLoop=true break - elif ! Validate_Number "$daystokeep_choice"; then - printf "\\n${ERR}Please enter a valid number (30-365)${CLEARFORMAT}\\n" - elif [ "$daystokeep_choice" -lt 30 ] || [ "$daystokeep_choice" -gt 365 ]; then - printf "\\n${ERR}Please enter a number between 30 and 365${CLEARFORMAT}\\n" + elif ! Validate_Number "$daystokeep_choice" + then + printf "\n${ERR}Please enter a valid number [5-365].${CLEARFORMAT}\n" + PressEnter + elif [ "$daystokeep_choice" -lt 5 ] || [ "$daystokeep_choice" -gt 365 ] + then + printf "\n${ERR}Please enter a number between 5 and 365.${CLEARFORMAT}\n" + PressEnter else - daystokeep="$daystokeep_choice" - printf "\\n" + daysToKeep="$daystokeep_choice" break fi done - if [ "$exitmenu" != "exit" ]; then - sed -i 's/^DAYSTOKEEP=.*$/DAYSTOKEEP='"$daystokeep"'/' "$SCRIPT_CONF" - return 0 + if "$exitLoop" + then + echo ; return 1 else - printf "\\n" - return 1 + DAYSTOKEEP="$daysToKeep" + sed -i 's/^DAYSTOKEEP=.*$/DAYSTOKEEP='"$DAYSTOKEEP"'/' "$SCRIPT_CONF" + echo ; return 0 fi ;; check) DAYSTOKEEP="$(Conf_Parameters check DAYSTOKEEP)" - echo "$DAYSTOKEEP" + echo "${DAYSTOKEEP:=30}" ;; esac } -LastXResults(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +LastXResults() +{ case "$1" in update) - lastxresults=10 - exitmenu="" - ScriptHeader - while true; do - printf "\\n${BOLD}Please enter the desired number of results\\nto display in the WebUI (1-100):${CLEARFORMAT} " + lastXResults="$(LastXResults check)" + exitLoop=false + while true + do + ScriptHeader + printf "${BOLD}Current number of results to display: ${GRNct}${lastXResults}${CLEARct}\n" + printf "\n${BOLD}Please enter the maximum number of results\nto display in the WebUI [5-100] (e=Exit):${CLEARFORMAT} " read -r lastx_choice - - if [ "$lastx_choice" = "e" ]; then - exitmenu="exit" + if [ -z "$lastx_choice" ] && \ + echo "$lastXResults" | grep -qE "^([1-9][0-9]{0,2})$" && \ + [ "$lastXResults" -ge 5 ] && [ "$lastXResults" -le 100 ] + then + exitLoop=true break - elif ! Validate_Number "$lastx_choice"; then - printf "\\n${ERR}Please enter a valid number (1-100)${CLEARFORMAT}\\n" - elif [ "$lastx_choice" -lt 1 ] || [ "$lastx_choice" -gt 100 ]; then - printf "\\n${ERR}Please enter a number between 1 and 100${CLEARFORMAT}\\n" + elif [ "$lastx_choice" = "e" ] + then + exitLoop=true + break + elif ! Validate_Number "$lastx_choice" + then + printf "\n${ERR}Please enter a valid number [5-100].${CLEARFORMAT}\n" + PressEnter + elif [ "$lastx_choice" -lt 5 ] || [ "$lastx_choice" -gt 100 ] + then + printf "\n${ERR}Please enter a number between 5 and 100.${CLEARFORMAT}\n" + PressEnter else - lastxresults="$lastx_choice" - printf "\\n" + lastXResults="$lastx_choice" break fi done - if [ "$exitmenu" != "exit" ]; then - sed -i 's/^LASTXRESULTS=.*$/LASTXRESULTS='"$lastxresults"'/' "$SCRIPT_CONF" - Generate_LastXResults - return 0 + if "$exitLoop" + then + echo ; return 1 else - printf "\\n" - return 1 + LASTXRESULTS="$lastXResults" + sed -i 's/^LASTXRESULTS=.*$/LASTXRESULTS='"$LASTXRESULTS"'/' "$SCRIPT_CONF" + Generate_LastXResults + echo ; return 0 fi ;; check) LASTXRESULTS="$(Conf_Parameters check LASTXRESULTS)" - echo "$LASTXRESULTS" + echo "${LASTXRESULTS:=10}" ;; esac } -Auto_ServiceEvent(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Auto_ServiceEvent() +{ case $1 in create) - if [ -f /jffs/scripts/service-event ]; then + if [ -f /jffs/scripts/service-event ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/service-event)" STARTUPLINECOUNTEX="$(grep -cx 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'"; then { /jffs/scripts/'"$SCRIPT_NAME"' service_event "$@" & }; fi # '"$SCRIPT_NAME" /jffs/scripts/service-event)" - if [ "$STARTUPLINECOUNT" -gt 1 ] || { [ "$STARTUPLINECOUNTEX" -eq 0 ] && [ "$STARTUPLINECOUNT" -gt 0 ]; }; then + if [ "$STARTUPLINECOUNT" -gt 1 ] || { [ "$STARTUPLINECOUNTEX" -eq 0 ] && [ "$STARTUPLINECOUNT" -gt 0 ]; } + then sed -i -e '/# '"$SCRIPT_NAME"'/d' /jffs/scripts/service-event fi - if [ "$STARTUPLINECOUNTEX" -eq 0 ]; then - echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'"; then { /jffs/scripts/'"$SCRIPT_NAME"' service_event "$@" & }; fi # '"$SCRIPT_NAME" >> /jffs/scripts/service-event + if [ "$STARTUPLINECOUNTEX" -eq 0 ] + then + { + echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'"; then { /jffs/scripts/'"$SCRIPT_NAME"' service_event "$@" & }; fi # '"$SCRIPT_NAME" + } >> /jffs/scripts/service-event fi else - echo "#!/bin/sh" > /jffs/scripts/service-event - echo "" >> /jffs/scripts/service-event - echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'"; then { /jffs/scripts/'"$SCRIPT_NAME"' service_event "$@" & }; fi # '"$SCRIPT_NAME" >> /jffs/scripts/service-event + { + echo "#!/bin/sh" ; echo + echo 'if echo "$2" | /bin/grep -q "'"$SCRIPT_NAME"'"; then { /jffs/scripts/'"$SCRIPT_NAME"' service_event "$@" & }; fi # '"$SCRIPT_NAME" + echo + } >> /jffs/scripts/service-event chmod 0755 /jffs/scripts/service-event fi ;; delete) - if [ -f /jffs/scripts/service-event ]; then + if [ -f /jffs/scripts/service-event ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/service-event)" if [ "$STARTUPLINECOUNT" -gt 0 ]; then @@ -722,43 +930,58 @@ Auto_ServiceEvent(){ esac } -Auto_Startup(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Auto_Startup() +{ case $1 in create) - if [ -f /jffs/scripts/services-start ]; then + if [ -f /jffs/scripts/services-start ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/services-start)" if [ "$STARTUPLINECOUNT" -gt 0 ]; then sed -i -e '/# '"$SCRIPT_NAME"'/d' /jffs/scripts/services-start fi fi - if [ -f /jffs/scripts/post-mount ]; then + if [ -f /jffs/scripts/post-mount ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/post-mount)" - STARTUPLINECOUNTEX="$(grep -cx "/jffs/scripts/$SCRIPT_NAME startup"' "$@" & # '"$SCRIPT_NAME" /jffs/scripts/post-mount)" + STARTUPLINECOUNTEX="$(grep -cx '\[ -x "${1}/entware/bin/opkg" \] && \[ -x /jffs/scripts/'"$SCRIPT_NAME"' \] && /jffs/scripts/'"$SCRIPT_NAME"' startup "$@" & # '"$SCRIPT_NAME" /jffs/scripts/post-mount)" - if [ "$STARTUPLINECOUNT" -gt 1 ] || { [ "$STARTUPLINECOUNTEX" -eq 0 ] && [ "$STARTUPLINECOUNT" -gt 0 ]; }; then + if [ "$STARTUPLINECOUNT" -gt 1 ] || { [ "$STARTUPLINECOUNTEX" -eq 0 ] && [ "$STARTUPLINECOUNT" -gt 0 ]; } + then sed -i -e '/# '"$SCRIPT_NAME"'/d' /jffs/scripts/post-mount + STARTUPLINECOUNT=0 fi - if [ "$STARTUPLINECOUNTEX" -eq 0 ]; then - echo "/jffs/scripts/$SCRIPT_NAME startup"' "$@" & # '"$SCRIPT_NAME" >> /jffs/scripts/post-mount + if [ "$STARTUPLINECOUNTEX" -eq 0 ] + then + { + echo '[ -x "${1}/entware/bin/opkg" ] && [ -x /jffs/scripts/'"$SCRIPT_NAME"' ] && /jffs/scripts/'"$SCRIPT_NAME"' startup "$@" & # '"$SCRIPT_NAME" + } >> /jffs/scripts/post-mount fi else - echo "#!/bin/sh" > /jffs/scripts/post-mount - echo "" >> /jffs/scripts/post-mount - echo "/jffs/scripts/$SCRIPT_NAME startup"' "$@" & # '"$SCRIPT_NAME" >> /jffs/scripts/post-mount + { + echo "#!/bin/sh" ; echo + echo '[ -x "${1}/entware/bin/opkg" ] && [ -x /jffs/scripts/'"$SCRIPT_NAME"' ] && /jffs/scripts/'"$SCRIPT_NAME"' startup "$@" & # '"$SCRIPT_NAME" + echo + } > /jffs/scripts/post-mount chmod 0755 /jffs/scripts/post-mount fi ;; delete) - if [ -f /jffs/scripts/services-start ]; then + if [ -f /jffs/scripts/services-start ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/services-start)" if [ "$STARTUPLINECOUNT" -gt 0 ]; then sed -i -e '/# '"$SCRIPT_NAME"'/d' /jffs/scripts/services-start fi fi - if [ -f /jffs/scripts/post-mount ]; then + if [ -f /jffs/scripts/post-mount ] + then STARTUPLINECOUNT="$(grep -c '# '"$SCRIPT_NAME" /jffs/scripts/post-mount)" if [ "$STARTUPLINECOUNT" -gt 0 ]; then @@ -769,24 +992,56 @@ Auto_Startup(){ esac } -Auto_Cron(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Nov-23] ## +##----------------------------------------## +Auto_Cron() +{ case $1 in create) - STARTUPLINECOUNT="$(cru l | grep -c "$SCRIPT_NAME")" - - if [ "$STARTUPLINECOUNT" -eq 0 ]; then - CRU_DAYNUMBERS="$(Conf_Parameters check SCHDAYS | sed 's/Sun/0/;s/Mon/1/;s/Tues/2/;s/Wed/3/;s/Thurs/4/;s/Fri/5/;s/Sat/6/;')" - CRU_HOURS="$(Conf_Parameters check SCHHOURS)" - CRU_MINUTES="$(Conf_Parameters check SCHMINS)" + STARTUPLINECOUNTGEN="$(cru l | grep -c "#${SCRIPT_NAME}#")" + if [ "$STARTUPLINECOUNTGEN" -gt 0 ]; then + cru d "${SCRIPT_NAME}" + fi + STARTUPLINECOUNTGEN="$(cru l | grep -c "${SCRIPT_NAME}_generate")" + CRU_SCHHOUR="$(Conf_Parameters check SCHHOURS)" + CRU_SCHMINS="$(Conf_Parameters check SCHMINS)" + STARTUPLINECOUNTEXGEN="$(cru l | grep "${SCRIPT_NAME}_generate" | grep -c "^$CRU_SCHMINS $CRU_SCHHOUR [*] [*]")" + if [ "$STARTUPLINECOUNTGEN" -gt 0 ] && [ "$STARTUPLINECOUNTEXGEN" -eq 0 ] + then + cru d "${SCRIPT_NAME}_generate" + STARTUPLINECOUNTGEN="$(cru l | grep -c "${SCRIPT_NAME}_generate")" + fi + if [ "$STARTUPLINECOUNTGEN" -eq 0 ] + then + CRU_SCHDAYS="$(Conf_Parameters check SCHDAYS | sed 's/Sun/0/;s/Mon/1/;s/Tues/2/;s/Wed/3/;s/Thurs/4/;s/Fri/5/;s/Sat/6/;')" + cru a "${SCRIPT_NAME}_generate" "$CRU_SCHMINS $CRU_SCHHOUR * * $CRU_SCHDAYS /jffs/scripts/$SCRIPT_NAME generate" + echo "$CRU_SCHMINS $CRU_SCHHOUR * * $CRU_SCHDAYS" > "$SCRIPT_STORAGE_DIR/.cron" + fi - cru a "$SCRIPT_NAME" "$CRU_MINUTES $CRU_HOURS * * $CRU_DAYNUMBERS /jffs/scripts/$SCRIPT_NAME generate" - echo "$CRU_MINUTES $CRU_HOURS * * $CRU_DAYNUMBERS" > "$SCRIPT_STORAGE_DIR/.cron" + STARTUPLINECOUNTTRIM="$(cru l | grep -c "${SCRIPT_NAME}_trimDB")" + STARTUPLINECOUNTEXTRIM="$(cru l | grep "${SCRIPT_NAME}_trimDB" | grep -c "^$defTrimDB_Mins $defTrimDB_Hour [*] [*]")" + if [ "$STARTUPLINECOUNTTRIM" -gt 0 ] && [ "$STARTUPLINECOUNTEXTRIM" -eq 0 ] + then + cru d "${SCRIPT_NAME}_trimDB" + STARTUPLINECOUNTTRIM="$(cru l | grep -c "${SCRIPT_NAME}_trimDB")" + fi + if [ "$STARTUPLINECOUNTTRIM" -eq 0 ]; then + cru a "${SCRIPT_NAME}_trimDB" "$defTrimDB_Mins $defTrimDB_Hour * * * /jffs/scripts/$SCRIPT_NAME trimdb" fi ;; delete) - STARTUPLINECOUNT="$(cru l | grep -c "$SCRIPT_NAME")" - if [ "$STARTUPLINECOUNT" -gt 0 ]; then - cru d "$SCRIPT_NAME" + STARTUPLINECOUNTGEN="$(cru l | grep -c "#${SCRIPT_NAME}#")" + if [ "$STARTUPLINECOUNTGEN" -gt 0 ]; then + cru d "${SCRIPT_NAME}" + fi + STARTUPLINECOUNTGEN="$(cru l | grep -c "#${SCRIPT_NAME}_generate#")" + if [ "$STARTUPLINECOUNTGEN" -gt 0 ]; then + cru d "${SCRIPT_NAME}_generate" + fi + STARTUPLINECOUNTTRIM="$(cru l | grep -c "#${SCRIPT_NAME}_trimDB#")" + if [ "$STARTUPLINECOUNTTRIM" -gt 0 ]; then + cru d "${SCRIPT_NAME}_trimDB" fi ;; esac @@ -842,7 +1097,8 @@ Get_WebUI_URL(){ ### ### ### locking mechanism code credit to Martineau (@MartineauUK) ### -Mount_WebUI(){ +Mount_WebUI() +{ Print_Output true "Mounting WebUI tab for $SCRIPT_NAME" "$PASS" LOCKFILE=/tmp/addonwebui.lock FD=386 @@ -857,7 +1113,8 @@ Mount_WebUI(){ cp -f "$SCRIPT_DIR/connmonstats_www.asp" "$SCRIPT_WEBPAGE_DIR/$MyPage" echo "$SCRIPT_NAME" > "$SCRIPT_WEBPAGE_DIR/$(echo $MyPage | cut -f1 -d'.').title" - if [ "$(/bin/uname -o)" = "ASUSWRT-Merlin" ]; then + if [ "$(/bin/uname -o)" = "ASUSWRT-Merlin" ] + then if [ ! -f /tmp/index_style.css ]; then cp -f /www/index_style.css /tmp/ fi @@ -898,7 +1155,8 @@ Mount_WebUI(){ Print_Output true "Mounted $SCRIPT_NAME WebUI page as $MyPage" "$PASS" } -ExcludeFromQoS(){ +ExcludeFromQoS() +{ case "$1" in enable) sed -i 's/^EXCLUDEFROMQOS=.*$/EXCLUDEFROMQOS=true/' "$SCRIPT_CONF" @@ -913,100 +1171,139 @@ ExcludeFromQoS(){ esac } -AutomaticMode(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +AutomaticMode() +{ case "$1" in enable) - sed -i 's/^AUTOMATED=.*$/AUTOMATED=true/' "$SCRIPT_CONF" + if AutomaticMode check + then + printf "\nAutomatic ping tests are already ${GRNct}ENABLED${CLEARct}.\n\n" + return 0 + fi + sed -i 's/^AUTOMATICMODE=.*$/AUTOMATICMODE=true/' "$SCRIPT_CONF" Auto_Cron create 2>/dev/null + printf "Automatic ping tests are now ${GRNct}ENABLED${CLEARct}.\n\n" + _UpdateAutomaticModeState_ ;; disable) - sed -i 's/^AUTOMATED=.*$/AUTOMATED=false/' "$SCRIPT_CONF" + if ! AutomaticMode check + then + printf "\nAutomatic ping tests are already ${REDct}DISABLED${CLEARct}.\n\n" + return 0 + fi + sed -i 's/^AUTOMATICMODE=.*$/AUTOMATICMODE=false/' "$SCRIPT_CONF" Auto_Cron delete 2>/dev/null + printf "Automatic ping tests are now ${REDct}DISABLED${CLEARct}.\n\n" + _UpdateAutomaticModeState_ ;; check) - AUTOMATED="$(Conf_Parameters check AUTOMATED)" - if [ "$AUTOMATED" = "true" ]; then return 0; else return 1; fi + AUTOMATICMODE="$(Conf_Parameters check AUTOMATICMODE)" + if [ "${AUTOMATICMODE:=true}" = "true" ]; then return 0; else return 1; fi ;; esac } -TestSchedule(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +CronTestSchedule() +{ case "$1" in update) sed -i 's/^SCHDAYS=.*$/SCHDAYS='"$(echo "$2" | sed 's/0/Sun/;s/1/Mon/;s/2/Tues/;s/3/Wed/;s/4/Thurs/;s/5/Fri/;s/6/Sat/;')"'/' "$SCRIPT_CONF" sed -i 's~^SCHHOURS=.*$~SCHHOURS='"$3"'~' "$SCRIPT_CONF" sed -i 's~^SCHMINS=.*$~SCHMINS='"$4"'~' "$SCRIPT_CONF" - Auto_Cron delete 2>/dev/null - Auto_Cron create 2>/dev/null + AutomaticMode check && Auto_Cron create 2>/dev/null ;; check) SCHDAYS="$(Conf_Parameters check SCHDAYS)" SCHHOURS="$(Conf_Parameters check SCHHOURS)" SCHMINS="$(Conf_Parameters check SCHMINS)" - echo "$SCHDAYS|$SCHHOURS|$SCHMINS" + echo "${SCHDAYS:=*}|${SCHHOURS:=*}|${SCHMINS:=*/3}" ;; esac } -ScriptStorageLocation(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +ScriptStorageLocation() +{ case "$1" in usb) + printf "Please wait..." sed -i 's/^STORAGELOCATION=.*$/STORAGELOCATION=usb/' "$SCRIPT_CONF" mkdir -p "/opt/share/$SCRIPT_NAME.d/" - mv "/jffs/addons/$SCRIPT_NAME.d/csv" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/config" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/config.bak" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/connstatstext.js" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/lastx.csv" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/connstats.db" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.indexcreated" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.newcolumns" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.cron" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.customactioninfo" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.customactionlist" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - mv "/jffs/addons/$SCRIPT_NAME.d/.emailinfo" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null - - SCRIPT_CONF="/opt/share/$SCRIPT_NAME.d/config" - ScriptStorageLocation load + mv -f "/jffs/addons/$SCRIPT_NAME.d/csv" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/config" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/config.bak" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/connstatstext.js" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/lastx.csv" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/connstats.db" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.indexcreated" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.newcolumns" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.cron" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.customactioninfo" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.customactionlist" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/.emailinfo" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/jffs/addons/$SCRIPT_NAME.d/userscripts.d" "/opt/share/$SCRIPT_NAME.d/" 2>/dev/null + SCRIPT_CONF="/opt/share/${SCRIPT_NAME}.d/config" + CONNSTATS_DB="/opt/share/${SCRIPT_NAME}.d/connstats.db" + CSV_OUTPUT_DIR="/opt/share/${SCRIPT_NAME}.d/csv" + ScriptStorageLocation load true + sleep 2 ;; jffs) + printf "Please wait..." sed -i 's/^STORAGELOCATION=.*$/STORAGELOCATION=jffs/' "$SCRIPT_CONF" mkdir -p "/jffs/addons/$SCRIPT_NAME.d/" - mv "/opt/share/$SCRIPT_NAME.d/csv" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/config" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/config.bak" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/connstatstext.js" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/lastx.csv" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/connstats.db" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.indexcreated" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.newcolumns" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.cron" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.customactioninfo" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.customactionlist" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - mv "/opt/share/$SCRIPT_NAME.d/.emailinfo" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null - SCRIPT_CONF="/jffs/addons/$SCRIPT_NAME.d/config" - ScriptStorageLocation load + mv -f "/opt/share/$SCRIPT_NAME.d/csv" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/config" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/config.bak" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/connstatstext.js" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/lastx.csv" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/connstats.db" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.indexcreated" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.newcolumns" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.cron" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.customactioninfo" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.customactionlist" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/.emailinfo" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + mv -f "/opt/share/$SCRIPT_NAME.d/userscripts.d" "/jffs/addons/$SCRIPT_NAME.d/" 2>/dev/null + SCRIPT_CONF="/jffs/addons/${SCRIPT_NAME}.d/config" + CONNSTATS_DB="/jffs/addons/${SCRIPT_NAME}.d/connstats.db" + CSV_OUTPUT_DIR="/jffs/addons/${SCRIPT_NAME}.d/csv" + ScriptStorageLocation load true + sleep 2 ;; check) STORAGELOCATION="$(Conf_Parameters check STORAGELOCATION)" - echo "$STORAGELOCATION" + echo "${STORAGELOCATION:=jffs}" ;; load) STORAGELOCATION="$(Conf_Parameters check STORAGELOCATION)" - if [ "$STORAGELOCATION" = "usb" ]; then - SCRIPT_STORAGE_DIR="/opt/share/$SCRIPT_NAME.d" - elif [ "$STORAGELOCATION" = "jffs" ]; then - SCRIPT_STORAGE_DIR="/jffs/addons/$SCRIPT_NAME.d" + if [ "$STORAGELOCATION" = "usb" ] + then + SCRIPT_STORAGE_DIR="/opt/share/${SCRIPT_NAME}.d" + elif [ "$STORAGELOCATION" = "jffs" ] + then + SCRIPT_STORAGE_DIR="/jffs/addons/${SCRIPT_NAME}.d" fi - + CONNSTATS_DB="$SCRIPT_STORAGE_DIR/connstats.db" CSV_OUTPUT_DIR="$SCRIPT_STORAGE_DIR/csv" USER_SCRIPT_DIR="$SCRIPT_STORAGE_DIR/userscripts.d" + if [ $# -gt 1 ] && [ "$2" = "true" ] + then _UpdateJFFS_FreeSpaceInfo_ ; fi ;; esac } -OutputTimeMode(){ +OutputTimeMode() +{ case "$1" in unix) sed -i 's/^OUTPUTTIMEMODE=.*$/OUTPUTTIMEMODE=unix/' "$SCRIPT_CONF" @@ -1024,36 +1321,51 @@ OutputTimeMode(){ } ##----------------------------------------## -## Modified by Martinski W. [2024-Jul-14] ## +## Modified by Martinski W. [2024-Nov-23] ## ##----------------------------------------## WriteStats_ToJS() { if [ $# -lt 4 ] ; then return 1 ; fi - echo "function $3(){" > "$2" + if [ -f "$2" ] + then + sed -i -e '/}/d;/function/d;/document.getElementById/d;/databaseResetDone/d;' "$2" + awk 'NF' "$2" > "${2}.tmp" + mv -f "${2}.tmp" "$2" + fi + printf "\nfunction %s(){\n" "$3" >> "$2" html='document.getElementById("'"$4"'").innerHTML="' while IFS='' read -r line || [ -n "$line" ] - do html="${html}${line}\r\n" + do html="${html}${line}" done < "$1" html="$html"'"' if [ $# -lt 5 ] || [ -z "$5" ] - then printf "%s\r\n}\r\n" "$html" >> "$2" - else printf "%s;\r\n%s\r\n}\r\n" "$html" "$5" >> "$2" + then printf "%s\n}\n" "$html" >> "$2" + else printf "%s;\n%s\n}\n" "$html" "$5" >> "$2" fi } -#$1 fieldname $2 tablename $3 frequency (hours) $4 length (days) $5 outputfile $6 outputfrequency $7 sqlfile $8 timestamp -WriteSql_ToFile(){ +##---------------------------------------------------------------------- +## $1 fieldname $2 tablename $3 frequency (hours) $4 length (days) +## $5 outputfile $6 outputfrequency $7 sqlfile $8 timestamp +##---------------------------------------------------------------------- +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +WriteSql_ToFile() +{ timenow="$8" maxcount="$(echo "$3" "$4" | awk '{printf ((24*$2)/$1)}')" - if ! echo "$5" | grep -q "day"; then + if ! echo "$5" | grep -q "day" + then { echo ".mode csv" echo ".headers on" echo ".output ${5}_${6}.htm" + echo "PRAGMA temp_store=1;" echo "SELECT '$1' Metric,Min(strftime('%s',datetime(strftime('%Y-%m-%d %H:00:00',datetime([Timestamp],'unixepoch'))))) Time,IFNULL(Avg([$1]),'NaN') Value FROM $2 WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-$maxcount hour'))) GROUP BY strftime('%m',datetime([Timestamp],'unixepoch')),strftime('%d',datetime([Timestamp],'unixepoch')),strftime('%H',datetime([Timestamp],'unixepoch')) ORDER BY [Timestamp] DESC;" } > "$7" else @@ -1061,14 +1373,353 @@ WriteSql_ToFile(){ echo ".mode csv" echo ".headers on" echo ".output ${5}_${6}.htm" + echo "PRAGMA temp_store=1;" echo "SELECT '$1' Metric,Max(strftime('%s',datetime([Timestamp],'unixepoch','start of day'))) Time,IFNULL(Avg([$1]),'NaN') Value FROM $2 WHERE ([Timestamp] > strftime('%s',datetime($timenow,'unixepoch','start of day','+1 day','-$maxcount day'))) GROUP BY strftime('%m',datetime([Timestamp],'unixepoch')),strftime('%d',datetime([Timestamp],'unixepoch')) ORDER BY [Timestamp] DESC;" } > "$7" fi } -Run_PingTest(){ - if [ ! -f /opt/bin/xargs ]; then - Print_Output true "Installing findutils from Entware" +##-------------------------------------## +## Added by Martinski W. [2024-Nov-23] ## +##-------------------------------------## +_GetFileSize_() +{ + local sizeUnits sizeInfo fileSize + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -s "$1" ] + then echo 0; return 1 ; fi + + if [ $# -lt 2 ] || [ -z "$2" ] || \ + ! echo "$2" | grep -qE "^(B|KB|MB|GB|HR|HRx)$" + then sizeUnits="B" ; else sizeUnits="$2" ; fi + + _GetNum_() { printf "%.1f" "$(echo "$1" | awk "{print $1}")" ; } + + case "$sizeUnits" in + B|KB|MB|GB) + fileSize="$(ls -1l "$1" | awk -F ' ' '{print $3}')" + case "$sizeUnits" in + KB) fileSize="$(_GetNum_ "($fileSize / $oneKByte)")" ;; + MB) fileSize="$(_GetNum_ "($fileSize / $oneMByte)")" ;; + GB) fileSize="$(_GetNum_ "($fileSize / $oneGByte)")" ;; + esac + echo "$fileSize" + ;; + HR|HRx) + fileSize="$(ls -1lh "$1" | awk -F ' ' '{print $3}')" + sizeInfo="${fileSize}B" + if [ "$sizeUnits" = "HR" ] + then echo "$sizeInfo" ; return 0 ; fi + sizeUnits="$(echo "$sizeInfo" | tr -d '.0-9')" + case "$sizeUnits" in + MB) fileSize="$(_GetFileSize_ "$1" KB)" + sizeInfo="$sizeInfo [${fileSize}KB]" + ;; + GB) fileSize="$(_GetFileSize_ "$1" MB)" + sizeInfo="$sizeInfo [${fileSize}MB]" + ;; + esac + echo "$sizeInfo" + ;; + *) echo 0 ;; + esac + return 0 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_Get_JFFS_Space_() +{ + local typex total usedx freex totalx + local sizeUnits sizeType sizeInfo sizeNum + local jffsMountStr jffsUsageStr percentNum percentStr + + if [ $# -lt 1 ] || [ -z "$1" ] || \ + ! echo "$1" | grep -qE "^(ALL|USED|FREE)$" + then sizeType="ALL" ; else sizeType="$1" ; fi + + if [ $# -lt 2 ] || [ -z "$2" ] || \ + ! echo "$2" | grep -qE "^(KB|KBP|MBP|GBP|HR|HRx)$" + then sizeUnits="KB" ; else sizeUnits="$2" ; fi + + _GetNum_() { printf "%.2f" "$(echo "$1" | awk "{print $1}")" ; } + + jffsMountStr="$(mount | grep '/jffs')" + jffsUsageStr="$(df -kT /jffs | grep -E '.*[[:blank:]]+/jffs$')" + + if [ -z "$jffsMountStr" ] || [ -z "$jffsUsageStr" ] + then echo "**ERROR**: JFFS is *NOT* mounted." ; return 1 + fi + if echo "$jffsMountStr" | grep -qE "[[:blank:]]+[(]?ro[[:blank:],]" + then echo "**ERROR**: JFFS is mounted READ-ONLY." ; return 2 + fi + + typex="$(echo "$jffsUsageStr" | awk -F ' ' '{print $2}')" + total="$(echo "$jffsUsageStr" | awk -F ' ' '{print $3}')" + usedx="$(echo "$jffsUsageStr" | awk -F ' ' '{print $4}')" + freex="$(echo "$jffsUsageStr" | awk -F ' ' '{print $5}')" + totalx="$total" + if [ "$typex" = "ubifs" ] && [ "$((usedx + freex))" -ne "$total" ] + then totalx="$((usedx + freex))" ; fi + + if [ "$sizeType" = "ALL" ] ; then echo "$totalx" ; return 0 ; fi + + case "$sizeUnits" in + KB|KBP|MBP|GBP) + case "$sizeType" in + USED) sizeNum="$usedx" + percentNum="$(printf "%.1f" "$(_GetNum_ "($usedx * 100 / $totalx)")")" + percentStr="[${percentNum}%]" + ;; + FREE) sizeNum="$freex" + percentNum="$(printf "%.1f" "$(_GetNum_ "($freex * 100 / $totalx)")")" + percentStr="[${percentNum}%]" + ;; + esac + case "$sizeUnits" in + KB) sizeInfo="$sizeNum" + ;; + KBP) sizeInfo="${sizeNum}.0KB $percentStr" + ;; + MBP) sizeNum="$(_GetNum_ "($sizeNum / $oneKByte)")" + sizeInfo="${sizeNum}MB $percentStr" + ;; + GBP) sizeNum="$(_GetNum_ "($sizeNum / $oneMByte)")" + sizeInfo="${sizeNum}GB $percentStr" + ;; + esac + echo "$sizeInfo" + ;; + HR|HRx) + jffsUsageStr="$(df -hT /jffs | grep -E '.*[[:blank:]]+/jffs$')" + case "$sizeType" in + USED) usedx="$(echo "$jffsUsageStr" | awk -F ' ' '{print $4}')" + sizeInfo="${usedx}B" + ;; + FREE) freex="$(echo "$jffsUsageStr" | awk -F ' ' '{print $5}')" + sizeInfo="${freex}B" + ;; + esac + if [ "$sizeUnits" = "HR" ] + then echo "$sizeInfo" ; return 0 ; fi + sizeUnits="$(echo "$sizeInfo" | tr -d '.0-9')" + case "$sizeUnits" in + KB) sizeInfo="$(_Get_JFFS_Space_ "$sizeType" KBP)" ;; + MB) sizeInfo="$(_Get_JFFS_Space_ "$sizeType" MBP)" ;; + GB) sizeInfo="$(_Get_JFFS_Space_ "$sizeType" GBP)" ;; + esac + echo "$sizeInfo" + ;; + *) echo 0 ;; + esac + return 0 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +## Check JFFS free space *before* moving files from USB ## +##------------------------------------------------------## +_Check_JFFS_SpaceAvailable_() +{ + local requiredSpace jffsAllxSpace jffsFreeSpace jffsMinxSpace + if [ $# -eq 0 ] || [ -z "$1" ] || [ ! -d "$1" ] ; then return 0 ; fi + + [ "$1" = "/jffs/addons/$SCRIPT_NAME.d" ] && return 0 + + if ! jffsAllxSpace="$(_Get_JFFS_Space_ ALL KB)" ; then return 1 ; fi + if ! jffsFreeSpace="$(_Get_JFFS_Space_ FREE KB)" ; then return 1 ; fi + + jffsAllxSpace="$(echo "$jffsAllxSpace" | awk '{printf("%d", $1 * 1024);}')" + jffsFreeSpace="$(echo "$jffsFreeSpace" | awk '{printf("%d", $1 * 1024);}')" + + requiredSpace="$(du -kc "$1" | grep -w 'total$' | awk -F ' ' '{print $1}')" + requiredSpace="$(echo "$requiredSpace" | awk '{printf("%d", $1 * 1024);}')" + + ## Make sure remaining free space is greater than 20% of total space ## + jffsMinxSpace="$(echo "$jffsAllxSpace" | awk '{printf("%d", $1 * 20 / 100);}')" + requiredSpace="$((requiredSpace + jffsMinxSpace))" + [ "$requiredSpace" -lt "$jffsFreeSpace" ] && return 0 + + requiredSpace="$(du -hc "$1" | grep -w 'total$' | awk -F ' ' '{print $1}')" + errorMsg1="Not enough free space ["$(_Get_JFFS_Space_ FREE HR)"] available in JFFS." + errorMsg2="Minimum storage space required: $requiredSpace" + Print_Output true "${errorMsg1} ${errorMsg2}" "$CRIT" + return 1 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_UpdateJFFS_FreeSpaceInfo_() +{ + local jffsFreeSpace + local outJSfile="$SCRIPT_STORAGE_DIR/connstatstext.js" + [ ! -d "$SCRIPT_STORAGE_DIR" ] && return 1 + + jffsFreeSpace="$(_Get_JFFS_Space_ FREE HRx)" + if [ ! -s "$outJSfile" ] || \ + ! grep -q "^var jffsAvailableSpace =.*" "$outJSfile" + then + sed -i "1 i var jffsAvailableSpace = '${jffsFreeSpace}';" "$outJSfile" + else + sed -i "s/^var jffsAvailableSpace =.*/var jffsAvailableSpace = '${jffsFreeSpace}';/" "$outJSfile" + fi +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_UpdateAutomaticModeState_() +{ + local automaticModeStatus + local outJSfile="$SCRIPT_STORAGE_DIR/connstatstext.js" + [ ! -d "$SCRIPT_STORAGE_DIR" ] && return 1 + + if AutomaticMode check + then automaticModeStatus="ENABLED" + else automaticModeStatus="DISABLED" + fi + if [ ! -s "$outJSfile" ] || \ + ! grep -q "^var automaticModeState =.*" "$outJSfile" + then + sed -i "3 i var automaticModeState = '${automaticModeStatus}';" "$outJSfile" + else + sed -i "s/^var automaticModeState =.*/var automaticModeState = '${automaticModeStatus}';/" "$outJSfile" + fi +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_UpdateDatabaseFileSizeInfo_() +{ + local databaseFileSize + local outJSfile="$SCRIPT_STORAGE_DIR/connstatstext.js" + [ ! -d "$SCRIPT_STORAGE_DIR" ] && return 1 + + databaseFileSize="$(_GetFileSize_ "$CONNSTATS_DB" HRx)" + if [ ! -s "$outJSfile" ] || \ + ! grep -q "^var sqlDatabaseFileSize =.*" "$outJSfile" + then + sed -i "1 i var sqlDatabaseFileSize = '${databaseFileSize}';" "$outJSfile" + else + sed -i "s/^var sqlDatabaseFileSize =.*/var sqlDatabaseFileSize = '${databaseFileSize}';/" "$outJSfile" + fi + _UpdateJFFS_FreeSpaceInfo_ + _UpdateAutomaticModeState_ +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ApplyDatabaseSQLCmds_() +{ + local errorCount=0 maxErrorCount=5 + local triesCount=0 maxTriesCount=15 sqlErrorMsg + local tempLogFilePath="/tmp/connMonStats_TMP_$$.LOG" + + resultStr="" + foundError=false ; foundLocked=false + rm -f "$tempLogFilePath" + + while [ "$errorCount" -lt "$maxErrorCount" ] && \ + [ "$((triesCount++))" -lt "$maxTriesCount" ] + do + if "$SQLITE3_PATH" "$CONNSTATS_DB" < "$1" >> "$tempLogFilePath" 2>&1 + then foundError=false ; foundLocked=false ; break + fi + sqlErrorMsg="$(tail -n1 "$tempLogFilePath")" + if echo "$sqlErrorMsg" | grep -qE "^(Error:|Parse error|Runtime error)" + then + echo "$sqlErrorMsg" + if echo "$sqlErrorMsg" | grep -qE "^Runtime error .*: database is locked" + then foundLocked=true ; sleep 2 ; continue + fi + errorCount="$((errorCount + 1))" + foundError=true ; foundLocked=false + Print_Output true "SQLite3 failure: $sqlErrorMsg" "$ERR" + fi + [ "$triesCount" -ge "$maxTriesCount" ] && break + [ "$errorCount" -ge "$maxErrorCount" ] && break + sleep 1 + done + + rm -f "$tempLogFilePath" + if "$foundError" + then resultStr="reported error(s)." + elif "$foundLocked" + then resultStr="found database locked." + else resultStr="completed successfully." + fi + if "$foundError" || "$foundLocked" + then + Print_Output true "SQLite process ${resultStr}" "$ERR" + fi +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_Optimize_Database_() +{ + renice 15 $$ + local foundError foundLocked resultStr + + Print_Output true "Running database analysis and optimization..." "$PASS" + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA analysis_limit=0;" + echo "PRAGMA cache_size=-20000;" + echo "ANALYZE connstats;" + echo "VACUUM;" + } > /tmp/connmon-trim.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-trim.sql + + rm -f /tmp/connmon-trim.sql + if "$foundError" || "$foundLocked" + then Print_Output true "Database analysis and optimization ${resultStr}" "$ERR" + else Print_Output true "Database analysis and optimization ${resultStr}" "$PASS" + fi + renice 0 $$ +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_Trim_Database_() +{ + renice 15 $$ + TZ="$(cat /etc/TZ)" + export TZ + timeNow="$(date +'%s')" + + local foundError foundLocked resultStr + + Print_Output true "Trimming records entries from database..." "$PASS" + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "DELETE FROM [connstats] WHERE [Timestamp] < strftime('%s',datetime($timeNow,'unixepoch','-$(DaysToKeep check) day'));" + } > /tmp/connmon-trim.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-trim.sql + + rm -f /tmp/connmon-trim.sql + if "$foundError" || "$foundLocked" + then Print_Output true "Database record trimming ${resultStr}" "$ERR" + else Print_Output true "Database record trimming ${resultStr}" "$PASS" + fi + renice 0 $$ +} + +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Run_PingTest() +{ + if [ ! -f /opt/bin/xargs ] && [ -f /opt/bin/opkg ] + then + Print_Output true "Installing findutils from Entware" "$PASS" opkg update opkg install findutils fi @@ -1080,7 +1731,10 @@ Run_PingTest(){ Create_Dirs Conf_Exists Auto_Startup create 2>/dev/null - if AutomaticMode check; then Auto_Cron create 2>/dev/null; else Auto_Cron delete 2>/dev/null; fi + if AutomaticMode check + then Auto_Cron create 2>/dev/null + else Auto_Cron delete 2>/dev/null + fi Auto_ServiceEvent create 2>/dev/null ScriptStorageLocation load Create_Symlinks @@ -1098,7 +1752,8 @@ Run_PingTest(){ Print_Output false "$pingduration second ping test to $pingtarget starting..." "$PASS" - if ! expr "$pingtarget" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null && nslookup "$pingtarget" >/dev/null 2>&1; then + if ! expr "$pingtarget" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null && nslookup "$pingtarget" >/dev/null 2>&1 + then pingtargetip="$(dig +short +answer "$pingtarget" | head -n 1)" completepingtarget="$pingtarget ($pingtargetip)" else @@ -1107,8 +1762,10 @@ Run_PingTest(){ fi stoppedqos="false" - if [ "$(ExcludeFromQoS check)" = "true" ]; then - if [ "$(nvram get qos_enable)" -eq 1 ] && [ "$(nvram get qos_type)" -eq 1 ]; then + if [ "$(ExcludeFromQoS check)" = "true" ] + then + if [ "$(nvram get qos_enable)" -eq 1 ] && [ "$(nvram get qos_type)" -eq 1 ] + then for ACTION in -D -A ; do iptables "$ACTION" OUTPUT -p icmp -j MARK --set-xmark 0x80000000/0xC0000000 2>/dev/null iptables -t mangle "$ACTION" OUTPUT -p icmp -j MARK --set-xmark 0x80000000/0xC0000000 2>/dev/null @@ -1126,7 +1783,8 @@ Run_PingTest(){ ping -w "$pingduration" "$pingtargetip" > "$pingfile" - if [ "$stoppedqos" = "true" ]; then + if [ "$stoppedqos" = "true" ] + then if [ "$(nvram get qos_enable)" -eq 1 ] && [ "$(nvram get qos_type)" -eq 1 ]; then iptables -D OUTPUT -p icmp -j MARK --set-xmark 0x80000000/0xC0000000 2>/dev/null iptables -t mangle -D OUTPUT -p icmp -j MARK --set-xmark 0x80000000/0xC0000000 2>/dev/null @@ -1146,11 +1804,14 @@ Run_PingTest(){ PINGLIST="$(grep seq= "$pingfile")" PINGCOUNT="$(echo "$PINGLIST" | sed '/^\s*$/d' | wc -l)" DIFFCOUNT="$((PINGCOUNT - 1))" - if [ "$PINGCOUNT" -gt 0 ]; then - until [ "$COUNTER" -gt "$PINGCOUNT" ]; do + if [ "$PINGCOUNT" -gt 0 ] + then + until [ "$COUNTER" -gt "$PINGCOUNT" ] + do CURPING="$(echo "$PINGLIST" | sed -n "$COUNTER"p | cut -f4 -d"=" | cut -f1 -d" ")" - if [ "$COUNTER" -gt 1 ]; then + if [ "$COUNTER" -gt 1 ] + then DIFF="$(echo "$CURPING" "$PREVPING" | awk '{printf "%4.3f\n",$1-$2}')" NEG="$(echo "$DIFF" 0 | awk '{ if ($1 < $2) print "neg"; else print "pos"}')" if [ "$NEG" = "neg" ]; then DIFF="$(echo "$DIFF" "-1" | awk '{printf "%4.3f\n",$1*$2}')"; fi @@ -1164,14 +1825,15 @@ Run_PingTest(){ TZ="$(cat /etc/TZ)" export TZ - timenow="$(/bin/date +"%s")" + timenow="$(/bin/date +'%s')" timenowfriendly="$(/bin/date +"%c")" ping=0 jitter=0 linequal=0 - if [ "$PINGCOUNT" -gt 1 ]; then + if [ "$PINGCOUNT" -gt 1 ] + then ping="$(tail -n 1 "$pingfile" | cut -f4 -d"/")" jitter="$(echo "$TOTALDIFF" "$DIFFCOUNT" | awk '{printf "%4.3f\n",$1/$2}')" pkt_trans="$(tail -n 2 "$pingfile" | head -n 1 | cut -f1 -d"," | cut -f1 -d" ")" @@ -1182,31 +1844,25 @@ Run_PingTest(){ Process_Upgrade { - echo "CREATE TABLE IF NOT EXISTS [connstats] ([StatID] INTEGER PRIMARY KEY NOT NULL,[Timestamp] NUMERIC NOT NULL,[Ping] REAL NOT NULL,[Jitter] REAL NOT NULL,[LineQuality] REAL NOT NULL,[PingTarget] TEXT NOT NULL,[PingDuration] NUMERIC);" - echo "INSERT INTO connstats ([Timestamp],[Ping],[Jitter],[LineQuality],[PingTarget],[PingDuration]) values($timenow,$ping,$jitter,$linequal,'$completepingtarget',$pingduration);" + echo "PRAGMA journal_mode=WAL;" + echo "PRAGMA temp_store=1;" + echo "CREATE TABLE IF NOT EXISTS [connstats] ([StatID] INTEGER PRIMARY KEY NOT NULL,[Timestamp] NUMERIC NOT NULL,[Ping] REAL NOT NULL,[Jitter] REAL NOT NULL,[LineQuality] REAL NOT NULL,[PingTarget] TEXT NOT NULL,[PingDuration] NUMERIC);" + echo "INSERT INTO connstats ([Timestamp],[Ping],[Jitter],[LineQuality],[PingTarget],[PingDuration]) values($timenow,$ping,$jitter,$linequal,'$completepingtarget',$pingduration);" } > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql - - { - echo "DELETE FROM [connstats] WHERE [Timestamp] < strftime('%s',datetime($timenow,'unixepoch','-$(DaysToKeep check) day'));" - echo "PRAGMA analysis_limit=0;" - echo "PRAGMA cache_size=-20000;" - echo "ANALYZE connstats;" - } > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql >/dev/null 2>&1 - rm -f /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql echo 'var connmonstatus = "GenerateCSV";' > "$SCRIPT_WEB_DIR/detect_connmon.js" - Generate_CSVs + _UpdateDatabaseFileSizeInfo_ + echo "Stats last updated: $timenowfriendly" > /tmp/connstatstitle.txt WriteStats_ToJS /tmp/connstatstitle.txt "$SCRIPT_STORAGE_DIR/connstatstext.js" setConnmonStatsTitle statstitle - Print_Output false "Test results - Ping $ping ms - Jitter - $jitter ms - Line Quality $linequal %" "$PASS" + Print_Output false "Test results: Ping $ping ms - Jitter - $jitter ms - Line Quality ${linequal}%" "$PASS" { - printf "Ping test result\\n" - printf "\\nPing %s ms - Jitter - %s ms - Line Quality %s %%\\n" "$ping" "$jitter" "$linequal" + printf "Ping test result\n" + printf "\nPing %s ms - Jitter - %s ms - Line Quality %s %%\n" "$ping" "$jitter" "$linequal" } >> "$resultfile" rm -f "$pingfile" @@ -1228,7 +1884,11 @@ Run_PingTest(){ echo 'var connmonstatus = "Done";' > "$SCRIPT_WEB_DIR/detect_connmon.js" } -Generate_CSVs(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Generate_CSVs() +{ Process_Upgrade renice 15 $$ OUTPUTTIMEMODE="$(OutputTimeMode check)" @@ -1240,48 +1900,52 @@ Generate_CSVs(){ metriclist="Ping Jitter LineQuality" - for metric in $metriclist; do + for metric in $metriclist + do { echo ".mode csv" echo ".headers on" echo ".output $CSV_OUTPUT_DIR/${metric}_raw_daily.htm" + echo "PRAGMA temp_store=1;" echo "SELECT '$metric' Metric,[Timestamp] Time,[$metric] Value FROM connstats WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-1 day'))) ORDER BY [Timestamp] DESC;" } > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql { echo ".mode csv" echo ".headers on" echo ".output $CSV_OUTPUT_DIR/${metric}_raw_weekly.htm" + echo "PRAGMA temp_store=1;" echo "SELECT '$metric' Metric,[Timestamp] Time,[$metric] Value FROM connstats WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-7 day'))) ORDER BY [Timestamp] DESC;" } > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql { echo ".mode csv" echo ".headers on" echo ".output $CSV_OUTPUT_DIR/${metric}_raw_monthly.htm" + echo "PRAGMA temp_store=1;" echo "SELECT '$metric' Metric,[Timestamp] Time,[$metric] Value FROM connstats WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-30 day'))) ORDER BY [Timestamp] DESC;" } > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 1 1 "$CSV_OUTPUT_DIR/${metric}_hour" daily /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 1 7 "$CSV_OUTPUT_DIR/${metric}_hour" weekly /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 1 30 "$CSV_OUTPUT_DIR/${metric}_hour" monthly /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 24 1 "$CSV_OUTPUT_DIR/${metric}_day" daily /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 24 7 "$CSV_OUTPUT_DIR/${metric}_day" weekly /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql WriteSql_ToFile "$metric" connstats 24 30 "$CSV_OUTPUT_DIR/${metric}_day" monthly /tmp/connmon-stats.sql "$timenow" - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql rm -f "$CSV_OUTPUT_DIR/${metric}daily.htm" rm -f "$CSV_OUTPUT_DIR/${metric}weekly.htm" @@ -1292,12 +1956,14 @@ Generate_CSVs(){ Generate_LastXResults { - echo ".mode csv" - echo ".headers on" - echo ".output $CSV_OUTPUT_DIR/CompleteResults.htm" - } > /tmp/connmon-complete.sql - echo "SELECT [Timestamp],[Ping],[Jitter],[LineQuality],[PingTarget],[PingDuration] FROM connstats WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-$(DaysToKeep check) day'))) ORDER BY [Timestamp] DESC;" >> /tmp/connmon-complete.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-complete.sql + echo ".mode csv" + echo ".headers on" + echo ".output $CSV_OUTPUT_DIR/CompleteResults.htm" + echo "PRAGMA temp_store=1;" + echo "SELECT [Timestamp],[Ping],[Jitter],[LineQuality],[PingTarget],[PingDuration] FROM connstats WHERE ([Timestamp] >= strftime('%s',datetime($timenow,'unixepoch','-$(DaysToKeep check) day'))) ORDER BY [Timestamp] DESC;" + } > /tmp/connmon-complete.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-complete.sql + rm -f /tmp/connmon-complete.sql sed -i 's/"//g' "$CSV_OUTPUT_DIR/CompleteResults.htm" @@ -1307,10 +1973,13 @@ Generate_CSVs(){ mkdir -p "$tmpoutputdir" mv "$CSV_OUTPUT_DIR/CompleteResults.htm" "$tmpoutputdir/CompleteResults.htm" - if [ "$OUTPUTTIMEMODE" = "unix" ]; then + if [ "$OUTPUTTIMEMODE" = "unix" ] + then find "$tmpoutputdir/" -name '*.htm' -exec sh -c 'i="$1"; mv -- "$i" "${i%.htm}.csv"' _ {} \; - elif [ "$OUTPUTTIMEMODE" = "non-unix" ]; then - for i in "$tmpoutputdir/"*".htm"; do + elif [ "$OUTPUTTIMEMODE" = "non-unix" ] + then + for i in "$tmpoutputdir/"*".htm" + do awk -F"," 'NR==1 {OFS=","; print} NR>1 {OFS=","; $1=strftime("%Y-%m-%d %H:%M:%S", $1); print }' "$i" > "$i.out" done @@ -1324,43 +1993,51 @@ Generate_CSVs(){ renice 0 $$ } -Generate_LastXResults(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Generate_LastXResults() +{ rm -f "$SCRIPT_STORAGE_DIR/connjs.js" rm -f "$SCRIPT_STORAGE_DIR/lastx.htm" { echo ".mode csv" echo ".output /tmp/conn-lastx.csv" + echo "PRAGMA temp_store=1;" echo "SELECT [Timestamp],[Ping],[Jitter],[LineQuality],[PingTarget],[PingDuration] FROM connstats ORDER BY [Timestamp] DESC LIMIT $(LastXResults check);" } > /tmp/conn-lastx.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/conn-lastx.sql + _ApplyDatabaseSQLCmds_ /tmp/conn-lastx.sql + rm -f /tmp/conn-lastx.sql sed -i 's/"//g' /tmp/conn-lastx.csv mv /tmp/conn-lastx.csv "$SCRIPT_STORAGE_DIR/lastx.csv" } - ##----------------------------------------## -## Modified by Martinski W. [2024-Jul-14] ## +## Modified by Martinski W. [2024-Dec-21] ## ##----------------------------------------## Reset_DB() { - SIZEAVAIL="$(df -P -k "$SCRIPT_STORAGE_DIR" | awk '{print $4}' | tail -n 1)" - SIZEDB="$(ls -l "$SCRIPT_STORAGE_DIR/connstats.db" | awk '{print $5}')" + SIZEAVAIL="$(df -kP "$SCRIPT_STORAGE_DIR" | awk -F ' ' '{print $4}' | tail -n 1)" + SIZEDB="$(ls -l "$CONNSTATS_DB" | awk -F ' ' '{print $5}')" SIZEAVAIL="$(echo "$SIZEAVAIL" | awk '{printf("%s", $1 * 1024);}')" if [ "$(echo "$SIZEAVAIL $SIZEDB" | awk '{print ($1 < $2)}')" -eq 1 ] then - Print_Output true "Database size exceeds available space. $(ls -lh "$SCRIPT_STORAGE_DIR/connstats.db" | awk '{print $5}')B is required to create backup." "$ERR" + Print_Output true "Database size exceeds available space. $(ls -lh "$CONNSTATS_DB" | awk '{print $5}')B is required to create backup." "$ERR" return 1 else Print_Output true "Sufficient free space to back up database, proceeding..." "$PASS" - if ! cp -a "$SCRIPT_STORAGE_DIR/connstats.db" "$SCRIPT_STORAGE_DIR/connstats.db.bak"; then + if ! cp -a "$CONNSTATS_DB" "${CONNSTATS_DB}.bak"; then Print_Output true "Database backup failed, please check storage device" "$WARN" fi Print_Output false "Please wait..." "$PASS" - echo "DELETE FROM [connstats];" > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + { + echo "PRAGMA temp_store=1;" + echo "DELETE FROM [connstats];" + } > /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql rm -f /tmp/connmon-stats.sql ## Clear/Reset all CSV files ## @@ -1376,6 +2053,7 @@ Reset_DB() Print_Output true "Database reset complete" "$WARN" { sleep 4 + _UpdateDatabaseFileSizeInfo_ timeDateNow="$(/bin/date +"%c")" extraJScode='databaseResetDone = 0;' echo "Stats were reset: $timeDateNow" > /tmp/connstatstitle.txt @@ -1385,39 +2063,73 @@ Reset_DB() fi } -Process_Upgrade(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Process_Upgrade() +{ + local foundError foundLocked resultStr + rm -f "$SCRIPT_STORAGE_DIR/.tableupgraded" - if [ ! -f "$SCRIPT_STORAGE_DIR/.indexcreated" ]; then + if [ ! -f "$SCRIPT_STORAGE_DIR/.indexcreated" ] + then renice 15 $$ Print_Output true "Creating database table indexes..." "$PASS" - echo "CREATE INDEX IF NOT EXISTS idx_time_ping ON connstats (Timestamp,Ping);" > /tmp/connmon-upgrade.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-upgrade.sql - echo "CREATE INDEX IF NOT EXISTS idx_time_jitter ON connstats (Timestamp,Jitter);" > /tmp/connmon-upgrade.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-upgrade.sql - echo "CREATE INDEX IF NOT EXISTS idx_time_linequality ON connstats (Timestamp,LineQuality);" > /tmp/connmon-upgrade.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-upgrade.sql + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "CREATE INDEX IF NOT EXISTS idx_time_ping ON connstats (Timestamp,Ping);" + } > /tmp/connmon-upgrade.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-upgrade.sql + + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "CREATE INDEX IF NOT EXISTS idx_time_jitter ON connstats (Timestamp,Jitter);" + } > /tmp/connmon-upgrade.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-upgrade.sql + + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "CREATE INDEX IF NOT EXISTS idx_time_linequality ON connstats (Timestamp,LineQuality);" + } > /tmp/connmon-upgrade.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-upgrade.sql + rm -f /tmp/connmon-upgrade.sql touch "$SCRIPT_STORAGE_DIR/.indexcreated" Print_Output true "Database ready, continuing..." "$PASS" renice 0 $$ fi - if [ ! -f "$SCRIPT_STORAGE_DIR/.newcolumns" ]; then - echo "ALTER TABLE connstats ADD COLUMN PingTarget [TEXT] NOT NULL DEFAULT '';" > /tmp/connmon-upgrade.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-upgrade.sql - echo "ALTER TABLE connstats ADD COLUMN PingDuration [NUMERIC];" > /tmp/connmon-upgrade.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-upgrade.sql + if [ ! -f "$SCRIPT_STORAGE_DIR/.newcolumns" ] + then + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "ALTER TABLE connstats ADD COLUMN PingTarget [TEXT] NOT NULL DEFAULT '';" + } > /tmp/connmon-upgrade.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-upgrade.sql + + { + echo "PRAGMA temp_store=1;" + echo "PRAGMA cache_size=-20000;" + echo "ALTER TABLE connstats ADD COLUMN PingDuration [NUMERIC];" + } > /tmp/connmon-upgrade.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-upgrade.sql + rm -f /tmp/connmon-upgrade.sql touch "$SCRIPT_STORAGE_DIR/.newcolumns" fi if [ ! -f "$SCRIPT_STORAGE_DIR/lastx.csv" ]; then Generate_LastXResults fi - if [ ! -f /opt/bin/dig ]; then + if [ ! -f /opt/bin/dig ] && [ -f /opt/bin/opkg ] + then opkg update opkg install bind-dig fi if [ ! -f "$SCRIPT_STORAGE_DIR/.cron" ]; then - cru l | grep "$SCRIPT_NAME" | cut -f1-5 -d' ' > "$SCRIPT_STORAGE_DIR/.cron" + cru l | grep "${SCRIPT_NAME}_generate" | cut -f1-5 -d' ' > "$SCRIPT_STORAGE_DIR/.cron" fi if [ ! -f "$SCRIPT_STORAGE_DIR/.customactioninfo" ]; then CustomAction_Info silent @@ -1428,7 +2140,8 @@ Process_Upgrade(){ if [ ! -f "$SCRIPT_STORAGE_DIR/.emailinfo" ]; then Email_Header silent fi - if [ ! -f /tmp/start_apply.htm ]; then + if [ ! -f /tmp/start_apply.htm ] + then cp -f /www/start_apply.htm /tmp/ if ! grep -q 'addon_settings' /tmp/start_apply.htm ; then sed -i "/}else if(action_script == \"start_sig_check\"){/i }else if(action_script.indexOf(\"addon_settings\") != -1){ \/\/ do nothing" /tmp/start_apply.htm @@ -1445,16 +2158,20 @@ Process_Upgrade(){ if [ ! -f "$SCRIPT_DIR/LICENSE" ]; then Update_File LICENSE fi - if [ ! -f "$SCRIPT_STORAGE_DIR/connstatstext.js" ]; then + if [ ! -f "$SCRIPT_STORAGE_DIR/connstatstext.js" ] + then echo "Stats last updated: Not yet updated" > /tmp/connstatstitle.txt WriteStats_ToJS /tmp/connstatstitle.txt "$SCRIPT_STORAGE_DIR/connstatstext.js" setConnmonStatsTitle statstitle fi + _UpdateDatabaseFileSizeInfo_ } -Shortcut_Script(){ +Shortcut_Script() +{ case $1 in create) - if [ -d /opt/bin ] && [ ! -f "/opt/bin/$SCRIPT_NAME" ] && [ -f "/jffs/scripts/$SCRIPT_NAME" ]; then + if [ -d /opt/bin ] && [ ! -f "/opt/bin/$SCRIPT_NAME" ] && [ -f "/jffs/scripts/$SCRIPT_NAME" ] + then ln -s "/jffs/scripts/$SCRIPT_NAME" /opt/bin chmod 0755 "/opt/bin/$SCRIPT_NAME" fi @@ -1467,21 +2184,23 @@ Shortcut_Script(){ esac } -PressEnter(){ - while true; do - printf "Press enter to continue..." - read -r key +PressEnter() +{ + while true + do + printf "Press key to continue..." + read -rs key case "$key" in - *) - break - ;; + *) break ;; esac done return 0 } -Email_ConfExists(){ - if [ -f "$EMAIL_CONF" ]; then +Email_ConfExists() +{ + if [ -f "$EMAIL_CONF" ] + then dos2unix "$EMAIL_CONF" chmod 0644 "$EMAIL_CONF" . "$EMAIL_CONF" @@ -1509,8 +2228,10 @@ Email_ConfExists(){ fi } -Email_Header(){ - if [ -z "$1" ]; then +Email_Header() +{ + if [ -z "$1" ] + then printf "If you have Two Factor Authentication (2FA) enabled you need to\\n" printf "use an App password.\\n\\n" printf "${BOLD}Common SMTP Server settings${CLEARFORMAT}\\n" @@ -1538,9 +2259,11 @@ Email_Header(){ } > "$SCRIPT_STORAGE_DIR/.emailinfo" } -Email_EmailAddress(){ +Email_EmailAddress() +{ EMAIL_ADDRESS="" - while true; do + while true + do printf "\\n${BOLD}Enter email address:${CLEARFORMAT} " read -r EMAIL_ADDRESS if [ "$EMAIL_ADDRESS" = "e" ]; then @@ -1572,9 +2295,11 @@ Email_EmailAddress(){ done } -Email_RouterName(){ +Email_RouterName() +{ FRIENDLY_ROUTER_NAME="" - while true; do + while true + do printf "\\n${BOLD}Enter friendly router name:${CLEARFORMAT} " read -r FRIENDLY_ROUTER_NAME if [ "$FRIENDLY_ROUTER_NAME" = "e" ]; then @@ -1895,7 +2620,8 @@ SendEmail(){ fi } -Webhook_Targets(){ +Webhook_Targets() +{ case "$1" in update) while true; do @@ -2073,7 +2799,8 @@ linequality value=$LINEQUAL $TIMESTAMP" fi } -ToggleNotificationTypes(){ +ToggleNotificationTypes() +{ case "$1" in enable) sed -i 's/^'"$2"'=.*$/'"$2"'=true/' "$SCRIPT_CONF" @@ -2088,7 +2815,8 @@ ToggleNotificationTypes(){ esac } -Conf_Parameters(){ +Conf_Parameters() +{ case "$1" in update) case "$2" in @@ -2154,8 +2882,8 @@ Conf_Parameters(){ esac ;; check) - NOTIFICATION_SETTING="$(grep "$2=" "$SCRIPT_CONF" | cut -f2 -d"=")" - echo "$NOTIFICATION_SETTING" + CONFIG_SETTING="$(grep "^${2}=" "$SCRIPT_CONF" | cut -f2 -d'=')" + echo "$CONFIG_SETTING" ;; esac } @@ -2168,9 +2896,11 @@ Validate_Float(){ fi } -Notification_String(){ +Notification_String() +{ NOTIFICATION_STRING="" - while true; do + while true + do printf "\\n${BOLD}Enter $1:${CLEARFORMAT} " read -r NOTIFICATION_STRING if [ "$NOTIFICATION_STRING" = "e" ]; then @@ -2198,7 +2928,8 @@ Notification_String(){ done } -Notification_Number(){ +Notification_Number() +{ NOTIFICATION_NUMBER="" while true; do printf "\\n${BOLD}Enter $1:${CLEARFORMAT} " @@ -2228,7 +2959,8 @@ Notification_Number(){ done } -Notification_Float(){ +Notification_Float() +{ NOTIFICATION_FLOAT="" while true; do printf "\\n${BOLD}Enter $1:${CLEARFORMAT} " @@ -2254,7 +2986,8 @@ Notification_Float(){ done } -TriggerNotifications(){ +TriggerNotifications() +{ TRIGGERTYPE="$1" DATETIME="$2" if [ "$TRIGGERTYPE" = "PingTest" ]; then @@ -2274,12 +3007,16 @@ TriggerNotifications(){ fi NOTIFICATIONMETHODS="$(NotificationMethods check "$TRIGGERTYPE")" IFS=$',' - for NOTIFICATIONMETHOD in $NOTIFICATIONMETHODS; do + for NOTIFICATIONMETHOD in $NOTIFICATIONMETHODS + do NOTIFICATIONMETHOD_SETTING="$(echo "NOTIFICATIONS_${NOTIFICATIONMETHOD}" | tr "a-z" "A-Z")" - if ToggleNotificationTypes check "$NOTIFICATIONMETHOD_SETTING"; then - if [ "$NOTIFICATIONMETHOD" = "Email" ]; then + if ToggleNotificationTypes check "$NOTIFICATIONMETHOD_SETTING" + then + if [ "$NOTIFICATIONMETHOD" = "Email" ] + then NOTIFICATIONS_EMAIL_LIST="$(Email_Recipients check)" - if [ -z "$NOTIFICATIONS_EMAIL_LIST" ]; then + if [ -z "$NOTIFICATIONS_EMAIL_LIST" ] + then if [ "$TRIGGERTYPE" = "PingTest" ]; then SendEmail "Ping test result from $SCRIPT_NAME - $DATETIME" "

Ping: $PING
Jitter: $JITTER
Line Quality: $LINEQUAL

" elif [ "$TRIGGERTYPE" = "PingThreshold" ]; then @@ -2361,8 +3098,10 @@ TriggerNotifications(){ fi } -Menu_EmailNotifications(){ - while true; do +Menu_EmailNotifications() +{ + while true + do Email_ConfExists ScriptHeader NOTIFICATIONS_EMAIL="" @@ -2779,8 +3518,10 @@ Menu_InfluxDB(){ done } -Menu_Notifications(){ - while true; do +Menu_Notifications() +{ + while true + do ScriptHeader printf "${BOLD}${UNDERLINE}Notification Types${CLEARFORMAT}\\n" printf "1. Ping test\\n Current methods: ${SETTING}$(NotificationMethods check PingTest)${CLEARFORMAT}\\n\\n" @@ -2849,7 +3590,8 @@ Menu_Notifications(){ done } -NotificationMethods(){ +NotificationMethods() +{ case "$1" in update) while true; do @@ -2968,7 +3710,8 @@ NotificationMethods(){ esac } -ScriptHeader(){ +ScriptHeader() +{ clear printf "\\n" printf "${BOLD}##############################################################${CLEARFORMAT}\\n" @@ -2977,7 +3720,7 @@ ScriptHeader(){ printf "${BOLD}## | (__ | (_) || | | || | | || | | | | || (_) || | | | ##${CLEARFORMAT}\\n" printf "${BOLD}## \___| \___/ |_| |_||_| |_||_| |_| |_| \___/ |_| |_| ##${CLEARFORMAT}\\n" printf "${BOLD}## ##${CLEARFORMAT}\\n" - printf "${BOLD}## %s on %-11s ##${CLEARFORMAT}\\n" "$SCRIPT_VERSION" "$ROUTER_MODEL" + printf "${BOLD}## %s on %-18s ##${CLEARFORMAT}\n" "$SCRIPT_VERSION" "$ROUTER_MODEL" printf "${BOLD}## ##${CLEARFORMAT}\\n" printf "${BOLD}## https://github.com/jackyaz/connmon ##${CLEARFORMAT}\\n" printf "${BOLD}## ##${CLEARFORMAT}\\n" @@ -2985,57 +3728,179 @@ ScriptHeader(){ printf "\\n" } -MainMenu(){ - EXCLUDEFROMQOS_MENU="" - if [ "$(ExcludeFromQoS check)" = "true" ]; then EXCLUDEFROMQOS_MENU="excluded from"; else EXCLUDEFROMQOS_MENU="included in"; fi +##-------------------------------------## +## Added by Martinski W. [2024-Nov-23] ## +##-------------------------------------## +_CronScheduleHourMinsInfo_() +{ + if [ $# -lt 2 ] || [ -z "$1" ] || [ -z "$2" ] + then echo ; return 1 ; fi + local schedHour="$1" schedMins="$2" schedInfoStr + local freqHourNum freqMinsNum hasFreqHour hasFreqMins + + _IsValidNumber_() + { + if echo "$1" | grep -qE "^[0-9]+$" + then return 0 ; else return 1 ; fi + } + + _Get12HourAmPm_() + { + if [ $# -eq 0 ] || [ -z "$1" ] + then echo ; return 1 ; fi + local theHour theMins="" ampmTag="AM" + theHour="$1" + if [ $# -eq 2 ] && [ -n "$2" ] + then theMins="$2" + fi + if [ "$theHour" -eq 0 ] + then theHour=12 + elif [ "$theHour" -eq 12 ] + then ampmTag="PM" + elif [ "$theHour" -gt 12 ] + then + ampmTag="PM" ; theHour="$((theHour - 12))" + fi + if [ -z "$theMins" ] + then printf "%d $ampmTag" "$theHour" + else printf "%d:%02d $ampmTag" "$theHour" "$theMins" + fi + } + + if echo "$schedHour" | grep -qE "^[*]/.*" + then + hasFreqHour=true + freqHourNum="$(echo "$schedHour" | cut -f2 -d'/')" + else + hasFreqHour=false ; freqHourNum="" + fi + if echo "$schedMins" | grep -qE "^[*]/.*" + then + hasFreqMins=true + freqMinsNum="$(echo "$schedMins" | cut -f2 -d'/')" + else + hasFreqMins=false ; freqMinsNum="" + fi + if [ "$schedHour" = "*" ] && [ "$schedMins" = "0" ] + then + schedInfoStr="Every hour" + elif [ "$schedHour" = "*" ] && [ "$schedMins" = "*" ] + then + schedInfoStr="Every minute" + elif [ "$schedHour" = "*" ] && _IsValidNumber_ "$schedMins" + then + schedInfoStr="Every hour at minute $schedMins" + elif "$hasFreqHour" && [ "$schedMins" = "0" ] + then + schedInfoStr="Every $freqHourNum hours" + elif "$hasFreqHour" && [ "$schedMins" = "*" ] + then + schedInfoStr="Every minute, every $freqHourNum hours" + elif "$hasFreqHour" && _IsValidNumber_ "$schedMins" + then + schedInfoStr="Every $freqHourNum hours at minute $schedMins" + elif "$hasFreqMins" && [ "$schedHour" = "*" ] + then + schedInfoStr="Every $freqMinsNum minutes" + elif "$hasFreqHour" && "$hasFreqMins" + then + schedInfoStr="Every $freqMinsNum minutes, every $freqHourNum hours" + elif "$hasFreqMins" && _IsValidNumber_ "$schedHour" + then + schedInfoStr="Hour: $(_Get12HourAmPm_ "$schedHour"), every $freqMinsNum minutes" + elif _IsValidNumber_ "$schedHour" && _IsValidNumber_ "$schedMins" + then + schedInfoStr="Hour: $(_Get12HourAmPm_ "$schedHour" "$schedMins")" + elif "$hasFreqHour" + then + schedInfoStr="Every $freqHourNum hours, Minutes: $schedMins" + elif "$hasFreqMins" + then + schedInfoStr="Hours: ${schedHour}; every $freqMinsNum minutes" + elif [ "$schedHour" = "*" ] + then + schedInfoStr="Every hour, Minutes: $schedMins" + elif [ "$schedMins" = "*" ] + then + schedInfoStr="Hours: ${schedHour}; every minute" + else + schedInfoStr="Hours: ${schedHour}; Minutes: $schedMins" + fi + echo "$schedInfoStr" +} - AUTOMATIC_ENABLED="" - if AutomaticMode check; then AUTOMATIC_ENABLED="${PASS}Enabled"; else AUTOMATIC_ENABLED="${ERR}Disabled"; fi - TEST_SCHEDULE="$(TestSchedule check)" +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +MainMenu() +{ + local menuOption STORAGE_MenuStr automaticModeStatus - if [ "$(echo "$TEST_SCHEDULE" | cut -f2 -d'|' | grep -c "/")" -gt 0 ] && [ "$(echo "$TEST_SCHEDULE" | cut -f3 -d'|')" -eq 0 ]; then - TEST_SCHEDULE_MENU="Every $(echo "$TEST_SCHEDULE" | cut -f2 -d'|' | cut -f2 -d'/') hours" - elif [ "$(echo "$TEST_SCHEDULE" | cut -f3 -d'|' | grep -c "/")" -gt 0 ] && [ "$(echo "$TEST_SCHEDULE" | cut -f2 -d'|')" = "*" ]; then - TEST_SCHEDULE_MENU="Every $(echo "$TEST_SCHEDULE" | cut -f3 -d'|' | cut -f2 -d'/') minutes" - else - TEST_SCHEDULE_MENU="Hours: $(echo "$TEST_SCHEDULE" | cut -f2 -d'|') - Minutes: $(echo "$TEST_SCHEDULE" | cut -f3 -d'|')" + EXCLUDEFROMQOS_MENU="" + if [ "$(ExcludeFromQoS check)" = "true" ] + then EXCLUDEFROMQOS_MENU="excluded from" + else EXCLUDEFROMQOS_MENU="included in" fi - if [ "$(echo "$TEST_SCHEDULE" | cut -f1 -d'|')" = "*" ]; then - TEST_SCHEDULE_MENU2="Days of week: All" - else - TEST_SCHEDULE_MENU2="Days of week: $(echo "$TEST_SCHEDULE" | cut -f1 -d'|')" - fi - - printf "WebUI for %s is available at:\\n${SETTING}%s${CLEARFORMAT}\\n\\n" "$SCRIPT_NAME" "$(Get_WebUI_URL)" - printf "1. Check connection now\\n\\n" - printf "2. Set preferred ping server\\n Currently: ${SETTING}%s${CLEARFORMAT}\\n\\n" "$(PingServer check)" - printf "3. Set ping test duration\\n Currently: ${SETTING}%ss${CLEARFORMAT}\\n\\n" "$(PingDuration check)" - printf "4. Toggle automatic ping tests\\n Currently: ${BOLD}$AUTOMATIC_ENABLED${CLEARFORMAT}\\n\\n" - printf "5. Set schedule for automatic ping tests\\n ${SETTING}%s\\n %s${CLEARFORMAT}\\n\\n" "$TEST_SCHEDULE_MENU" "$TEST_SCHEDULE_MENU2" - printf "6. Toggle time output mode\\n Currently ${SETTING}%s${CLEARFORMAT} time values will be used for CSV exports\\n\\n" "$(OutputTimeMode check)" - printf "7. Set number of ping test results to show in WebUI\\n Currently: ${SETTING}%s results will be shown${CLEARFORMAT}\\n\\n" "$(LastXResults check)" - printf "8. Set number of days data to keep in database\\n Currently: ${SETTING}%s days data will be kept${CLEARFORMAT}\\n\\n" "$(DaysToKeep check)" - printf "s. Toggle storage location for stats and config\\n Current location is ${SETTING}%s${CLEARFORMAT} \\n\\n" "$(ScriptStorageLocation check)" - printf "q. Toggle exclusion of %s ping tests from QoS\\n Currently %s ping tests are ${SETTING}%s\\e[0m QoS\\n\\n" "$SCRIPT_NAME" "$SCRIPT_NAME" "$EXCLUDEFROMQOS_MENU" - printf "n. Configure notifications and integrations for %s\\n\\n" "$SCRIPT_NAME" - printf "u. Check for updates\\n" - printf "uf. Update %s with latest version (force update)\\n\\n" "$SCRIPT_NAME" - printf "cl. View changelog for %s (use q to exit)\\n\\n" "$SCRIPT_NAME" - printf "r. Reset %s database / delete all data\\n\\n" "$SCRIPT_NAME" - printf "e. Exit %s\\n\\n" "$SCRIPT_NAME" - printf "z. Uninstall %s\\n" "$SCRIPT_NAME" - printf "\\n" + if AutomaticMode check + then automaticModeStatus="${GRNct}ENABLED${CLEARct}" + else automaticModeStatus="${CRIT} DISABLED ${CLEARct}" + fi + + TEST_SCHEDULE="$(CronTestSchedule check)" + CRON_SCHED_DAYS="$(echo "$TEST_SCHEDULE" | cut -f1 -d'|')" + CRON_SCHED_HOUR="$(echo "$TEST_SCHEDULE" | cut -f2 -d'|')" + CRON_SCHED_MINS="$(echo "$TEST_SCHEDULE" | cut -f3 -d'|')" + if [ "$CRON_SCHED_DAYS" = "*" ] + then TEST_SCHEDULE_DAYS="Every day" + else TEST_SCHEDULE_DAYS="Days of Week: $CRON_SCHED_DAYS" + fi + TEST_SCHEDULE_MENU="$(_CronScheduleHourMinsInfo_ "$CRON_SCHED_HOUR" "$CRON_SCHED_MINS")" + + STORAGE_MenuStr="$(echo "$(ScriptStorageLocation check)" | tr 'a-z' 'A-Z')" + + printf "WebUI for %s is available at:\n${SETTING}%s${CLEARFORMAT}\n\n" "$SCRIPT_NAME" "$(Get_WebUI_URL)" + printf "1. Check connection now\n" + printf " Database size: ${SETTING}%s${CLEARFORMAT}\n\n" "$(_GetFileSize_ "$CONNSTATS_DB" HRx)" + printf "2. Set preferred ping server\n" + printf " Currently: ${SETTING}%s${CLEARFORMAT}\n\n" "$(PingServer check)" + printf "3. Set ping test duration\n" + printf " Currently: ${SETTING}%s sec.${CLEARFORMAT}\n\n" "$(PingDuration check)" + printf "4. Toggle automatic ping tests\n" + printf " Currently: ${automaticModeStatus}${CLEARFORMAT}\n\n" + printf "5. Set schedule for automatic ping tests\n" + printf " Currently: ${SETTING}%s - %s${CLEARFORMAT}\n\n" "$TEST_SCHEDULE_MENU" "$TEST_SCHEDULE_DAYS" + printf "6. Toggle time output mode\n" + printf " Currently: ${SETTING}%s${CLEARFORMAT} time values will be used for CSV exports\n\n" "$(OutputTimeMode check)" + printf "7. Set number of ping test results to show in WebUI\n" + printf " Currently: ${SETTING}%s results will be shown${CLEARFORMAT}\n\n" "$(LastXResults check)" + printf "8. Set number of days data to keep in database\n" + printf " Currently: ${SETTING}%s days data will be kept${CLEARFORMAT}\n\n" "$(DaysToKeep check)" + printf "s. Toggle storage location for stats and config\n" + printf " Current location: ${SETTING}%s${CLEARFORMAT}\n" "$STORAGE_MenuStr" + printf " JFFS Available: ${SETTING}%s${CLEARFORMAT}\n\n" "$(_Get_JFFS_Space_ FREE HRx)" + printf "q. Toggle exclusion of %s ping tests from QoS\n" "$SCRIPT_NAME" + printf " Currently: %s ping tests are ${SETTING}%s${CLEARFORMAT} QoS\n\n" "$SCRIPT_NAME" "$EXCLUDEFROMQOS_MENU" + printf "n. Configure notifications and integrations for %s\n\n" "$SCRIPT_NAME" + printf "u. Check for updates\n" + printf "uf. Update %s with latest version (force update)\n\n" "$SCRIPT_NAME" + printf "cl. View changelog for %s (use q to exit)\n\n" "$SCRIPT_NAME" + printf "r. Reset %s database / delete all data\n\n" "$SCRIPT_NAME" + printf "e. Exit %s\n\n" "$SCRIPT_NAME" + printf "z. Uninstall %s\n" "$SCRIPT_NAME" + printf "\n" printf "${BOLD}##############################################################${CLEARFORMAT}\\n" - printf "\\n" + printf "\n" - while true; do + while true + do printf "Choose an option: " - read -r menu - case "$menu" in + read -r menuOption + case "$menuOption" in 1) - printf "\\n" - if Check_Lock menu; then + printf "\n" + if Check_Lock menu + then Run_PingTest Clear_Lock fi @@ -3043,34 +3908,36 @@ MainMenu(){ break ;; 2) - printf "\\n" + printf "\n" PingServer update - PressEnter break ;; 3) - printf "\\n" - PingDuration update - PressEnter + printf "\n" + PingDuration update && PressEnter break ;; 4) - printf "\\n" - if AutomaticMode check; then - AutomaticMode disable - else - AutomaticMode enable + printf "\n" + if Check_Lock menu + then + if AutomaticMode check + then AutomaticMode disable + else AutomaticMode enable + fi + Clear_Lock + PressEnter fi break ;; 5) - printf "\\n" + printf "\n" Menu_EditSchedule PressEnter break ;; 6) - printf "\\n" + printf "\n" if [ "$(OutputTimeMode check)" = "unix" ]; then OutputTimeMode non-unix elif [ "$(OutputTimeMode check)" = "non-unix" ]; then @@ -3079,30 +3946,39 @@ MainMenu(){ break ;; 7) - printf "\\n" - LastXResults update - PressEnter + printf "\n" + LastXResults update && PressEnter break ;; 8) - printf "\\n" - DaysToKeep update - PressEnter + printf "\n" + DaysToKeep update && PressEnter break ;; s) - printf "\\n" - if [ "$(ScriptStorageLocation check)" = "jffs" ]; then - ScriptStorageLocation usb - Create_Symlinks - elif [ "$(ScriptStorageLocation check)" = "usb" ]; then - ScriptStorageLocation jffs + printf "\n" + if Check_Lock menu + then + if [ "$(ScriptStorageLocation check)" = "jffs" ] + then + ScriptStorageLocation usb + elif [ "$(ScriptStorageLocation check)" = "usb" ] + then + if ! _Check_JFFS_SpaceAvailable_ "$SCRIPT_STORAGE_DIR" + then + Clear_Lock + PressEnter + break + fi + ScriptStorageLocation jffs + fi Create_Symlinks + Clear_Lock fi break ;; q) - printf "\\n" + printf "\n" if [ "$(ExcludeFromQoS check)" = "true" ]; then ExcludeFromQoS disable elif [ "$(ExcludeFromQoS check)" = "false" ]; then @@ -3111,7 +3987,7 @@ MainMenu(){ break ;; n) - printf "\\n" + printf "\n" Menu_Notifications break ;; @@ -3167,7 +4043,11 @@ MainMenu(){ done ;; *) - printf "\\n${BOLD}${ERR}Please choose a valid option${CLEARFORMAT}\\n\\n" + [ -n "$menuOption" ] && \ + printf "\n${REDct}INVALID input [$menuOption]${CLEARFORMAT}" + printf "\nPlease choose a valid option.\n\n" + PressEnter + break ;; esac done @@ -3176,7 +4056,8 @@ MainMenu(){ MainMenu } -Check_Requirements(){ +Check_Requirements() +{ CHECKSFAILED="false" if [ "$(nvram get jffs2_scripts)" -ne 1 ]; then @@ -3186,7 +4067,7 @@ Check_Requirements(){ fi if [ ! -f /opt/bin/opkg ]; then - Print_Output true "Entware not detected!" "$ERR" + Print_Output true "Entware not detected!" "$CRIT" CHECKSFAILED="true" fi @@ -3196,7 +4077,8 @@ Check_Requirements(){ CHECKSFAILED="true" fi - if [ "$CHECKSFAILED" = "false" ]; then + if [ "$CHECKSFAILED" = "false" ] + then Print_Output true "Installing required packages from Entware" "$PASS" opkg update opkg install sqlite3-cli @@ -3208,14 +4090,19 @@ Check_Requirements(){ fi } -Menu_Install(){ +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Menu_Install() +{ ScriptHeader - Print_Output true "Welcome to $SCRIPT_NAME $SCRIPT_VERSION, a script by JackYaz" + Print_Output true "Welcome to $SCRIPT_NAME $SCRIPT_VERSION, a script by JackYaz" "$PASS" sleep 1 - Print_Output true "Checking your router meets the requirements for $SCRIPT_NAME" + Print_Output true "Checking if your router meets the requirements for $SCRIPT_NAME" "$PASS" - if ! Check_Requirements; then + if ! Check_Requirements + then Print_Output true "Requirements for $SCRIPT_NAME not met, please see above for the reason(s)" "$CRIT" PressEnter Clear_Lock @@ -3227,7 +4114,7 @@ Menu_Install(){ Conf_Exists Set_Version_Custom_Settings local "$SCRIPT_VERSION" Set_Version_Custom_Settings server "$SCRIPT_VERSION" - ScriptStorageLocation load + ScriptStorageLocation load true Create_Symlinks Update_File CHANGELOG.md @@ -3236,13 +4123,19 @@ Menu_Install(){ Update_File shared-jy.tar.gz Auto_Startup create 2>/dev/null - if AutomaticMode check; then Auto_Cron create 2>/dev/null; else Auto_Cron delete 2>/dev/null; fi + Auto_Cron delete 2>/dev/null + AutomaticMode check && Auto_Cron create 2>/dev/null Auto_ServiceEvent create 2>/dev/null Shortcut_Script create - echo "CREATE TABLE IF NOT EXISTS [connstats] ([StatID] INTEGER PRIMARY KEY NOT NULL,[Timestamp] NUMERIC NOT NULL,[Ping] REAL NOT NULL,[Jitter] REAL NOT NULL,[LineQuality] REAL NOT NULL,[PingTarget] TEXT NOT NULL,[PingDuration] NUMERIC);" > /tmp/connmon-stats.sql - "$SQLITE3_PATH" "$SCRIPT_STORAGE_DIR/connstats.db" < /tmp/connmon-stats.sql + { + echo "PRAGMA journal_mode=WAL;" + echo "PRAGMA temp_store=1;" + echo "CREATE TABLE IF NOT EXISTS [connstats] ([StatID] INTEGER PRIMARY KEY NOT NULL,[Timestamp] NUMERIC NOT NULL,[Ping] REAL NOT NULL,[Jitter] REAL NOT NULL,[LineQuality] REAL NOT NULL,[PingTarget] TEXT NOT NULL,[PingDuration] NUMERIC);" + } > /tmp/connmon-stats.sql + _ApplyDatabaseSQLCmds_ /tmp/connmon-stats.sql rm -f /tmp/connmon-stats.sql + touch "$SCRIPT_STORAGE_DIR/.newcolumns" touch "$SCRIPT_STORAGE_DIR/lastx.csv" Process_Upgrade @@ -3257,23 +4150,27 @@ Menu_Install(){ MainMenu } +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## Menu_Startup() { if [ $# -eq 0 ] || [ -z "$1" ] then - Print_Output true "Missing argument for startup, not starting $SCRIPT_NAME" "$WARN" + Print_Output true "Missing argument for startup, not starting $SCRIPT_NAME" "$ERR" exit 1 - elif [ "$1" != "force" ]; then - if [ ! -f "$1/entware/bin/opkg" ]; then - Print_Output true "$1 does not contain Entware, not starting $SCRIPT_NAME" "$WARN" + elif [ "$1" != "force" ] + then + if [ ! -x "${1}/entware/bin/opkg" ] + then + Print_Output true "$1 does NOT contain Entware, not starting $SCRIPT_NAME" "$CRIT" exit 1 else - Print_Output true "$1 contains Entware, starting $SCRIPT_NAME" "$WARN" + Print_Output true "$1 contains Entware, starting $SCRIPT_NAME" "$PASS" fi fi NTP_Ready - Check_Lock if [ "$1" != "force" ]; then @@ -3282,349 +4179,608 @@ Menu_Startup() Create_Dirs Conf_Exists - ScriptStorageLocation load + ScriptStorageLocation load true Create_Symlinks Auto_Startup create 2>/dev/null - if AutomaticMode check; then Auto_Cron create 2>/dev/null; else Auto_Cron delete 2>/dev/null; fi + if AutomaticMode check + then Auto_Cron create 2>/dev/null + else Auto_Cron delete 2>/dev/null + fi Auto_ServiceEvent create 2>/dev/null Shortcut_Script create Mount_WebUI - Clear_Lock } -Menu_EditSchedule(){ - exitmenu="" - formattype="" - crudays="" - crudaysvalidated="" - cruhours="" - crumins="" +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ValidateCronDAYSofWEEK_() +{ + if [ $# -eq 0 ] || [ -z "$1" ] ; then return 1 ; fi + + local cruDaysOK cruDaysTmp1 cruDaysTmp2 tmpDay1 tmpDay2 + + [ "$1" = "*" ] && return 0 + + _DayOfWeekNameToDayNum_() + { echo "$1" | sed 's/Sun/0/;s/Mon/1/;s/Tues/2/;s/Wed/3/;s/Thurs/4/;s/Fri/5/;s/Sat/6/;s/Tue/2/;s/Thu/4/;' ; } + + cruDaysOK=true + cruDaysTmp1="$(_DayOfWeekNameToDayNum_ "$1")" + cruDaysTmp1="$(echo "$cruDaysTmp1" | sed 's/,/ /g')" + + for tmpDay1 in $cruDaysTmp1 + do + if echo "$tmpDay1" | grep -q '-' + then + if [ "$tmpDay1" = "-" ] + then + cruDaysOK=false + printf "\n${ERR}Please enter a valid number between 0 and 6${CLEARFORMAT}\n" + break + fi + cruDaysTmp2="$(echo "$tmpDay1" | sed 's/-/ /')" + for tmpDay2 in $cruDaysTmp2 + do + if ! echo "$tmpDay2" | grep -qE "^[0-6]$" || \ + [ "$tmpDay2" -lt 0 ] || [ "$tmpDay2" -gt 6 ] + then + cruDaysOK=false + printf "\n${ERR}Please enter valid numbers between 0 and 6${CLEARFORMAT}\n" + break + fi + done + "$cruDaysOK" && continue || break + elif ! echo "$tmpDay1" | grep -qE "^[0-6]$" || \ + [ "$tmpDay1" -lt 0 ] || [ "$tmpDay1" -gt 6 ] + then + cruDaysOK=false + printf "\n${ERR}Please enter a valid number between 0 and 6, or comma-separated numbers${CLEARFORMAT}\n" + break + fi + done + + "$cruDaysOK" && return 0 || return 1 +} - while true; do - printf "\\n${BOLD}Please choose which day(s) to run ping test\\n(0-6 - 0 = Sunday, * for every day, or comma separated days):${CLEARFORMAT} " +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ValidateCronFreqHOURS_() +{ + local cruHoursOK=true isVerbose=true + + if [ $# -eq 0 ] || [ -z "$1" ] + then return 1 + fi + if [ $# -gt 1 ] && [ "$2" = "-quiet" ] + then isVerbose=false + fi + if ! echo "$1" | grep -qE "^[1-9][0-9]?$" || \ + [ "$1" -lt 1 ] || [ "$1" -gt 24 ] + then + cruHoursOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 1 and 24${CLEARFORMAT}\n" + fi + "$cruHoursOK" && return 0 || return 1 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ValidateCronFreqMINS_() +{ + local cruMinsOK=true isVerbose=true + + if [ $# -eq 0 ] || [ -z "$1" ] + then return 1 + fi + if [ $# -gt 1 ] && [ "$2" = "-quiet" ] + then isVerbose=false + fi + if ! echo "$1" | grep -qE "^[1-9][0-9]?$" || \ + [ "$1" -lt 1 ] || [ "$1" -gt 30 ] + then + cruMinsOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 1 and 30${CLEARFORMAT}\n" + fi + "$cruMinsOK" && return 0 || return 1 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ValidateCronHOURS_() +{ + local cruHoursOK cruHoursTmp1 cruHoursTmp2 cruHoursTmp3 + local tmpHour1 tmpHour2 isVerbose=true + + if [ $# -eq 0 ] || [ -z "$1" ] + then return 1 + fi + if [ $# -gt 1 ] && [ "$2" = "-quiet" ] + then isVerbose=false + fi + [ "$1" = "*" ] && return 0 + + cruHoursOK=true + cruHoursTmp1="$(echo "$1" | sed 's/,/ /g')" + + for tmpHour1 in $cruHoursTmp1 + do + if echo "$tmpHour1" | grep -q "-" + then + if [ "$tmpHour1" = "-" ] + then + cruHoursOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 0 and 23${CLEARFORMAT}\n" + break + fi + cruHoursTmp2="$(echo "$tmpHour1" | sed 's/-/ /')" + for tmpHour2 in $cruHoursTmp2 + do + if ! echo "$tmpHour2" | grep -qE "^(0|[1-9][0-9]?)$" || \ + [ "$tmpHour2" -lt 0 ] || [ "$tmpHour2" -gt 23 ] + then + cruHoursOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter valid numbers between 0 and 23${CLEARFORMAT}\n" + break + fi + done + "$cruHoursOK" && continue || break + elif echo "$tmpHour1" | grep -q "[*]/.*" + then + cruHoursTmp3="$(echo "$tmpHour1" | sed 's/\*\///')" + if ! echo "$cruHoursTmp3" | grep -qE "^[1-9][0-9]?$" || \ + [ "$cruHoursTmp3" -lt 2 ] || [ "$cruHoursTmp3" -gt 23 ] + then + cruHoursOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid frequency number between 2 and 23${CLEARFORMAT}\n" + break + fi + elif ! echo "$tmpHour1" | grep -qE "^(0|[1-9][0-9]?)$" || \ + [ "$tmpHour1" -lt 0 ] || [ "$tmpHour1" -gt 23 ] + then + cruHoursOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 0 and 23, or comma-separated numbers${CLEARFORMAT}\n" + break + fi + done + + "$cruHoursOK" && return 0 || return 1 +} + +##-------------------------------------## +## Added by Martinski W. [2024-Dec-21] ## +##-------------------------------------## +_ValidateCronMINS_() +{ + local cruMinsOK cruMinsTmp1 cruMinsTmp2 cruMinsTmp3 + local tmpMins1 tmpMins2 isVerbose=true + + if [ $# -eq 0 ] || [ -z "$1" ] + then return 1 + fi + if [ $# -gt 1 ] && [ "$2" = "-quiet" ] + then isVerbose=false + fi + [ "$1" = "*" ] && return 0 + + cruMinsOK=true + cruMinsTmp1="$(echo "$1" | sed 's/,/ /g')" + + for tmpMins1 in $cruMinsTmp1 + do + if echo "$tmpMins1" | grep -q "-" + then + if [ "$tmpMins1" = "-" ] + then + cruMinsOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 0 and 59${CLEARFORMAT}\n" + break + fi + cruMinsTmp2="$(echo "$tmpMins1" | sed 's/-/ /')" + for tmpMins2 in $cruMinsTmp2 + do + if ! echo "$tmpMins2" | grep -qE "^(0|[1-9][0-9]?)$" || \ + [ "$tmpMins2" -lt 0 ] || [ "$tmpMins2" -gt 59 ] + then + cruMinsOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter valid numbers between 0 and 59${CLEARFORMAT}\n" + break + fi + done + "$cruMinsOK" && continue || break + elif echo "$tmpMins1" | grep -q "[*]/.*" + then + cruMinsTmp3="$(echo "$tmpMins1" | sed 's/\*\///')" + if ! echo "$cruMinsTmp3" | grep -qE "^[1-9][0-9]?$" || \ + [ "$cruMinsTmp3" -lt 2 ] || [ "$cruMinsTmp3" -gt 30 ] + then + cruMinsOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid frequency number between 2 and 30${CLEARFORMAT}\n" + break + fi + elif ! echo "$tmpMins1" | grep -qE "^(0|[1-9][0-9]?)$" || \ + [ "$tmpMins1" -lt 0 ] || [ "$tmpMins1" -gt 59 ] + then + cruMinsOK=false + "$isVerbose" && \ + printf "\n${ERR}Please enter a valid number between 0 and 59, or comma-separated numbers${CLEARFORMAT}\n" + break + fi + done + + "$cruMinsOK" && return 0 || return 1 +} + +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-22] ## +##----------------------------------------## +Menu_EditSchedule() +{ + local exitMenu testScheduleStr + local cruDays cruHour cruMins formatType + local cruHoursStr cruHoursTmp cruMinsStr cruMinsTmp + + _DayOfWeekNumToDayName_() + { echo "$1" | sed 's/0/Sun/;s/1/Mon/;s/2/Tue/;s/3/Wed/;s/4/Thu/;s/5/Fri/;s/6/Sat/;' ; } + + _GetSchedDaysHR_() + { + local cruSchedDays="$1" + if [ "$1" = "*" ] + then cruSchedDays="Every day" + elif ! echo "$1" | grep -qE "^[*]/.*" + then cruSchedDays="$(_DayOfWeekNumToDayName_ "$1")" + fi + echo "$cruSchedDays" + } + + _GetScheduleHR_() + { echo "$(_CronScheduleHourMinsInfo_ "$1" "$2") - $(_GetSchedDaysHR_ "$3")" ; } + + _ValidateHoursRange_() + { + local cruHour1st cruHour2nd cruHourTmp + cruHour1st="$(echo "$1" | cut -f1 -d'-')" + cruHour2nd="$(echo "$1" | cut -f2 -d'-')" + if [ "$cruHour1st" -eq "$cruHour2nd" ] + then cruHourTmp="$cruHour1st" + elif [ "$cruHour1st" -lt "$cruHour2nd" ] + then cruHourTmp="$1" + elif [ "$cruHour1st" -gt "$cruHour2nd" ] + then cruHourTmp="0-${cruHour2nd},${cruHour1st}-23" + fi + echo "$cruHourTmp" + } + + _ValidateMinsRange_() + { + local cruMins1st cruMins2nd cruMinsTmp + cruMins1st="$(echo "$1" | cut -f1 -d'-')" + cruMins2nd="$(echo "$1" | cut -f2 -d'-')" + if [ "$cruMins1st" -eq "$cruMins2nd" ] + then cruMinsTmp="$cruMins1st" + elif [ "$cruMins1st" -lt "$cruMins2nd" ] + then cruMinsTmp="$1" + elif [ "$cruMins1st" -gt "$cruMins2nd" ] + then cruMinsTmp="0-${cruMins2nd},${cruMins1st}-59" + fi + echo "$cruMinsTmp" + } + + testScheduleStr="$(CronTestSchedule check)" + cruDays="$(echo "$testScheduleStr" | cut -f1 -d'|')" + cruHour="$(echo "$testScheduleStr" | cut -f2 -d'|')" + cruMins="$(echo "$testScheduleStr" | cut -f3 -d'|')" + exitMenu=false ; formatType="" + + ## DAYS of the WEEK ## + while true + do + ScriptHeader + printf "${BOLD}Current schedule: ${GRNct}$(_GetScheduleHR_ "$cruHour" "$cruMins" "$cruDays")${CLEARct}\n" + printf "\n${BOLD}Please enter the DAYS of the week when to run the ping tests.\n" + printf "[${GRNct}0-6${CLEARct}], ${GRNct}0${CLEARct}=Sunday, ${GRNct}6${CLEARct}=Saturday, ${GRNct}*${CLEARct}=Every day, or comma-separated days.${CLEARFORMAT}" + printf "\n\n${BOLD}Enter DAYS of the week (${GRNct}e${CLEARct}=Exit)${CLEARFORMAT}: " read -r day_choice - if [ "$day_choice" = "e" ]; then - exitmenu="exit" - break - elif [ "$day_choice" = "*" ]; then - crudays="$day_choice" - printf "\\n" - break - elif [ -z "$day_choice" ]; then - printf "\\n${ERR}Please enter a valid number (0-6) or comma separated values${CLEARFORMAT}\\n" + if [ "$day_choice" = "e" ] + then + exitMenu=true ; break + elif [ -z "$day_choice" ] + then + if _ValidateCronDAYSofWEEK_ "$cruDays" + then echo ; break ; fi + PressEnter else - crudaystmp="$(echo "$day_choice" | sed "s/,/ /g")" - crudaysvalidated="true" - for i in $crudaystmp; do - if echo "$i" | grep -q "-"; then - if [ "$i" = "-" ]; then - printf "\\n${ERR}Please enter a valid number (0-6)${CLEARFORMAT}\\n" - crudaysvalidated="false" - break - fi - crudaystmp2="$(echo "$i" | sed "s/-/ /")" - for i2 in $crudaystmp2; do - if ! Validate_Number "$i2"; then - printf "\\n${ERR}Please enter a valid number (0-6)${CLEARFORMAT}\\n" - crudaysvalidated="false" - break - elif [ "$i2" -lt 0 ] || [ "$i2" -gt 6 ]; then - printf "\\n${ERR}Please enter a number between 0 and 6${CLEARFORMAT}\\n" - crudaysvalidated="false" - break - fi - done - elif ! Validate_Number "$i"; then - printf "\\n${ERR}Please enter a valid number (0-6) or comma separated values${CLEARFORMAT}\\n" - crudaysvalidated="false" - break - elif [ "$i" -lt 0 ] || [ "$i" -gt 6 ]; then - printf "\\n${ERR}Please enter a number between 0 and 6 or comma separated values${CLEARFORMAT}\\n" - crudaysvalidated="false" - break - fi - done - if [ "$crudaysvalidated" = "true" ]; then - crudays="$day_choice" - printf "\\n" - break - fi + if _ValidateCronDAYSofWEEK_ "$day_choice" + then cruDays="$day_choice" ; echo ; break ; fi + PressEnter fi done - if [ "$exitmenu" != "exit" ]; then - while true; do - printf "\\n${BOLD}Please choose the format to specify the hour/minute(s)\\nto run ping test:${CLEARFORMAT}\\n" - printf " 1. Every X hours/minutes\\n" - printf " 2. Custom\\n\\n" + ## FORMAT: "Custom" or "EveryX" ## + if [ "$exitMenu" = "false" ] + then + while true + do + ScriptHeader + printf "${BOLD}Please choose the method to specify the hour/minute(s)\nto run the ping tests:${CLEARFORMAT}\n\n" + printf " 1. Every X hours/minutes\n" + printf " 2. Custom\n" + printf " e. Exit to Main Menu\n\n" printf "Choose an option: " - read -r formatmenu - - case "$formatmenu" in - 1) - formattype="everyx" - printf "\\n" - break - ;; - 2) - formattype="custom" - printf "\\n" - break - ;; - e) - exitmenu="exit" - break - ;; - *) - printf "\\n${ERR}Please enter a valid choice (1-2)${CLEARFORMAT}\\n" - ;; + read -r formatChoice + + case "$formatChoice" in + 1) formatType="everyx" ; echo ; break ;; + 2) formatType="custom" ; echo ; break ;; + e) exitMenu=true ; break ;; + *) printf "\n${ERR}Please enter a valid choice [1-2]${CLEARFORMAT}\n" + PressEnter ;; esac done fi - if [ "$exitmenu" != "exit" ]; then - if [ "$formattype" = "everyx" ]; then - while true; do - printf "\\n${BOLD}Please choose whether to specify every X hours or every X minutes\\nto run ping test:${CLEARFORMAT}\\n" - printf " 1. Hours\\n" - printf " 2. Minutes\\n\\n" + if [ "$exitMenu" = "false" ] + then + if [ "$formatType" = "everyx" ] + then + while true + do + ScriptHeader + printf "${BOLD}Please choose whether to specify every X hours or every X minutes\nto run the ping tests:${CLEARFORMAT}\n\n" + printf " 1. Hours\n" + printf " 2. Minutes\n" + printf " e. Exit to Main Menu\n\n" printf "Choose an option: " - read -r formatmenu - - case "$formatmenu" in - 1) - formattype="hours" - printf "\\n" - break - ;; - 2) - formattype="mins" - printf "\\n" - break - ;; - e) - exitmenu="exit" - break - ;; - *) - printf "\\n${ERR}Please enter a valid choice (1-2)${CLEARFORMAT}\\n" - ;; + read -r formatChoice + + case "$formatChoice" in + 1) formatType="hours" ; echo ; break ;; + 2) formatType="mins" ; echo ; break ;; + e) exitMenu=true ; break ;; + *) printf "\n${ERR}Please enter a valid choice [1-2]${CLEARFORMAT}\n" + PressEnter ;; esac done fi fi - if [ "$exitmenu" != "exit" ]; then - if [ "$formattype" = "hours" ]; then - while true; do - printf "\\n${BOLD}Please choose how often to run ping test\\n(every X hours, where X is 1-24):${CLEARFORMAT} " + if [ "$exitMenu" = "false" ] + then + ## EVERY X HOURS ## + if [ "$formatType" = "hours" ] + then + while true + do + ScriptHeader + printf "${BOLD}Current schedule: ${GRNct}$(_GetScheduleHR_ "$cruHour" "$cruMins" "$cruDays")${CLEARct}\n" + printf "\n${BOLD}Please enter how often in HOURS to run the ping tests.\n" + printf "Every X hours, where X is ${GRNct}1-24${CLEARct}, (${GRNct}e${CLEARct}=Exit)${CLEARFORMAT}: " read -r hour_choice - if [ "$hour_choice" = "e" ]; then - exitmenu="exit" - break - elif ! Validate_Number "$hour_choice"; then - printf "\\n${ERR}Please enter a valid number (1-24)${CLEARFORMAT}\\n" - elif [ "$hour_choice" -lt 1 ] || [ "$hour_choice" -gt 24 ]; then - printf "\\n${ERR}Please enter a number between 1 and 24${CLEARFORMAT}\\n" - elif [ "$hour_choice" -eq 24 ]; then - cruhours=0 - crumins=0 - printf "\\n" - break + if [ "$hour_choice" = "e" ] + then + exitMenu=true ; break + elif [ -z "$hour_choice" ] + then + if _ValidateCronHOURS_ "$cruHour" -quiet || \ + _ValidateCronFreqHOURS_ "$cruHour" -quiet + then echo ; break ; fi + printf "\n${ERR}Please enter a number between 1 and 24${CLEARFORMAT}\n" + PressEnter + elif ! _ValidateCronFreqHOURS_ "$hour_choice" + then + PressEnter + elif [ "$hour_choice" -eq 24 ] + then + cruHour=0 + cruMins=0 + echo ; break + elif [ "$hour_choice" -eq 1 ] + then + cruHour="*" + cruMins=0 + echo ; break else - cruhours="*/$hour_choice" - crumins=0 - printf "\\n" - break + cruHour="*/$hour_choice" + cruMins=0 + echo ; break fi done - elif [ "$formattype" = "mins" ]; then - while true; do - printf "\\n${BOLD}Please choose how often to run ping test\\n(every X minutes, where X is 1-30):${CLEARFORMAT} " - read -r min_choice - if [ "$min_choice" = "e" ]; then - exitmenu="exit" - break - elif ! Validate_Number "$min_choice"; then - printf "\\n${ERR}Please enter a valid number (1-30)${CLEARFORMAT}\\n" - elif [ "$min_choice" -lt 1 ] || [ "$min_choice" -gt 30 ]; then - printf "\\n${ERR}Please enter a number between 1 and 30${CLEARFORMAT}\\n" + ## EVERY X MINUTES ## + elif [ "$formatType" = "mins" ] + then + while true + do + ScriptHeader + printf "${BOLD}Current schedule: ${GRNct}$(_GetScheduleHR_ "$cruHour" "$cruMins" "$cruDays")${CLEARct}\n" + printf "\n${BOLD}Please enter how often in MINUTES to run the ping tests.\n" + printf "Every X minutes, where X is ${GRNct}1-30${CLEARct}, (${GRNct}e${CLEARct}=Exit)${CLEARFORMAT}: " + read -r mins_choice + + if [ "$mins_choice" = "e" ] + then + exitMenu=true ; break + elif [ -z "$mins_choice" ] + then + if _ValidateCronMINS_ "$cruMins" -quiet || \ + _ValidateCronFreqMINS_ "$cruMins" -quiet + then echo ; break ; fi + printf "\n${ERR}Please enter a number between 1 and 30${CLEARFORMAT}\n" + PressEnter + elif ! _ValidateCronFreqMINS_ "$mins_choice" + then + PressEnter + elif [ "$mins_choice" -eq 1 ] + then + cruMins="*" + cruHour="*" + echo ; break else - crumins="*/$min_choice" - cruhours="*" - printf "\\n" - break + cruMins="*/$mins_choice" + cruHour="*" + echo ; break fi done fi fi - if [ "$exitmenu" != "exit" ]; then - if [ "$formattype" = "custom" ]; then - while true; do - printf "\\n${BOLD}Please choose which hour(s) to run ping test\\n(0-23, * for every hour, or comma separated hours):${CLEARFORMAT} " + if [ "$exitMenu" = "false" ] + then + if [ "$formatType" = "custom" ] + then + ## CUSTOM HOURS ## + while true + do + ScriptHeader + printf "${BOLD}Current schedule: ${GRNct}$(_GetScheduleHR_ "$cruHour" "$cruMins" "$cruDays")${CLEARct}\n" + printf "\n${BOLD}Please enter the HOURS when to run the ping tests.\n" + printf "[${GRNct}0-23${CLEARct}], ${GRNct}*${CLEARct}=Every hour, or comma-separated hours, (${GRNct}e${CLEARct}=Exit)${CLEARFORMAT}: " read -r hour_choice - if [ "$hour_choice" = "e" ]; then - exitmenu="exit" - break - elif [ "$hour_choice" = "*" ]; then - cruhours="$hour_choice" - printf "\\n" - break + if [ "$hour_choice" = "e" ] + then + exitMenu=true ; break + elif [ -z "$hour_choice" ] + then + if _ValidateCronHOURS_ "$cruHour" -quiet || \ + _ValidateCronFreqHOURS_ "$cruHour" -quiet + then echo ; break ; fi + printf "\n${ERR}Please enter a number between 0 and 23${CLEARFORMAT}\n" + PressEnter else - cruhourstmp="$(echo "$hour_choice" | sed "s/,/ /g")" - cruhoursvalidated="true" - for i in $cruhourstmp; do - if echo "$i" | grep -q "-"; then - if [ "$i" = "-" ]; then - printf "\\n${ERR}Please enter a valid number (0-23)${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - fi - cruhourstmp2="$(echo "$i" | sed "s/-/ /")" - for i2 in $cruhourstmp2; do - if ! Validate_Number "$i2"; then - printf "\\n${ERR}Please enter a valid number (0-23)${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - elif [ "$i2" -lt 0 ] || [ "$i2" -gt 23 ]; then - printf "\\n${ERR}Please enter a number between 0 and 23${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - fi - done - elif echo "$i" | grep -q "/"; then - cruhourstmp3="$(echo "$i" | sed "s/\*\///")" - if ! Validate_Number "$cruhourstmp3"; then - printf "\\n${ERR}Please enter a valid number (0-23)${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - elif [ "$cruhourstmp3" -lt 0 ] || [ "$cruhourstmp3" -gt 23 ]; then - printf "\\n${ERR}Please enter a number between 0 and 23${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - fi - elif ! Validate_Number "$i"; then - printf "\\n${ERR}Please enter a valid number (0-23) or comma separated values${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - elif [ "$i" -lt 0 ] || [ "$i" -gt 23 ]; then - printf "\\n${ERR}Please enter a number between 0 and 23 or comma separated values${CLEARFORMAT}\\n" - cruhoursvalidated="false" - break - fi - done - if [ "$cruhoursvalidated" = "true" ]; then - if echo "$hour_choice" | grep -q "-"; then - cruhours1="$(echo "$hour_choice" | cut -f1 -d'-')" - cruhours2="$(echo "$hour_choice" | cut -f2 -d'-')" - if [ "$cruhours1" -lt "$cruhours2" ]; then - cruhours="$hour_choice" - elif [ "$cruhours2" -lt "$cruhours1" ]; then - cruhours="$cruhours1-23,0-$cruhours2" + if _ValidateCronHOURS_ "$hour_choice" + then + if echo "$hour_choice" | grep -q "-" + then + if echo "$hour_choice" | grep -q "," + then + cruHour="" + cruHoursStr="$(echo "$hour_choice" | sed 's/,/ /g')" + for tmpHours in $cruHoursStr + do + if echo "$tmpHours" | grep -q "-" + then + cruHoursTmp="$(_ValidateHoursRange_ "$tmpHours")" + if [ -z "$cruHour" ] + then cruHour="$cruHoursTmp" + else cruHour="${cruHour},${cruHoursTmp}" + fi + else + if [ -z "$cruHour" ] + then cruHour="$tmpHours" + else cruHour="${cruHour},${tmpHours}" + fi + fi + done + else + cruHour="$(_ValidateHoursRange_ "$hour_choice")" fi + elif [ "$hour_choice" = "*/1" ] + then + cruHour="*" else - cruhours="$hour_choice" + cruHour="$hour_choice" fi - printf "\\n" - break + echo ; break fi + PressEnter fi done fi fi - if [ "$exitmenu" != "exit" ]; then - if [ "$formattype" = "custom" ]; then - while true; do - printf "\\n${BOLD}Please choose which minutes(s) to run ping test\\n(0-59, * for every minute, or comma separated minutes):${CLEARFORMAT} " - read -r min_choice - - if [ "$min_choice" = "e" ]; then - exitmenu="exit" - break - elif [ "$min_choice" = "*" ]; then - crumins="$min_choice" - printf "\\n" - break + if [ "$exitMenu" = "false" ] + then + if [ "$formatType" = "custom" ] + then + ## CUSTOM MINUTES ## + while true + do + ScriptHeader + printf "${BOLD}Current schedule: ${GRNct}$(_GetScheduleHR_ "$cruHour" "$cruMins" "$cruDays")${CLEARct}\n" + printf "\n${BOLD}Please enter the MINUTES when to run the ping tests.\n" + printf "[${GRNct}0-59${CLEARct}], ${GRNct}*${CLEARct}=Every minute, or comma-separated minutes, (${GRNct}e${CLEARct}=Exit)${CLEARFORMAT}: " + read -r mins_choice + + if [ "$mins_choice" = "e" ] + then + exitMenu=true ; break + elif [ -z "$mins_choice" ] + then + if _ValidateCronMINS_ "$cruMins" -quiet || \ + _ValidateCronFreqMINS_ "$cruMins" -quiet + then echo ; break ; fi + printf "\n${ERR}Please enter a number between 0 and 59${CLEARFORMAT}\n" + PressEnter else - cruminstmp="$(echo "$min_choice" | sed "s/,/ /g")" - cruminsvalidated="true" - for i in $cruminstmp; do - if echo "$i" | grep -q "-"; then - if [ "$i" = "-" ]; then - printf "\\n${ERR}Please enter a valid number (0-23)${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - fi - cruminstmp2="$(echo "$i" | sed "s/-/ /")" - for i2 in $cruminstmp2; do - if ! Validate_Number "$i2"; then - printf "\\n${ERR}Please enter a valid number (0-59)${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - elif [ "$i2" -lt 0 ] || [ "$i2" -gt 59 ]; then - printf "\\n${ERR}Please enter a number between 0 and 59${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - fi - done - elif echo "$i" | grep -q "/"; then - cruminstmp3="$(echo "$i" | sed "s/\*\///")" - if ! Validate_Number "$cruminstmp3"; then - printf "\\n${ERR}Please enter a valid number (0-30)${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - elif [ "$cruminstmp3" -lt 0 ] || [ "$cruminstmp3" -gt 30 ]; then - printf "\\n${ERR}Please enter a number between 0 and 30${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - fi - elif ! Validate_Number "$i"; then - printf "\\n${ERR}Please enter a valid number (0-59) or comma separated values${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - elif [ "$i" -lt 0 ] || [ "$i" -gt 59 ]; then - printf "\\n${ERR}Please enter a number between 0 and 59 or comma separated values${CLEARFORMAT}\\n" - cruminsvalidated="false" - break - fi - done - - if [ "$cruminsvalidated" = "true" ]; then - if echo "$min_choice" | grep -q "-"; then - crumins1="$(echo "$min_choice" | cut -f1 -d'-')" - crumins2="$(echo "$min_choice" | cut -f2 -d'-')" - if [ "$crumins1" -lt "$crumins2" ]; then - crumins="$min_choice" - elif [ "$crumins2" -lt "$crumins1" ]; then - crumins="$crumins1-59,0-$crumins2" + if _ValidateCronMINS_ "$mins_choice" + then + if echo "$mins_choice" | grep -q "-" + then + if echo "$mins_choice" | grep -q "," + then + cruMins="" + cruMinsStr="$(echo "$mins_choice" | sed 's/,/ /g')" + for tmpMins in $cruMinsStr + do + if echo "$tmpMins" | grep -q "-" + then + cruMinsTmp="$(_ValidateMinsRange_ "$tmpMins")" + if [ -z "$cruMins" ] + then cruMins="$cruMinsTmp" + else cruMins="${cruMins},${cruMinsTmp}" + fi + else + if [ -z "$cruMins" ] + then cruMins="$tmpMins" + else cruMins="${cruMins},${tmpMins}" + fi + fi + done + else + cruMins="$(_ValidateMinsRange_ "$mins_choice")" fi + elif [ "$mins_choice" = "*/1" ] + then + cruMins="*" else - crumins="$min_choice" + cruMins="$mins_choice" fi - printf "\\n" - break + echo ; break fi + PressEnter fi done fi fi - if [ "$exitmenu" != "exit" ]; then - TestSchedule update "$crudays" "$cruhours" "$crumins" + if [ "$exitMenu" = "false" ] + then + CronTestSchedule update "$cruDays" "$cruHour" "$cruMins" return 0 else - return 1 + echo ; return 1 fi } -Menu_ResetDB(){ +Menu_ResetDB() +{ printf "${BOLD}\\e[33mWARNING: This will reset the %s database by deleting all database records.\\n" "$SCRIPT_NAME" printf "A backup of the database will be created if you change your mind.${CLEARFORMAT}\\n" printf "\\n${BOLD}Do you want to continue? (y/n)${CLEARFORMAT} " @@ -3640,13 +4796,24 @@ Menu_ResetDB(){ esac } -Menu_Uninstall(){ - Print_Output true "Removing $SCRIPT_NAME..." "$PASS" - if [ -n "$PPID" ]; then +##----------------------------------------## +## Modified by Martinski W. [2024-Nov-23] ## +##----------------------------------------## +Menu_Uninstall() +{ + if [ -n "$PPID" ] + then ps | grep -v grep | grep -v $$ | grep -v "$PPID" | grep -i "$SCRIPT_NAME" | grep generate | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 else ps | grep -v grep | grep -v $$ | grep -i "$SCRIPT_NAME" | grep generate | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 fi + if [ -n "$PPID" ] + then + ps | grep -v grep | grep -v $$ | grep -v "$PPID" | grep -i "$SCRIPT_NAME" | grep trimdb | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 + else + ps | grep -v grep | grep -v $$ | grep -i "$SCRIPT_NAME" | grep trimdb | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 + fi + Print_Output true "Removing $SCRIPT_NAME..." "$PASS" Auto_Startup delete 2>/dev/null Auto_Cron delete 2>/dev/null Auto_ServiceEvent delete 2>/dev/null @@ -3689,16 +4856,20 @@ Menu_Uninstall(){ Print_Output true "Uninstall completed" "$PASS" } -NTP_Ready(){ - if [ "$(nvram get ntp_ready)" -eq 0 ]; then - ntpwaitcount=0 +NTP_Ready() +{ + if [ "$(nvram get ntp_ready)" -eq 0 ] + then Check_Lock - while [ "$(nvram get ntp_ready)" -eq 0 ] && [ "$ntpwaitcount" -lt 600 ]; do + ntpwaitcount=0 + while [ "$(nvram get ntp_ready)" -eq 0 ] && [ "$ntpwaitcount" -lt 600 ] + do ntpwaitcount="$((ntpwaitcount + 30))" Print_Output true "Waiting for NTP to sync..." "$WARN" sleep 30 done - if [ "$ntpwaitcount" -ge 600 ]; then + if [ "$ntpwaitcount" -ge 600 ] + then Print_Output true "NTP failed to sync after 10 minutes. Please resolve!" "$CRIT" Clear_Lock exit 1 @@ -3710,17 +4881,30 @@ NTP_Ready(){ } ### function based on @Adamm00's Skynet USB wait function ### -Entware_Ready(){ - if [ ! -f /opt/bin/opkg ]; then +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## +Entware_Ready() +{ + local theSleepDelay=5 maxSleepTimer=100 sleepTimerSecs + + if [ ! -f /opt/bin/opkg ] + then Check_Lock - sleepcount=1 - while [ ! -f /opt/bin/opkg ] && [ "$sleepcount" -le 10 ]; do - Print_Output true "Entware not found, sleeping for 10s (attempt $sleepcount of 10)" "$ERR" - sleepcount="$((sleepcount + 1))" - sleep 10 + sleepTimerSecs=0 + + while [ ! -f /opt/bin/opkg ] && [ "$sleepTimerSecs" -lt "$maxSleepTimer" ] + do + if [ "$((sleepTimerSecs % 10))" -eq 0 ] + then + Print_Output true "Entware NOT found, sleeping for $theSleepDelay secs [$sleepTimerSecs secs]..." "$WARN" + fi + sleep "$theSleepDelay" + sleepTimerSecs="$((sleepTimerSecs + theSleepDelay))" done - if [ ! -f /opt/bin/opkg ]; then - Print_Output true "Entware not found and is required for $SCRIPT_NAME to run, please resolve" "$CRIT" + if [ ! -f /opt/bin/opkg ] + then + Print_Output true "Entware NOT found and is required for $SCRIPT_NAME to run, please resolve." "$CRIT" Clear_Lock exit 1 else @@ -3732,7 +4916,8 @@ Entware_Ready(){ ### ### ### function based on @dave14305's FlexQoS about function ### -Show_About(){ +Show_About() +{ cat </dev/null - if AutomaticMode check; then Auto_Cron create 2>/dev/null; else Auto_Cron delete 2>/dev/null; fi + if AutomaticMode check + then Auto_Cron create 2>/dev/null + else Auto_Cron delete 2>/dev/null + fi Auto_ServiceEvent create 2>/dev/null Shortcut_Script create Process_Upgrade @@ -3808,6 +5006,9 @@ then exit 0 fi +##----------------------------------------## +## Modified by Martinski W. [2024-Dec-21] ## +##----------------------------------------## case "$1" in install) Check_Lock @@ -3826,6 +5027,16 @@ case "$1" in Clear_Lock exit 0 ;; + trimdb) + NTP_Ready + Entware_Ready + Check_Lock + _Trim_Database_ + _Optimize_Database_ + _UpdateDatabaseFileSizeInfo_ + Clear_Lock + exit 0 + ;; outputcsv) NTP_Ready Entware_Ready @@ -3836,16 +5047,20 @@ case "$1" in ;; enable) Entware_Ready + Check_Lock AutomaticMode enable + Clear_Lock exit 0 ;; disable) - Entware_Ready + Check_Lock AutomaticMode disable + Clear_Lock exit 0 ;; service_event) - if [ "$2" = "start" ] && [ "$3" = "$SCRIPT_NAME" ]; then + if [ "$2" = "start" ] && [ "$3" = "$SCRIPT_NAME" ] + then rm -f "$SCRIPT_WEB_DIR/detect_connmon.js" rm -f /tmp/pingfile.txt rm -f "$SCRIPT_WEB_DIR/ping-result.txt" @@ -3854,38 +5069,48 @@ case "$1" in Run_PingTest Clear_Lock exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}config" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}config" ] + then + Check_Lock webui echo 'var savestatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_save.js" sleep 3 Conf_FromSettings echo 'var savestatus = "Success";' > "$SCRIPT_WEB_DIR/detect_save.js" + Clear_Lock exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}emailconfig" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}emailconfig" ] + then echo 'var savestatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_save.js" sleep 3 EmailConf_FromSettings echo 'var savestatus = "Success";' > "$SCRIPT_WEB_DIR/detect_save.js" exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}checkupdate" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}checkupdate" ] + then Update_Check exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}doupdate" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}doupdate" ] + then Update_Version force unattended exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}emailpassword" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}emailpassword" ] + then if Email_ConfExists; then rm -f "$SCRIPT_WEB_DIR/password.htm" sleep 3 Email_Decrypt_Password > "$SCRIPT_WEB_DIR/password.htm" fi - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}deleteemailpassword" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}deleteemailpassword" ] + then rm -f "$SCRIPT_WEB_DIR/password.htm" - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}customactionlist" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}customactionlist" ] + then rm -f "$SCRIPT_STORAGE_DIR/.customactionlist" sleep 3 CustomAction_List silent exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestEmail" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestEmail" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" NOTIFICATIONS_EMAIL_LIST="$(Email_Recipients check)" @@ -3911,7 +5136,8 @@ case "$1" in fi unset IFS exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestWebhooks" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestWebhooks" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" NOTIFICATIONS_WEBHOOK_LIST="$(Webhook_Targets check)" @@ -3932,7 +5158,8 @@ case "$1" in echo 'var teststatus = "Fail";' > "$SCRIPT_WEB_DIR/detect_test.js" fi exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestPushover" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestPushover" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" if SendPushover "$(/bin/date +"%c")"$'\n'$'\n'"This is a test pushover message!"; then @@ -3941,7 +5168,8 @@ case "$1" in echo 'var teststatus = "Fail";' > "$SCRIPT_WEB_DIR/detect_test.js" fi exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestCustomActions" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestCustomActions" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" if [ -z "$(ls -A "$USER_SCRIPT_DIR")" ]; then @@ -3957,7 +5185,8 @@ case "$1" in echo 'var teststatus = "Success";' > "$SCRIPT_WEB_DIR/detect_test.js" fi exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestHealthcheck" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestHealthcheck" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" if SendHealthcheckPing "Pass"; then @@ -3966,7 +5195,8 @@ case "$1" in echo 'var teststatus = "Fail";' > "$SCRIPT_WEB_DIR/detect_test.js" fi exit 0 - elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestInfluxDB" ]; then + elif [ "$2" = "start" ] && [ "$3" = "${SCRIPT_NAME}TestInfluxDB" ] + then rm -f "$SCRIPT_WEB_DIR/detect_test.js" echo 'var teststatus = "InProgress";' > "$SCRIPT_WEB_DIR/detect_test.js" if SendToInfluxDB "$(/bin/date +%s)" 30 15 90; then @@ -3992,7 +5222,10 @@ case "$1" in ScriptStorageLocation load Create_Symlinks Auto_Startup create 2>/dev/null - if AutomaticMode check; then Auto_Cron create 2>/dev/null; else Auto_Cron delete 2>/dev/null; fi + if AutomaticMode check + then Auto_Cron create 2>/dev/null + else Auto_Cron delete 2>/dev/null + fi Auto_ServiceEvent create 2>/dev/null Shortcut_Script create Process_Upgrade @@ -4026,8 +5259,8 @@ case "$1" in ;; *) ScriptHeader - Print_Output false "Command not recognised" "$ERR" - Print_Output false "For a list of available commands run: $SCRIPT_NAME help" + Print_Output false "Parameter [$*] is NOT recognised." "$ERR" + Print_Output false "For a list of available commands run: $SCRIPT_NAME help" "$SETTING" exit 1 ;; esac diff --git a/connmonstats_www.asp b/connmonstats_www.asp index b746b5a..24754eb 100644 --- a/connmonstats_www.asp +++ b/connmonstats_www.asp @@ -12,7 +12,7 @@ @@ -35,7 +35,7 @@ -
- - -
- "> - - - - - - -
-
- - - - - - - - - "> - "> - - - - -
  - - - - - - -
- - - -
-
 
-
- connmon
-
Stats last updated: -
-
-
connmon is an internet connection monitoring - tool for AsusWRT Merlin with charts for daily, weekly and monthly - summaries.
-
-
- - - - - -
-
- -