From 54e2477dd6a64f5f595b9e8db2a2143f2051127f Mon Sep 17 00:00:00 2001
From: bav6096 <benedikt.deike@informatik.uni-hamburg.de>
Date: Mon, 1 Nov 2021 00:33:09 +0100
Subject: [PATCH] added topic for visualisation

---
 CMakeLists.txt             |  4 +++
 msg/Metric.msg             |  9 +++---
 msg/Monitoring.msg         |  1 -
 msg/State.msg              |  3 ++
 msg/States.msg             |  1 +
 nodes/monitor_test         |  4 +--
 nodes/monitor_test2        | 25 ++++++++++++++++
 nodes/watchdog             |  3 +-
 src/monitoring/monitor.py  |  6 ++--
 src/monitoring/watchdog.py | 60 ++++++++++++++++++++++++--------------
 10 files changed, 82 insertions(+), 34 deletions(-)
 create mode 100644 msg/State.msg
 create mode 100644 msg/States.msg
 create mode 100755 nodes/monitor_test2

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7bd6a6a..8ec28b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,6 +51,8 @@ add_message_files(
    FILES
    Monitoring.msg
    Metric.msg
+   States.msg
+   State.msg
 )
 
 ## Generate services in the 'srv' folder
@@ -161,6 +163,8 @@ include_directories(
 ## Mark executable scripts (Python etc.) for installation
 ## in contrast to setup.py, you can choose the destination
 catkin_install_python(PROGRAMS
+   nodes/watchdog
+   nodes/monitor_test2
    nodes/monitor_test
    DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
 )
diff --git a/msg/Metric.msg b/msg/Metric.msg
index 26728b1..08f3888 100644
--- a/msg/Metric.msg
+++ b/msg/Metric.msg
@@ -1,4 +1,5 @@
-string  label    # Label of the metric.
-string  value    # Value of the metric.
-string  unit     # Unit of the metric.
-float32 critical # Critical level of the metric.
\ No newline at end of file
+string  component # A metric is affiliated with a roboter component.
+string  label     # Label of the metric.
+string  value     # Value of the metric.
+string  unit      # Unit of the metric.
+float32 critical  # Critical level of the metric.
\ No newline at end of file
diff --git a/msg/Monitoring.msg b/msg/Monitoring.msg
index 4274d62..dd121ac 100644
--- a/msg/Monitoring.msg
+++ b/msg/Monitoring.msg
@@ -1,3 +1,2 @@
-string family # Affiliation of the monitored metric.
 string origin # Origin of the monitored metric.
 Metric metric # Monitored metric.
\ No newline at end of file
diff --git a/msg/State.msg b/msg/State.msg
new file mode 100644
index 0000000..0d2c235
--- /dev/null
+++ b/msg/State.msg
@@ -0,0 +1,3 @@
+string  component # Name of the component, whose
+                  # critical level is monitored.
+float32 critical  # Critical level of the family.
\ No newline at end of file
diff --git a/msg/States.msg b/msg/States.msg
new file mode 100644
index 0000000..d670583
--- /dev/null
+++ b/msg/States.msg
@@ -0,0 +1 @@
+State[] states # Array of states.
diff --git a/nodes/monitor_test b/nodes/monitor_test
index 01d669c..50119dd 100755
--- a/nodes/monitor_test
+++ b/nodes/monitor_test
@@ -6,11 +6,11 @@ from monitoring.monitor import Monitor
 
 def monitor_test():
     rospy.init_node("monitor_test")
-    monitor = Monitor(1, 1, "test")
+    monitor = Monitor(1, 1)
 
     rate = rospy.Rate(10)
     while not rospy.is_shutdown():
-        monitor.update_metric("test", 10, "test", 0.5)
+        monitor.update_metric("family", "label1", 10, "unit", 0.5)
         rate.sleep()
 
 
diff --git a/nodes/monitor_test2 b/nodes/monitor_test2
new file mode 100755
index 0000000..663b197
--- /dev/null
+++ b/nodes/monitor_test2
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+import rospy
+from monitoring.monitor import Monitor
+
+
+def monitor_test():
+    rospy.init_node("monitor_test2")
+    monitor = Monitor(1, 1)
+
+    rate = rospy.Rate(10)
+    value = 0
+    while not rospy.is_shutdown():
+        monitor.update_metric("family", "label2", 10, "unit", value)
+        value = value + 0.1
+        if value > 1.0:
+            value = 0
+        rate.sleep()
+
+
+if __name__ == '__main__':
+    try:
+        monitor_test()
+    except rospy.ROSInterruptException:
+        pass
diff --git a/nodes/watchdog b/nodes/watchdog
index 24ef85b..dc20214 100755
--- a/nodes/watchdog
+++ b/nodes/watchdog
@@ -6,11 +6,10 @@ from monitoring.watchdog import Watchdog
 
 def watchdog():
     rospy.init_node("watchdog")
-    watching = Watchdog(1.0)
+    watching = Watchdog(1, 1.0)
 
     rate = rospy.Rate(10)
     while not rospy.is_shutdown():
-        print(watching.states)
         rate.sleep()
 
 
diff --git a/src/monitoring/monitor.py b/src/monitoring/monitor.py
index 54c986a..307b26a 100755
--- a/src/monitoring/monitor.py
+++ b/src/monitoring/monitor.py
@@ -7,7 +7,7 @@ from monitoring.msg import Metric
 
 
 class Monitor:
-    def __init__(self, mode=1, freq=1.0, family="generic"):
+    def __init__(self, mode=1, freq=1.0):
         self.log = {}  # Logging dictionary. Is used to accomplish different publishing modes.
         self.pub = rospy.Publisher('monitoring', Monitoring, queue_size=1)
         self.mode = mode
@@ -19,16 +19,16 @@ class Monitor:
         self.timer = rospy.Timer(rospy.Duration(1.0 / freq), self.publish_monitoring)
 
         self.monitoring = Monitoring()
-        self.monitoring.family = family
         self.monitoring.origin = socket.gethostname() + rospy.get_name()
 
     # At the moment the last metric update ist published over and over.
     def publish_monitoring(self, event):
         self.pub.publish(self.monitoring)
 
-    def update_metric(self, label, value, unit, critical):
+    def update_metric(self, component, label, value, unit, critical):
         def set_metric():
             metric = Metric()
+            metric.component = str(component)
             metric.label = str(label)
             metric.value = str(value)
             metric.unit = str(unit)
diff --git a/src/monitoring/watchdog.py b/src/monitoring/watchdog.py
index 829d084..3529bfd 100755
--- a/src/monitoring/watchdog.py
+++ b/src/monitoring/watchdog.py
@@ -2,54 +2,70 @@
 
 import rospy
 from monitoring.msg import Monitoring
+from monitoring.msg import State
+from monitoring.msg import States
 
 
 class Watchdog:
-    def __init__(self, freq):
-        self.states = {}
+    def __init__(self, mode=1, freq=1.0):
+        self.mode = mode
+        self.pub = rospy.Publisher('states', States, queue_size=1)
+        self.component_states = {}
         self.observing = {}
 
         if not freq > 0.0:
             rospy.logwarn("Frequency must be greater then 0! Using 1 as frequency!")
             freq = 1.0
 
-        self.timer = rospy.Timer(rospy.Duration(1.0 / freq), self.update_state)
+        self.timer = rospy.Timer(rospy.Duration(1.0 / freq), self.update_states)
 
         rospy.Subscriber("monitoring", Monitoring, self.logging)
 
     def logging(self, monitoring):
-        family = monitoring.family
         origin = monitoring.origin
         metric = monitoring.metric
 
+        component = metric.component
         label = metric.label
         value = metric.value
         unit = metric.unit
         critical = metric.critical
 
-        if family in self.observing:
-            if origin in self.observing[family]:
-                self.observing[family][origin].update({label: {"value": value, "unit": unit, "critical": critical}})
+        if component in self.observing:
+            if origin in self.observing[component]:
+                self.observing[component][origin].update({label: {"value": value, "unit": unit, "critical": critical}})
             else:
-                self.observing[family][origin] = {}
-                self.observing[family][origin][label] = {"value": value, "unit": unit, "critical": critical}
+                self.observing[component][origin] = {}
+                self.observing[component][origin][label] = {"value": value, "unit": unit, "critical": critical}
         else:
-            self.observing[family] = {}
-            self.observing[family][origin] = {}
-            self.observing[family][origin][label] = {"value": value, "unit": unit, "critical": critical}
+            self.observing[component] = {}
+            self.observing[component][origin] = {}
+            self.observing[component][origin][label] = {"value": value, "unit": unit, "critical": critical}
 
-    def update_state(self, event):
-        for family in self.observing:
-            aggregation = 0
-            number = 0
+    def update_states(self, event):
+        for component in self.observing:
+            # Mode 1: Take the average critical level for a component
+            if self.mode == 1:
+                aggregation = 0
+                number = 0
 
-            for origin in self.observing[family]:
-                for label in self.observing[family][origin]:
-                    number = number + 1
-                    aggregation = aggregation + self.observing[family][origin][label]["critical"]
+                for origin in self.observing[component]:
+                    for label in self.observing[component][origin]:
+                        number = number + 1
+                        aggregation = aggregation + self.observing[component][origin][label]["critical"]
 
-            quotient = aggregation / number
-            self.states.update({family: quotient})
+                quotient = aggregation / number
+                self.component_states.update({component: quotient})
 
+        self.publish_states()
 
+    def publish_states(self):
+        topic = States()
+        for component in self.component_states:
+            state = State()
+            state.component = component
+            state.critical = self.component_states[component]
 
+            topic.states.append(state)
+
+        self.pub.publish(topic)
-- 
GitLab