Преглед изворни кода

Implemented new graph based configuration

Lukas Cerny пре 4 година
родитељ
комит
bf9074225c
28 измењених фајлова са 310 додато и 430 уклоњено
  1. 15 15
      build.gradle
  2. 90 24
      config/example.yaml
  3. 29 13
      config/foodie.yaml
  4. 0 48
      config/foodie_senslog.yaml
  5. 3 2
      config/lv.yaml
  6. 0 41
      config/lv_senslog_ws.yaml
  7. 0 105
      config/new_example.yaml
  8. 2 2
      docker/start.sh
  9. 3 0
      src/main/java/cz/senslog/watchdog/app/Application.java
  10. 65 36
      src/main/java/cz/senslog/watchdog/app/Watcher.java
  11. 5 0
      src/main/java/cz/senslog/watchdog/config/AllMonitoredObjects.java
  12. 13 24
      src/main/java/cz/senslog/watchdog/config/Configuration.java
  13. 1 1
      src/main/java/cz/senslog/watchdog/config/DataProviderType.java
  14. 1 1
      src/main/java/cz/senslog/watchdog/config/ExecutableGroup.java
  15. 7 1
      src/main/java/cz/senslog/watchdog/config/GroupConfig.java
  16. 1 1
      src/main/java/cz/senslog/watchdog/config/MonitoredObject.java
  17. 0 17
      src/main/java/cz/senslog/watchdog/config/SensLogGroupConfig.java
  18. 2 2
      src/main/java/cz/senslog/watchdog/config/SuperGroupConfig.java
  19. 12 13
      src/main/java/cz/senslog/watchdog/config/WSSensLogDataProviderConfig.java
  20. 7 7
      src/main/java/cz/senslog/watchdog/core/DataProviderInstanceCreator.java
  21. 8 1
      src/main/java/cz/senslog/watchdog/domain/Report.java
  22. 15 0
      src/main/java/cz/senslog/watchdog/messagebroker/broker/EmailMessageBroker.java
  23. 0 4
      src/main/java/cz/senslog/watchdog/provider/DataProvider.java
  24. 6 6
      src/main/java/cz/senslog/watchdog/provider/DataProviderManager.java
  25. 4 0
      src/main/java/cz/senslog/watchdog/provider/ProvidedData.java
  26. 3 8
      src/main/java/cz/senslog/watchdog/provider/database/DBDataProvider.java
  27. 18 44
      src/main/java/cz/senslog/watchdog/provider/ws/WSSensLogDataProvider.java
  28. 0 14
      src/main/java/cz/senslog/watchdog/util/http/HttpClient.java

+ 15 - 15
build.gradle

@@ -15,8 +15,8 @@ test {
 }
 
 java {
-    sourceCompatibility = JavaVersion.VERSION_1_8
-    targetCompatibility = JavaVersion.VERSION_1_8
+    sourceCompatibility = JavaVersion.VERSION_11
+    targetCompatibility = JavaVersion.VERSION_11
 }
 
 jar {
@@ -32,20 +32,20 @@ jar {
 
 dependencies {
 
-    compile group: 'com.beust', name: 'jcommander', version: '1.78'
-    compile group: 'org.yaml', name: 'snakeyaml', version: '1.24'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.12.0'
-    compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.0'
-    compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.9'
-    compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
+    implementation group: 'com.beust', name: 'jcommander', version: '1.78'
+    implementation group: 'org.yaml', name: 'snakeyaml', version: '1.24'
+    implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.12.0'
+    implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.12.0'
+    implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.9'
+    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
 
-    compile group: 'org.jdbi', name: 'jdbi3-postgres', version: '3.12.2'
-    compile group: 'org.jdbi', name: 'jdbi3-jodatime2', version: '3.12.2'
-    compile group: 'com.zaxxer', name: 'HikariCP', version: '3.4.2'
-    compile group: 'org.postgresql', name: 'postgresql', version: '42.2.10'
+    implementation group: 'org.jdbi', name: 'jdbi3-postgres', version: '3.12.2'
+    implementation group: 'org.jdbi', name: 'jdbi3-jodatime2', version: '3.12.2'
+    implementation group: 'com.zaxxer', name: 'HikariCP', version: '3.4.2'
+    implementation group: 'org.postgresql', name: 'postgresql', version: '42.2.10'
 
-    compile group: 'javax.mail', name: 'javax.mail-api', version: '1.6.2'
-    compile group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
+    implementation group: 'javax.mail', name: 'javax.mail-api', version: '1.6.2'
+    implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
 
-    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0'
+    testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.4.0'
 }

+ 90 - 24
config/example.yaml

@@ -1,39 +1,105 @@
-dataProvider:
-  type: DATABASE
-  config:
-    url: "jdbc:postgresql://localhost:5432/senslog"
-    username: "<username>"
-    password: "<password>"
-    connectionPoolSize: 6
-    groupName: "<group_name>"
-
-messageBroker:
-  type: EMAIL # EMAIL, CONSOLE (for testing), WHATSAPP (not yet), TELEGRAM (not yet)
-  vanishPeriod: 3 # number of days when already send report could be sent again
-  config:
+emailServers:
+  exampleEmailServer:
     smtpHost: "<smtp_server>"
     smtpPort: 465
-    authUsername: "<username>"
-    authPassword: "<password>"
-    senderEmail: "<sender_email>"
-    recipientEmail: "<recipient_email>"
-    subject: "<subject>"
+    authUsername: "username"
+    authPassword: "password"
+
+messageBrokers:
+  emailToAll:
+    type: EMAIL
+    config:
+      server: exampleEmailServer
+      senderEmail: "from@example.org"
+      recipientEmail: "to@example.org"
+      subject: "[watchdog] Example Report"
+  emailToTeam:
+    type: EMAIL
+    config:
+      server: exampleEmailServer
+      senderEmail: "from@example.org"
+      recipientEmail: "to@example.org"
+      subject: "[watchdog] Example Report"
+  signalEmergency:
+    type: SIGNAL
+    config:
+      recipientNumber: "+420 123 456 789"
+      senderNumber: "+420 123 456 789"
+      messagePattern: "No actual data from: $unit_id/$sensor_id"  # available props: $unit_id, $sensor_id, $timestamp, $value
+
+dataProviders:
+  wsServer1:
+    type: WEB_SERVICE
+    config:
+      baseUrl: "<senslog_domain_url>"
+      userName: "<user-name>"
+      groupName: "<group-name>"
+  wsServer2:
+    type: WEB_SERVICE
+    config:
+      baseUrl: "<senslog_domain_url>"
+      userName: "<user-name>"
+      groupName: "<group-name>"
+  dbServer:
+    type: DATABASE
+    config:
+      url: "<jdbc_url>"
+      username: "<username>"
+      password: "<password>"
+      connectionPoolSize: 6
+      groupName: "<group_name>"
+
+groups:
+  group1Checker:
+    name: "Group name 1"
+    dataProvider: wsServer1
+    messageBroker: emailToTeam
+    resultType: ALL
+    period: 86400
+  group2Checker:
+    name: "Group name 2"
+    dataProvider: dbServer
+    messageBroker: emailToTeam
+    resultType: ALL
+    period: 86400
+  groupRealTime:
+    name: "Group name 3"
+    dataProvider: wsServer1
+    messageBroker: signalEmergency
+    resultType: FAIL
+
+superGroups:
+  sumarizeError:
+    name: "Sum group"
+    messageBroker: emailToAll
+    resultType: FAIL
+    period: 86400
+    groups: [ group1Checker, group2Checker ]
 
 monitoredObjects:
   unit_id_1:
-    interval: 1440
+    groups: [group1Checker, group2Checker]
+    period: 1440
 
   unit_id_2:
-    interval: 1440
+    period: 1440
+    groups: [groupRealTime]
     sensors: [210000000, 220000000]
 
   unit_id_3:
-    interval: 1440
+    period: 1440
+    groups: [groupRealTime]
     sensors:
       310000000:
-      320000000: 2880
+        groups: [group1Checker]
+      320000000:
+        period: 2880
 
   unit_id_4:
     sensors:
-      410000000: 2880
-      420000000: 1440
+      410000000:
+        period: 2880
+        groups: [group1Checker]
+      420000000:
+        period: 1440
+        groups: [group1Checker]

+ 29 - 13
config/new_foodie.yaml → config/foodie.yaml

@@ -11,7 +11,7 @@ messageBrokers:
     config:
       server: lspEmail
       senderEmail: "watchdog@senslog.org"
-      recipientEmail: "luc.cerny@gmail.com"
+      recipientEmail: "luccerny@kiv.zcu.cz"
       subject: "[Watchdog] TEST Report Foodie SensLog (CZ)"
   emailToAll:
     type: EMAIL
@@ -22,48 +22,64 @@ messageBrokers:
       subject: "[Watchdog] Report Foodie SensLog (CZ)"
 
 dataProviders:
-  wsOldFoodie:
+  wsOldFoodieKynsperk:
     type: WEB_SERVICE
     config:
-      baseUrl: "http://foodie.lesprojekt.cz:8080/MapLogOT"
-      user: "kynsperk"
-      group: "kynsperk"
+      baseUrl: "http://sensor.lesprojekt.cz/DBServiceST"
+      userName: "kynsperk"
+      groupName: "kynsperk"
+
+  wsOldFoodieRostenice:
+    type: WEB_SERVICE
+    config:
+      baseUrl: "http://sensor.lesprojekt.cz/DBServiceST"
+      userName: "mikrsoil"
+      groupName: "rostenice_pudni"
 
 groups:
   kynsperk:
-    dataProvider: wsOldFoodie
+    name: "Kynsperk"
+    dataProvider: wsOldFoodieKynsperk
+    messageBroker: emailToAll
+    resultType: FAIL
+    period: 86400
+
+  rostenice:
+    name: "Rostenice"
+    dataProvider: wsOldFoodieRostenice
     messageBroker: emailToAll
     resultType: FAIL
     period: 86400
 
+
 monitoredObjects:
-  1305167562293765:
+  1305167562293765: # no data
     period: 86400
     groups: [kynsperk]
     sensors: [ 340340092, 360200000, 410130092 ]
 
-  1305167562275270:
+  1305167562275270: # no data
     period: 86400
     groups: [kynsperk]
     sensors: [ 340240003, 360200000, 410090003 ]
 
-  1305167562292824:
+  1305167562292824: # no data
     period: 86400
     groups: [kynsperk]
 
-  1305167549144045:
+  1305167549173046: # no data
     period: 86400
     groups: [ kynsperk ]
 
-  1305167549158198:
+  1305167549144045:
     period: 86400
     groups: [ kynsperk ]
 
-  1305167549167050:
+  1305167549158198:
     period: 86400
     groups: [ kynsperk ]
 
-  1305167549173046:
+  1305167549167050:
     period: 86400
     groups: [ kynsperk ]
 

+ 0 - 48
config/foodie_senslog.yaml

@@ -1,48 +0,0 @@
-dataProvider:
-  type: WEB_SERVICE
-  config:
-    url: "http://foodie.lesprojekt.cz:8080/MapLogOT"
-    group: "kynsperk"
-    user: "kynsperk"
-
-messageBroker:
-  type: EMAIL # EMAIL, CONSOLE (for testing), WHATSAPP (not yet), TELEGRAM (not yet)
-  vanishPeriod: 1 # number of days when already send report could be sent again
-  config:
-    smtpHost: "mail.lesprojekt.cz"
-    smtpPort: 465
-    authUsername: "watchdog@senslog.org"
-    authPassword: "5jspdD"
-    senderEmail: "watchdog@senslog.org"
-    recipientEmail: "luc.cerny@gmail.com, kepka@ccss.cz"
-    subject: "[Watchdog] Report Foodie SensLog (CZ)"
-
-monitoredObjects:
-  1305167562293765:
-    interval: 86400 # 1 day
-    sensors: [340340092, 360200000, 410130092]
-
-  1305167562275270:
-    interval: 86400 # 1 day
-    sensors: [340240003, 360200000, 410090003]
-
-  1305167562292824:
-    interval: 86400 # 1 day
-
-  1305167549144045:
-    interval: 86400 # 1 day
-
-  1305167549158198:
-    interval: 86400 # 1 day
-
-  1305167549167050:
-    interval: 86400 # 1 day
-
-  1305167549173046:
-    interval: 86400 # 1 day
-
-  1305167549167886:
-    interval: 86400 # 1 day
-
-  1305167549149707:
-    interval: 86400 # 1 day

+ 3 - 2
config/new_lv.yaml → config/lv.yaml

@@ -26,11 +26,12 @@ dataProviders:
     type: WEB_SERVICE
     config:
       baseUrl: "http://51.15.45.95:8080/senslog1"
-      user: "vilcini"
-      group: "vilcini"
+      userName: "vilcini"
+      groupName: "vilcini"
 
 groups:
   vilcini:
+    name: "Vilnici"
     dataProvider: wsVilcini
     messageBroker: emailToTest
     resultType: FAIL

+ 0 - 41
config/lv_senslog_ws.yaml

@@ -1,41 +0,0 @@
-dataProvider:
-  type: WEB_SERVICE
-  config:
-    url: "http://51.15.45.95:8080/senslog1"
-    group: "vilcini"
-    user: "vilcini"
-
-messageBroker:
-  type: CONSOLE # EMAIL, CONSOLE (for testing), WHATSAPP (not yet), TELEGRAM (not yet)]
-  vanishPeriod: 3 # number of days when already send report could be sent again
-  config:
-#    smtpHost: "mail.lesprojekt.cz"
-#    smtpPort: 465
-#    authUsername: "watchdog@senslog.org"
-#    authPassword: "5jspdD"
-#    senderEmail: "watchdog@senslog.org"
-#    recipientEmail: "luc.cerny@gmail.com" # "kepka@ccss.cz"
-#    subject: "[Watchdog] Report SAH SensLog (LV)"
-
-monitoredObjects:
-  18907678:
-    interval: 86400 # 1 day
-    sensors: [340414062, 410164038, 800014050]
-
-  18907677:
-    interval: 86400 # 1 day
-    sensors: [340414062, 410164038, 800014050]
-
-  2129992:
-    interval: 86400 # 1 day
-
-#  4280003:
-#    interval: 86400
-
-  4640825685:
-    interval: 86400 # 1 day
-    sensors: [850010000, 850020000, 850030000]
-
-  4638425647:
-    interval: 86400 # 1 day
-    sensors: [850010000, 850020000, 850030000 ]

+ 0 - 105
config/new_example.yaml

@@ -1,105 +0,0 @@
-emailServers:
-  exampleEmailServer:
-    smtpHost: "<smtp_server>"
-    smtpPort: 465
-    authUsername: "username"
-    authPassword: "password"
-
-messageBrokers:
-  emailToAll:
-    type: EMAIL
-    config:
-      server: exampleEmailServer
-      senderEmail: "from@example.org"
-      recipientEmail: "to@example.org"
-      subject: "[watchdog] Example Report"
-  emailToTeam:
-    type: EMAIL
-    config:
-      server: exampleEmailServer
-      senderEmail: "from@example.org"
-      recipientEmail: "to@example.org"
-      subject: "[watchdog] Example Report"
-  signalEmergency:
-    type: SIGNAL
-    config:
-      recipientNumber: "+420 123 456 789"
-      senderNumber: "+420 123 456 789"
-      messagePattern: "No actual data from: $unit_id/$sensor_id"  # available props: $unit_id, $sensor_id, $timestamp, $value
-
-dataProviders:
-  wsServer1:
-    type: WEB_SERVICE
-    config:
-      baseUrl: "<domain_url>"
-  wsServer2:
-    type: WEB_SERVICE
-    config:
-      baseUrl: "<domain_url>"
-  dbServer:
-    type: DATABASE
-    config:
-      url: "<jdbc_url>"
-      username: "<username>"
-      password: "<password>"
-      connectionPoolSize: 6
-      groupName: "<group_name>"
-
-groups:
-  group1Checker:
-    dataProvider: wsServer1
-    messageBroker: emailToTeam
-    resultType: ALL
-    period: 86400
-  group2Checker:
-    dataProvider: dbServer
-    messageBroker: emailToTeam
-    resultType: ALL
-    period: 86400
-  groupRealTime:
-    dataProvider: wsServer1
-    messageBroker: signalEmergency
-    resultType: FAIL
-
-senslogGroups:
-  senslogGAdmin:
-    dataProvider: wsServer1
-    messageBroker: emailToAll
-    resultType: FAIL
-    period: 86400
-    senslogGroups: [ "admin", "...." ]
-
-superGroups:
-  sumarizeError:
-    messageBroker: emailToAll
-    resultType: FAIL
-    period: 86400
-    groups: [ group1Checker, group2Checker ]
-
-monitoredObjects:
-  unit_id_1:
-    groups: [group1Checker, group2Checker]
-    period: 1440
-
-  unit_id_2:
-    period: 1440
-    groups: [groupRealTime]
-    sensors: [210000000, 220000000]
-
-  unit_id_3:
-    period: 1440
-    groups: [groupRealTime]
-    sensors:
-      310000000:
-        groups: [group1Checker]
-      320000000:
-        period: 2880
-
-  unit_id_4:
-    sensors:
-      410000000:
-        period: 2880
-        groups: [group1Checker]
-      420000000:
-        period: 1440
-        groups: [group1Checker]

+ 2 - 2
docker/start.sh

@@ -1,7 +1,7 @@
 #!/bin/sh
 
-BUILD_FOLDER="bin"
+BUILD_FOLDER="./build/libs"
 MAIN_CLASS="cz.senslog.watchdog.app.Main"
 LOG_PATH="/var/log/watchdog-app"
 
-java -cp "$BUILD_FOLDER/*" -DlogPath=$LOG_PATH $MAIN_CLASS $APP_PARAMS
+java -cp "$BUILD_FOLDER/*" -DlogPath=$LOG_PATH $MAIN_CLASS $APP_PARAMS

+ 3 - 0
src/main/java/cz/senslog/watchdog/app/Application.java

@@ -64,6 +64,9 @@ public class Application extends Thread {
                 config.getDataProviderConfigs()
         );
 
+        // config.getExecutableGroups().forEach(System.out::println);
+
+
         LocalDateTime now = LocalDateTime.now();
         Scheduler.SchedulerBuilder schedulerBuilder = Scheduler.createBuilder();
         for (ExecutableGroup exeGroup : config.getExecutableGroups()) {

+ 65 - 36
src/main/java/cz/senslog/watchdog/app/Watcher.java

@@ -47,51 +47,80 @@ public class Watcher {
         List<SimpleReport> reports = new ArrayList<>();
         List<String> reportedMessages = new ArrayList<>(data.getErrorMessages());
 
-        for (String unitId : group.getKeys()) {
-            if (!data.containsNode(unitId)) {
-                reportedMessages.add(String.format("No data for: unit_id - %s", unitId)); continue;
-            }
-            Node<String, MonitoredObject> mUnitNode = group.getNode(unitId);
-            Node<String, ProvidedObject> pUnitNode = data.getNode(unitId);
-            String unitName = pUnitNode.getValue().getName();
-            for (MonitoredObject mSensor : mUnitNode.getValues()) {
-                int period = mSensor.getPeriod();
-                Instant minTimestamp = now.minusSeconds(period);
-                Collection<ProvidedObject> providedObjects = mSensor instanceof AllMonitoredObjects ?
-                        pUnitNode.getValues() : pUnitNode.containsKey(mSensor.getId()) ?
+        if (!data.isEmpty()) {
+            for (String unitId : group.getKeys()) {
+                Node<String, MonitoredObject> mUnitNode = group.getNode(unitId);
+                if (mUnitNode.getValue() instanceof AllMonitoredObjects) {
+                    // ALL UNITS
+                    int period = mUnitNode.getValue().getPeriod();
+                    Instant minTimestamp = now.minusSeconds(period);
+                    for (String pUnitId : data.getKeys()) {
+                        Node<String, ProvidedObject> pUnitNode = data.getNode(pUnitId);
+                        String unitName = pUnitNode.getValue().getName();
+                        for (ProvidedObject pObject : pUnitNode.getValues()) {
+                            SimpleReport simpleReport = new SimpleReport(new ObservationInfo(
+                                    new Unit(Long.parseLong(pUnitId), unitName),
+                                    new Sensor(Long.parseLong(pObject.getId()), pObject.getName()),
+                                    pObject.getTimestamp()
+                            ),
+                                    pObject.getTimestamp().toInstant().isBefore(minTimestamp) ? FAIL : OK
+                            );
+
+                            if (isAllowedToReport(simpleReport)) {
+                                reports.add(simpleReport);
+                            }
+                        }
+                    }
+                } else if (!data.containsNode(unitId)) {
+                    reportedMessages.add(String.format("No data for: unit_id - %s", unitId));
+                } else {
+                    Node<String, ProvidedObject> pUnitNode = data.getNode(unitId);
+                    String unitName = pUnitNode.getValue().getName();
+                    for (MonitoredObject mSensor : mUnitNode.getValues()) {
+                        int period = mSensor.getPeriod();
+                        Instant minTimestamp = now.minusSeconds(period);
+                        Collection<ProvidedObject> providedObjects = mSensor instanceof AllMonitoredObjects ?
+                                pUnitNode.getValues() : pUnitNode.containsKey(mSensor.getId()) ?
                                 singletonList(pUnitNode.getNode(mSensor.getId()).getValue()) : emptyList();
 
-                if (providedObjects.isEmpty()) {
-                    reports.add(new SimpleReport(new ObservationInfo(
-                            new Unit(Long.parseLong(unitId), unitName),
-                            new Sensor(Long.parseLong(mSensor.getId()), "unknown"),
-                            null
-                    ),
-                            NO_DATA
-                    ));
-                }
-
-                for (ProvidedObject pObject : providedObjects) {
-                    SimpleReport simpleReport = new SimpleReport(new ObservationInfo(
-                            new Unit(Long.parseLong(unitId), unitName),
-                            new Sensor(Long.parseLong(pObject.getId()), pObject.getName()),
-                            pObject.getTimestamp()
-                    ),
-                            pObject.getTimestamp().toInstant().isBefore(minTimestamp) ? FAIL : OK
-                    );
-
-                    if (isAllowedToReport(simpleReport)) {
-                        reports.add(simpleReport);
+                        if (providedObjects.isEmpty()) {
+                            reports.add(new SimpleReport(new ObservationInfo(
+                                    new Unit(Long.parseLong(unitId), unitName),
+                                    new Sensor(Long.parseLong(mSensor.getId()), "unknown"),
+                                    null
+                            ),
+                                    NO_DATA
+                            ));
+                        }
+
+                        for (ProvidedObject pObject : providedObjects) {
+                            SimpleReport simpleReport = new SimpleReport(new ObservationInfo(
+                                    new Unit(Long.parseLong(unitId), unitName),
+                                    new Sensor(Long.parseLong(pObject.getId()), pObject.getName()),
+                                    pObject.getTimestamp()
+                            ),
+                                    pObject.getTimestamp().toInstant().isBefore(minTimestamp) ? FAIL : OK
+                            );
+
+                            if (isAllowedToReport(simpleReport)) {
+                                reports.add(simpleReport);
+                            }
+                        }
                     }
                 }
             }
+        } else {
+            reportedMessages.add("An error has occurred. No data to check.");
         }
 
-        messageBroker.send(new Report(ofInstant(now, ZoneId.systemDefault()), reports, reportedMessages), status -> {
+        Map<String, String> operationProperties = new HashMap<>();
+        operationProperties.put("Group name", group.getConfig().getName());
+
+        messageBroker.send(new Report(ofInstant(now, ZoneId.systemDefault()), reports, reportedMessages, operationProperties), status -> {
             String brokerType = messageBroker.getType().name().toLowerCase();
             if (status.isSuccess()) {
-                logger.info("The report at '{}' was send via '{}' broker successfully.",
-                        status.getReport().getCreated(), brokerType
+                logger.info("The report at '{}' was send via '{}' broker successfully for the group's name '{}'.",
+                        status.getReport().getCreated(), brokerType, group.getConfig().getName()
                 );
             } else {
                 logger.error("Can not send a message '{}' via '{}' broker because of '{}'.",

+ 5 - 0
src/main/java/cz/senslog/watchdog/config/AllMonitoredObjects.java

@@ -5,4 +5,9 @@ public class AllMonitoredObjects extends MonitoredObject {
     public AllMonitoredObjects(Integer period) {
         super("__all", period);
     }
+
+    @Override
+    public String toString() {
+        return "A(" + (getPeriod() != null ? Integer.toString(getPeriod()) : "null") + ")";
+    }
 }

+ 13 - 24
src/main/java/cz/senslog/watchdog/config/Configuration.java

@@ -43,7 +43,6 @@ public class Configuration {
             Map<String, MessageBrokerConfig> messageBrokers,
             Map<String, DataProviderConfig> dataProviders,
             Map<String, GroupConfig> groups,
-            Map<String, SensLogGroupConfig> sensLogGroups,
             Map<String, SuperGroupConfig> superGroups
     ) {
 
@@ -93,15 +92,23 @@ public class Configuration {
                     );
 
                     MonitoredObject sensorMObj = sensor.id != null ? new MonitoredObject(sensor.id, period) : new AllMonitoredObjects(period);
-                    executableGroup.swapPeriod(period);
+
+                    executableGroup.swapPeriod(sensorMObj.getPeriod());
                     executableGroup.computeIfAbsent(mObject.id, MonitoredObject::new)
                             .addNode(sensorMObj.getId(), sensorMObj);
                 }
             }
         }
 
-        for (SensLogGroupConfig sensLogGroup : sensLogGroups.values()) {
-            executableGroupsMap.put(sensLogGroup.getId(), new ExecutableGroup(sensLogGroup));
+        for (Map.Entry<String, GroupConfig> groupEntry : groups.entrySet()) {
+            String groupId = groupEntry.getKey();
+            GroupConfig groupConfig = groupEntry.getValue();
+            if (!executableGroupsMap.containsKey(groupId)) {
+                MonitoredObject allSensors = new AllMonitoredObjects(groupConfig.getPeriod());
+                executableGroupsMap.computeIfAbsent(groupId, k -> new ExecutableGroup(groupConfig))
+                        .computeIfAbsent(groupId, k -> new AllMonitoredObjects(groupConfig.getPeriod()))
+                        .addNode(allSensors.getId(), allSensors);
+            }
         }
 
         Map<String, SuperGroup> executableSGroupsMap = new HashMap<>();
@@ -170,7 +177,6 @@ public class Configuration {
                     parseMessageBrokers(createPropertyConfig(properties, "messageBrokers")),
                     parseDataProviders(createPropertyConfig(properties, "dataProviders")),
                     parseGroups(createPropertyConfig(properties, "groups")),
-                    parseSensLogGroups(createPropertyConfig(properties, "senslogGroups")),
                     parseSuperGroups(createPropertyConfig(properties, "superGroups"))
             );
         } catch (IOException e) {
@@ -224,6 +230,7 @@ public class Configuration {
         for (String id : groupIds) {
             PropertyConfig groupConfig = config.getPropertyConfig(id);
             groups.put(id, new GroupConfig(id,
+                    groupConfig.getStringProperty("name"),
                     groupConfig.getStringProperty("dataProvider"),
                     groupConfig.getStringProperty("messageBroker"),
                     ResultType.of(groupConfig.getStringProperty("resultType")),
@@ -242,25 +249,7 @@ public class Configuration {
             List<String> subGroupList = groupConfig.getArrayPropertyOf("groups", String.class);
             Set<String> subGroupNames = new HashSet<>(subGroupList);
             groups.put(id, new SuperGroupConfig(id,
-                    groupConfig.getStringProperty("messageBroker"),
-                    ResultType.of(groupConfig.getStringProperty("resultType")),
-                    groupConfig.getOptionalProperty("period", Integer.class).orElse(null),
-                    subGroupNames
-            ));
-        }
-        return groups;
-    }
-
-    private static Map<String, SensLogGroupConfig> parseSensLogGroups(PropertyConfig config) {
-        Set<String> groupIds = config.getAttributes();
-        Map<String, SensLogGroupConfig> groups = new HashMap<>(groupIds.size());
-        for (String id : groupIds) {
-            PropertyConfig groupConfig = config.getPropertyConfig(id);
-
-            List<String> subGroupList = groupConfig.getArrayPropertyOf("groups", String.class);
-            Set<String> subGroupNames = new HashSet<>(subGroupList);
-            groups.put(id, new SensLogGroupConfig(id,
-                    groupConfig.getStringProperty("dataProvider"),
+                    groupConfig.getStringProperty("name"),
                     groupConfig.getStringProperty("messageBroker"),
                     ResultType.of(groupConfig.getStringProperty("resultType")),
                     groupConfig.getOptionalProperty("period", Integer.class).orElse(null),

+ 1 - 1
src/main/java/cz/senslog/watchdog/config/DataProviderType.java

@@ -4,7 +4,7 @@ import java.util.function.BiFunction;
 
 public enum DataProviderType {
     DATABASE        (DatabaseDataProviderConfig::create),
-    WEB_SERVICE     (WebServiceDataProviderConfig::create)
+    WEB_SERVICE     (WSSensLogDataProviderConfig::create)
 
     ;
     private final BiFunction<String, PropertyConfig, DataProviderConfig> fnc;

+ 1 - 1
src/main/java/cz/senslog/watchdog/config/ExecutableGroup.java

@@ -28,7 +28,7 @@ public class ExecutableGroup extends Graph<String, MonitoredObject> {
     }
 
     public GroupConfig getConfig() {
-        return new GroupConfig(config.getId(), config.getDataProviderId(),
+        return new GroupConfig(config.getId(), config.getName(), config.getDataProviderId(),
                 config.getMessageBrokerId(), config.getResultType(), root.getPeriod()
         );
     }

+ 7 - 1
src/main/java/cz/senslog/watchdog/config/GroupConfig.java

@@ -5,13 +5,15 @@ import java.util.Objects;
 public class GroupConfig {
 
     private final String id;
+    private final String name;
     private final String dataProviderId;
     private final String messageBrokerId;
     private final ResultType resultType;
     private final Integer period;
 
-    public GroupConfig(String id, String dataProviderId, String messageBrokerId, ResultType resultType, Integer period) {
+    public GroupConfig(String id, String name, String dataProviderId, String messageBrokerId, ResultType resultType, Integer period) {
         this.id = id;
+        this.name = name;
         this.dataProviderId = dataProviderId;
         this.messageBrokerId = messageBrokerId;
         this.resultType = resultType;
@@ -38,6 +40,10 @@ public class GroupConfig {
         return period;
     }
 
+    public String getName() {
+        return name;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;

+ 1 - 1
src/main/java/cz/senslog/watchdog/config/MonitoredObject.java

@@ -28,6 +28,6 @@ public class MonitoredObject {
 
     @Override
     public String toString() {
-        return period != null ? Integer.toString(period) : "null";
+        return "S(" + (period != null ? Integer.toString(period) : "null") + ")";
     }
 }

+ 0 - 17
src/main/java/cz/senslog/watchdog/config/SensLogGroupConfig.java

@@ -1,17 +0,0 @@
-package cz.senslog.watchdog.config;
-
-import java.util.Set;
-
-public class SensLogGroupConfig extends GroupConfig {
-
-    private final Set<String> groups;
-
-    public SensLogGroupConfig(String id, String dataProviderId, String messageBrokerId, ResultType resultType, Integer period, Set<String> groups) {
-        super(id, dataProviderId, messageBrokerId, resultType, period);
-        this.groups = groups;
-    }
-
-    public Set<String> getGroups() {
-        return groups;
-    }
-}

+ 2 - 2
src/main/java/cz/senslog/watchdog/config/SuperGroupConfig.java

@@ -6,8 +6,8 @@ public class SuperGroupConfig extends GroupConfig {
 
     private final Set<String> groups;
 
-    public SuperGroupConfig(String id, String messageBrokerId, ResultType resultType, Integer period, Set<String> groups) {
-        super(id, null, messageBrokerId, resultType, period);
+    public SuperGroupConfig(String id, String name, String messageBrokerId, ResultType resultType, Integer period, Set<String> groups) {
+        super(id, name,null, messageBrokerId, resultType, period);
         this.groups = groups;
     }
 

+ 12 - 13
src/main/java/cz/senslog/watchdog/config/WebServiceDataProviderConfig.java → src/main/java/cz/senslog/watchdog/config/WSSensLogDataProviderConfig.java

@@ -1,36 +1,35 @@
 package cz.senslog.watchdog.config;
 
-public class WebServiceDataProviderConfig extends DataProviderConfig {
+public class WSSensLogDataProviderConfig extends DataProviderConfig {
 
     private final String baseUrl;
-
-    private final String userName;
     private final String groupName;
+    private final String userName;
 
-    public static WebServiceDataProviderConfig create(String id, PropertyConfig config) {
-        return new WebServiceDataProviderConfig(id,
+    public static WSSensLogDataProviderConfig create(String id, PropertyConfig config) {
+        return new WSSensLogDataProviderConfig(id,
                 config.getStringProperty("baseUrl"),
-                config.getStringProperty("user"),
-                config.getStringProperty("group")
+                config.getStringProperty("groupName"),
+                config.getStringProperty("userName")
         );
     }
 
-    public WebServiceDataProviderConfig(String id, String baseUrl, String userName, String groupName) {
+    public WSSensLogDataProviderConfig(String id, String baseUrl, String groupName, String userName) {
         super(id, DataProviderType.WEB_SERVICE);
         this.baseUrl = baseUrl;
-        this.userName = userName;
         this.groupName = groupName;
+        this.userName = userName;
     }
 
     public String getBaseUrl() {
         return baseUrl;
     }
 
-    public String getUserName() {
-        return userName;
-    }
-
     public String getGroupName() {
         return groupName;
     }
+
+    public String getUserName() {
+        return userName;
+    }
 }

+ 7 - 7
src/main/java/cz/senslog/watchdog/core/DataProviderInstanceCreator.java

@@ -1,17 +1,17 @@
 package cz.senslog.watchdog.core;
 
 import cz.senslog.watchdog.config.DatabaseDataProviderConfig;
-import cz.senslog.watchdog.config.WebServiceDataProviderConfig;
-import cz.senslog.watchdog.provider.database.DatabaseDataProvider;
-import cz.senslog.watchdog.provider.ws.WebServiceDataProvider;
+import cz.senslog.watchdog.config.WSSensLogDataProviderConfig;
+import cz.senslog.watchdog.provider.database.DBDataProvider;
+import cz.senslog.watchdog.provider.ws.WSSensLogDataProvider;
 
 public class DataProviderInstanceCreator implements InstanceCreator {
 
-    DatabaseDataProvider create(DatabaseDataProviderConfig config) {
-        return new DatabaseDataProvider(null);
+    DBDataProvider create(DatabaseDataProviderConfig config) {
+        return new DBDataProvider(null);
     }
 
-    WebServiceDataProvider create(WebServiceDataProviderConfig config) {
-        return new WebServiceDataProvider(null);
+    WSSensLogDataProvider create(WSSensLogDataProviderConfig config) {
+        return new WSSensLogDataProvider(null);
     }
 }

+ 8 - 1
src/main/java/cz/senslog/watchdog/domain/Report.java

@@ -2,17 +2,20 @@ package cz.senslog.watchdog.domain;
 
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 
 public class Report {
 
     private final LocalDateTime created;
     private final List<SimpleReport> reports;
     private final List<String> messages;
+    private final Map<String, String> operationProperties;
 
-    public Report(LocalDateTime created, List<SimpleReport> reports, List<String> messages) {
+    public Report(LocalDateTime created, List<SimpleReport> reports, List<String> messages, Map<String, String> operationProperties) {
         this.created = created;
         this.reports = reports;
         this.messages = messages;
+        this.operationProperties = operationProperties;
     }
 
     public LocalDateTime getCreated() {
@@ -26,4 +29,8 @@ public class Report {
     public List<String> getMessages() {
         return messages;
     }
+
+    public Map<String, String> getOperationProperties() {
+        return operationProperties;
+    }
 }

+ 15 - 0
src/main/java/cz/senslog/watchdog/messagebroker/broker/EmailMessageBroker.java

@@ -38,6 +38,21 @@ public class EmailMessageBroker implements MessageBroker {
         boolean isMessages = !report.getMessages().isEmpty();
         boolean isRecords = !report.getReports().isEmpty();
 
+        if (!report.getOperationProperties().isEmpty()) {
+
+            TableWriter tableSourceWriter = HtmlTableWriter.createWithHeader("width: 100%;", "background-color: #dddddd")
+                    .cell("Operation Type").cell("Operation Value").end();
+
+            for (Map.Entry<String, String> operationEntry : report.getOperationProperties().entrySet()) {
+                tableSourceWriter.row(rowStyle)
+                            .cell(operationEntry.getKey(), rowStyle)
+                            .cell(operationEntry.getValue(), rowStyle)
+                        .end();
+            }
+
+            content.append(tableSourceWriter.table()).append(BREAK_LINE);
+        }
+
         if (isMessages || !isRecords) {
             TableWriter tableMsgWriter = HtmlTableWriter.createWithHeader("width: 100%;", "background-color: #dddddd")
                     .cell("Messages").end();

+ 0 - 4
src/main/java/cz/senslog/watchdog/provider/DataProvider.java

@@ -1,10 +1,6 @@
 package cz.senslog.watchdog.provider;
 
-import java.util.List;
-
 public interface DataProvider {
 
-    List<Record> getLastRecords();
-
     ProvidedData getLastData();
 }

+ 6 - 6
src/main/java/cz/senslog/watchdog/provider/DataProviderManager.java

@@ -2,9 +2,9 @@ package cz.senslog.watchdog.provider;
 
 import cz.senslog.watchdog.config.DataProviderConfig;
 import cz.senslog.watchdog.config.DatabaseDataProviderConfig;
-import cz.senslog.watchdog.config.WebServiceDataProviderConfig;
-import cz.senslog.watchdog.provider.database.DatabaseDataProvider;
-import cz.senslog.watchdog.provider.ws.WebServiceDataProvider;
+import cz.senslog.watchdog.config.WSSensLogDataProviderConfig;
+import cz.senslog.watchdog.provider.database.DBDataProvider;
+import cz.senslog.watchdog.provider.ws.WSSensLogDataProvider;
 
 import java.util.Collection;
 import java.util.HashMap;
@@ -22,12 +22,12 @@ public class DataProviderManager {
             String id = config.getId();
             switch (config.getType()) {
                 case WEB_SERVICE: {
-                    WebServiceDataProviderConfig wsConfig = (WebServiceDataProviderConfig) config;
-                    instances.put(id, new WebServiceDataProvider(wsConfig));
+                    WSSensLogDataProviderConfig wsConfig = (WSSensLogDataProviderConfig) config;
+                    instances.put(id, new WSSensLogDataProvider(wsConfig));
                 } break;
                 case DATABASE: {
                     DatabaseDataProviderConfig dbConfig = (DatabaseDataProviderConfig) config;
-                    instances.put(id, new DatabaseDataProvider(dbConfig));
+                    instances.put(id, new DBDataProvider(dbConfig));
                 } break;
                 default: throw new IllegalStateException(
                         "Data provider for the type of '"+config.getType()+"' is not implemented yet"

+ 4 - 0
src/main/java/cz/senslog/watchdog/provider/ProvidedData.java

@@ -22,4 +22,8 @@ public class ProvidedData extends Graph<String, ProvidedObject> {
     public List<String> getErrorMessages() {
         return errorMessages;
     }
+
+    public boolean isEmpty() {
+        return getKeys().isEmpty();
+    }
 }

+ 3 - 8
src/main/java/cz/senslog/watchdog/provider/database/DatabaseDataProvider.java → src/main/java/cz/senslog/watchdog/provider/database/DBDataProvider.java

@@ -13,12 +13,12 @@ import java.util.List;
 
 import static cz.senslog.watchdog.config.DataProviderType.DATABASE;
 
-public class DatabaseDataProvider implements DataProvider {
+public class DBDataProvider implements DataProvider {
 
     private final SensLogRepository repository;
     private final String groupName;
 
-    public DatabaseDataProvider(DatabaseDataProviderConfig config) {
+    public DBDataProvider(DatabaseDataProviderConfig config) {
         Connection<Jdbi> connection = Connection.create(
                 config.getConnectionUrl(), config.getUsername(), config.getPassword(), config.getConnectionPoolSize()
         );
@@ -27,13 +27,8 @@ public class DatabaseDataProvider implements DataProvider {
     }
 
     @Override
-    public List<Record> getLastRecords() {
-        List<ObservationInfo> lastObservations = repository.getLastObservations(groupName);
-        return new ArrayList<>(lastObservations);
-    }
-
-    @Override
     public ProvidedData getLastData() {
+        List<ObservationInfo> lastObservations = repository.getLastObservations(groupName);
         return new ProvidedData(new ProviderInfo("db", DATABASE, false), new ArrayList<>());
     }
 }

+ 18 - 44
src/main/java/cz/senslog/watchdog/provider/ws/WebServiceDataProvider.java → src/main/java/cz/senslog/watchdog/provider/ws/WSSensLogDataProvider.java

@@ -1,11 +1,8 @@
 package cz.senslog.watchdog.provider.ws;
 
 import com.google.gson.reflect.TypeToken;
-import cz.senslog.watchdog.config.WebServiceDataProviderConfig;
-import cz.senslog.watchdog.domain.Sensor;
-import cz.senslog.watchdog.domain.Unit;
+import cz.senslog.watchdog.config.WSSensLogDataProviderConfig;
 import cz.senslog.watchdog.provider.*;
-import cz.senslog.watchdog.domain.ObservationInfo;
 import cz.senslog.watchdog.util.Tuple;
 import cz.senslog.watchdog.util.http.HttpClient;
 import cz.senslog.watchdog.util.http.HttpRequest;
@@ -24,9 +21,9 @@ import static cz.senslog.watchdog.util.json.BasicJson.jsonToObject;
 import static java.time.format.DateTimeFormatter.ofPattern;
 import static java.util.Collections.*;
 
-public class WebServiceDataProvider implements DataProvider {
+public class WSSensLogDataProvider implements DataProvider {
 
-    private static final Logger logger = LogManager.getLogger(WebServiceDataProvider.class);
+    private static final Logger logger = LogManager.getLogger(WSSensLogDataProvider.class);
 
     private static final String ERROR_KEY = "__error";
 
@@ -36,13 +33,12 @@ public class WebServiceDataProvider implements DataProvider {
     private static final DateTimeFormatter TIMESTAMP_PATTERN = ofPattern("yyyy-MM-dd HH:mm:ssX");
 
     private final HttpClient httpClient = HttpClient.newHttpClient();
-    private final WebServiceDataProviderConfig config;
+    private final WSSensLogDataProviderConfig config;
 
-    public WebServiceDataProvider(WebServiceDataProviderConfig config) {
+    public WSSensLogDataProvider(WSSensLogDataProviderConfig config) {
         this.config = config;
     }
 
-
     /* Map<unitId, Tuple<unitName, Map<sensorId, sensorName>>> */
     private Map<String, Tuple<String, Map<String, String>>> loadUnitsInfo() {
         HttpRequest request = HttpRequest.newBuilder().GET()
@@ -122,31 +118,8 @@ public class WebServiceDataProvider implements DataProvider {
     }
 
     @Override
-    public List<Record> getLastRecords() {
-
-        // Map<unitId, Tuple<unitName, Map<sensorId, sensorName>>>
-        Map<String, Tuple<String, Map<String, String>>> unitsInfo = loadUnitsInfo();
-        List<Map<String, Object>> lastObservations = loadLastObservations();
-
-        List<Record> observations = new ArrayList<>(lastObservations.size());
-        for (Map<String, Object> obMap : lastObservations) {
-
-            String unitId = obMap.getOrDefault("unitId", "").toString();
-            String sensorId = obMap.getOrDefault("sensorId", "").toString();
-            OffsetDateTime timestamp = OffsetDateTime.parse(obMap.get("timeStamp").toString(), TIMESTAMP_PATTERN);
-
-            Tuple<String, Map<String, String>> unitInfo = unitsInfo.getOrDefault(unitId, DEFAULT_UNIT_INFO);
-            Unit unit = new Unit(Long.parseLong(unitId), unitInfo.getItem1());
-            Sensor sensor = new Sensor(Long.parseLong(sensorId), unitInfo.getItem2().getOrDefault(sensorId, DEFAULT_NAME));
-            observations.add(new ObservationInfo(unit, sensor, timestamp));
-        }
-        return observations;
-    }
-
-    @Override
     public ProvidedData getLastData() {
 
-        // Map<unitId, Tuple<unitName, Map<sensorId, sensorName>>>
         Map<String, Tuple<String, Map<String, String>>> unitsInfo = loadUnitsInfo();
         List<Map<String, Object>> lastObservations = loadLastObservations();
 
@@ -163,21 +136,22 @@ public class WebServiceDataProvider implements DataProvider {
         String source = String.format("%s: %s", config.getId(), config.getBaseUrl());
         ProvidedData providedData = new ProvidedData(new ProviderInfo(source, WEB_SERVICE, isServerAlive), errorMessages);
 
-        for (Map<String, Object> obMap : lastObservations) {
-            long unitId = ((Double) obMap.get("unitId")).longValue();
-            long sensorId = ((Double) obMap.get("sensorId")).longValue();
-            OffsetDateTime timestamp = OffsetDateTime.parse(obMap.get("timeStamp").toString(), TIMESTAMP_PATTERN);
-
-            String unitIdStr = String.format("%d", unitId);
-            String sensorIdStr = String.format("%d", sensorId);
+        if (isServerAlive) {
+            for (Map<String, Object> obMap : lastObservations) {
+                long unitId = ((Double) obMap.get("unitId")).longValue();
+                long sensorId = ((Double) obMap.get("sensorId")).longValue();
+                OffsetDateTime timestamp = OffsetDateTime.parse(obMap.get("timeStamp").toString(), TIMESTAMP_PATTERN);
 
-            Tuple<String, Map<String, String>> unitInfo = unitsInfo.getOrDefault(unitIdStr, DEFAULT_UNIT_INFO);
-            String unitName = unitInfo.getItem1();
-            String sensorName = unitInfo.getItem2().getOrDefault(sensorIdStr, DEFAULT_NAME);
+                String unitIdStr = String.format("%d", unitId);
+                String sensorIdStr = String.format("%d", sensorId);
 
-            providedData.computeIfAbsent(unitIdStr, k -> new ProvidedObject(k, unitName, null))
-                    .addNode(sensorIdStr, new ProvidedObject(sensorIdStr, sensorName, timestamp));
+                Tuple<String, Map<String, String>> unitInfo = unitsInfo.getOrDefault(unitIdStr, DEFAULT_UNIT_INFO);
+                String unitName = unitInfo.getItem1();
+                String sensorName = unitInfo.getItem2().getOrDefault(sensorIdStr, DEFAULT_NAME);
 
+                providedData.computeIfAbsent(unitIdStr, k -> new ProvidedObject(k, unitName, null))
+                        .addNode(sensorIdStr, new ProvidedObject(sensorIdStr, sensorName, timestamp));
+            }
         }
 
         return providedData;

+ 0 - 14
src/main/java/cz/senslog/watchdog/util/http/HttpClient.java

@@ -49,20 +49,6 @@ public class HttpClient {
         return new HttpClient(HttpClientBuilder.create());
     }
 
-    public static HttpClient newHttpSSLClient() {
-        try {
-            SSLContextBuilder builder = new SSLContextBuilder();
-            builder.loadTrustMaterial(null, (TrustStrategy) (chain, authType) -> true);
-
-            SSLConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(builder.build(),
-                    SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
-            return new HttpClient(HttpClientBuilder.create().setSSLSocketFactory(sslSF));
-
-        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
-            return null;
-        }
-    }
-
     /**
      * Private constructors sets http client.
      */