diff --git a/.gitmodules b/.gitmodules
index d0b6407..52ea8f1 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,7 @@
[submodule "html/metar.js"]
path = html/metar.js
url = https://github.com/skydivejkl/metar.js
+[submodule "html/open-iconic"]
+ path = html/open-iconic
+ url = https://github.com/iconic/open-iconic
+ branch = master
diff --git a/html/css/styles.css b/html/css/styles.css
index d16b55b..01d2adf 100644
--- a/html/css/styles.css
+++ b/html/css/styles.css
@@ -30,3 +30,6 @@ td.dt-nowrap { white-space: nowrap }
.red {
background-color: Coral !important;
}
+
+
+#services_monitor_list {list-style-type: none;}
\ No newline at end of file
diff --git a/html/data/TG_List.csv b/html/data/TG_List.csv
index e7fac7f..a1f89dc 100644
--- a/html/data/TG_List.csv
+++ b/html/data/TG_List.csv
@@ -6,8 +6,8 @@ YSF,0,1,Local Parrot,
YSF,0,2,DEV Reflector,
YSF,0,10,YSF2DMR TG26250,
YSF,0,40,DL Multimode 263,https://c4fm.ysfreflector.de/Germany/
-YSF,0,41,DL-RAMSES,
-YSF,0,42,DL-RAMSES-II,
+YSF,0,41,DL-RAMSES,http://161.97.140.131:8000/RAMSES.html
+YSF,0,42,DL-RAMSES-II,http://161.97.140.131:8000/RAMSES-II.html
YSF,0,43,DL-RAMSES-III,
YSF,0,44,DL-PEGASUS,
YSF,0,45,DL-SAAR,https://c4fm.ysfreflector.de/DL-Saar/
diff --git a/html/index.html b/html/index.html
index e336f67..ce560d3 100644
--- a/html/index.html
+++ b/html/index.html
@@ -29,6 +29,7 @@
+
DG9VH - MMDVM-Dashboard by DG9VH
@@ -87,6 +88,9 @@
System Info
+
+ Services Monitor
+
About
@@ -294,6 +298,15 @@
+
@@ -446,6 +459,13 @@
t_dapnet.order( [ 0, 'desc' ] ).draw();
}
+ if (services > 0) {
+ var ws3 = new WebSocket("ws://" + window.location.hostname + ":5678/SERVICES");
+ ws3.onmessage = function (event) {
+ getServicesStatus(document, event);
+ };
+ }
+
checkConfigStructure();
diff --git a/html/js/config.js b/html/js/config.js
index 92acc36..311aa34 100644
--- a/html/js/config.js
+++ b/html/js/config.js
@@ -1,5 +1,5 @@
// config structure version, please change to value in github-file after update and adding new values
-var config_struc_ver = 20210312.1;
+var config_struc_ver = 20210414.1;
// 1 = show link to QRZ.com, 0 = off
var qrz = 1;
@@ -20,6 +20,7 @@ var allheard = 1;
var qso = 1;
var dapnet = 1;
var sysinfo = 1;
+var services = 1;
var about = 1;
// Set displayed timezone and timestamp to timezone of browser if 1, else use UTC for displaying
@@ -38,4 +39,4 @@ var qrz_blacklist = [
var dashboard_blacklist = [
"MY0CALL",
-]
\ No newline at end of file
+]
diff --git a/html/js/functions.js b/html/js/functions.js
index fd1555c..9202c50 100644
--- a/html/js/functions.js
+++ b/html/js/functions.js
@@ -1,4 +1,4 @@
-var act_config_struc_ver = 20210312.1;
+var act_config_struc_ver = 20210314.1;
var messagecount = 0;
var ts1TXing = null;
var ts2TXing = null;
@@ -21,6 +21,8 @@ dapnet = typeof(dapnet) == 'undefined' ? 1 : dapnet;
sysinfo = typeof(sysinfo) == 'undefined' ? 1 : sysinfo;
about = typeof(about) == 'undefined' ? 1 : about;
+var array_services = [];
+
setInterval(getCurrentTXing, 1000);
function logIt(message) {
@@ -857,6 +859,61 @@ function getSysInfo(document, event) {
});
}
+function getServiceName(event) {
+ return event.data.substring(17, event.data.lastIndexOf(":"));
+}
+
+
+function getServiceState(event) {
+ return event.data.substr(event.data.lastIndexOf(":") + 1);
+}
+
+function addToServices(servicename, servicestate) {
+ var newService = new Array();
+ newService[0] = servicename;
+ newService[1] = servicestate;
+ array_services.push(newService);
+}
+
+function insertOrUpdateServiceState(servicename, servicestate) {
+ updated = false;
+ for (i = 0; i < array_services.length; ++i){
+ actual_service = array_services[i];
+ if (actual_service[0] == servicename) {
+ var newService = new Array();
+ newService[0] = servicename;
+ newService[1] = servicestate;
+ array_services[i] = newService;
+ updated = true;
+ }
+ }
+ if (updated == false) {
+ addToServices(servicename, servicestate);
+ }
+}
+
+function getServicesStatus(document, event) {
+ $(document).ready(function() {
+ if (event.data.startsWith("SERVICESMONITOR")) {
+ var servicename = getServiceName(event);
+ var servicestate = getServiceState(event);
+ insertOrUpdateServiceState(servicename, servicestate);
+
+ document.getElementById("services_monitor").innerHTML = '
';
+ //document.getElementById("services_monitor").innerHTML = '';
+
+ array_services.forEach(function(actual_service){
+ if (actual_service[1] == "running") {
+ document.getElementById("services_monitor_list").innerHTML += '- ' + actual_service[0] + '
';
+ } else {
+ document.getElementById("services_monitor_list").innerHTML += '- ' + actual_service[0] + '
';
+ }
+ });
+ document.getElementById("services_monitor").innerHTML += "
";
+ }
+ });
+}
+
function activateDefaultTab(name) {
var element = document.getElementById(name + "-tab");
element.classList.add("active");
diff --git a/html/js/version.js b/html/js/version.js
index 20afeb6..3395fe9 100644
--- a/html/js/version.js
+++ b/html/js/version.js
@@ -1 +1 @@
-var dashboard_version = "2021-04-10 19:54:10";
+var dashboard_version = "2021-04-14 22:04:34";
diff --git a/html/open-iconic b/html/open-iconic
new file mode 160000
index 0000000..1d1e888
--- /dev/null
+++ b/html/open-iconic
@@ -0,0 +1 @@
+Subproject commit 1d1e8885c5031874b32f4e480e371ce2b1c24144
diff --git a/logtailer.ini b/logtailer.ini
index 216238a..ebfbaee 100644
--- a/logtailer.ini
+++ b/logtailer.ini
@@ -41,3 +41,9 @@ MMDVM_bin=/usr/local/bin/MMDVMHost
Logdir=/mnt/ramdisk/
Prefix=DAPNETGateway
+[ServiceMonitoring]
+# Here you list your Services to be monitored
+BinaryName1=MMDVMHost
+BinaryName2=DMRGateway
+BinaryName3=DGIdGateway
+BinaryName4=YSF2DMR
diff --git a/logtailer.py b/logtailer.py
index 42ad9cf..a3d7450 100644
--- a/logtailer.py
+++ b/logtailer.py
@@ -260,7 +260,8 @@ async def view_log(websocket, path):
await websocket.send(line)
else:
await asyncio.sleep(0.2)
- elif path == "/SYSINFO":
+
+ if path == "/SYSINFO":
mmdvmhost_version = str(subprocess.Popen(config['MMDVMHost']['MMDVM_bin'] + " -v", shell=True, stdout=subprocess.PIPE).stdout.read().decode("utf-8"))
mmdvmhost_ctime = time.ctime(os.path.getmtime(config['MMDVMHost']['MMDVM_bin']))
mmdvmhost_buildtime = datetime.datetime.strptime(mmdvmhost_ctime, "%a %b %d %H:%M:%S %Y")
@@ -304,6 +305,19 @@ async def view_log(websocket, path):
await websocket.send("SYSINFO: cputemp:" + cpu_temp + " cpufrg:" + cpufrq + " cpuusage:" + cpu_usage + " cpu_load1:" + cpu_load1 + " cpu_load5:" + cpu_load5 + " cpu_load15:" + cpu_load15 + " ram_total:" + ram_total + " ram_used:" + ram_used + " ram_free:" + ram_free + " ram_percent_used:" + ram_percent_used + " disk_total:" + disk_total + " disk_used:" + disk_used + " disk_free:" + disk_free + " disk_percent_used:" + disk_percent_used)
await asyncio.sleep(10)
+ if path == "/SERVICES":
+ services_items = [x for x in config.items('ServiceMonitoring') if x[0] not in config.defaults()]
+ while True:
+ for key, value in services_items:
+ logging.info('key: ' + key + " = " + value)
+ if checkIfProcessRunning(value):
+ logging.info('process ' + value + " is running")
+ await websocket.send("SERVICESMONITOR: " + value + ":running")
+ else:
+ logging.info('process ' + value + " is stopped")
+ await websocket.send("SERVICESMONITOR: " + value + ":stopped")
+ await asyncio.sleep(30)
+
except ValueError as e:
try:
await websocket.send('Logtailer-Errormessage: ValueError: {}'.format(e))
@@ -325,6 +339,21 @@ async def view_log(websocket, path):
log_close(websocket, path)
+def checkIfProcessRunning(processName):
+ '''
+ Check if there is any running process that contains the given name processName.
+ '''
+ #Iterate over the all the running process
+ for proc in psutil.process_iter():
+ try:
+ # Check if process name contains the given name string.
+ if processName.lower() in proc.name().lower():
+ return True
+ except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
+ pass
+ return False;
+
+
def log_close(websocket, path, exception=None):
message = 'Closed, remote={}, path={}'.format(websocket.remote_address, path)
if exception is not None: