diff --git a/arduino/HalMultiSensor/HalConfiguration.h b/arduino/HalMultiSensor/HalConfiguration.h
index 374981c5..4fbe1342 100755
--- a/arduino/HalMultiSensor/HalConfiguration.h
+++ b/arduino/HalMultiSensor/HalConfiguration.h
@@ -16,7 +16,7 @@
// TEMPERATURE SENSOR
#define TEMPERATURE_ENABLED // comment out to disable sensor
-#define TEMPERATURE_SENSOR SensorDHT(DHT11, 10)
+#define TEMPERATURE_SENSOR SensorDHT(DHT22, 10)
#define TEMPERATURE_PROTOCOL ProtocolOregon(11, DEVICE_BASE_ID + 2)
#define TEMPERATURE_TIMER_MULTIPLIER 10
diff --git a/resource/web/main_alerts.tmpl b/resource/web/main_alerts.tmpl
index 7eee7d3a..e6fdb466 100755
--- a/resource/web/main_alerts.tmpl
+++ b/resource/web/main_alerts.tmpl
@@ -5,7 +5,7 @@
×
- Error: {{.getMessage()}}
+ {{.getMessage()}}
{{/.isError()}}
{{#.isWarning()}}
@@ -14,7 +14,7 @@
×
- Warning: {{.getMessage()}}
+ {{.getMessage()}}
{{/.isWarning()}}
{{#.isSuccess()}}
@@ -23,7 +23,7 @@
×
- Success: {{.getMessage()}}
+ {{.getMessage()}}
{{/.isSuccess()}}
{{#.isInfo()}}
@@ -32,7 +32,7 @@
×
- Info: {{.getMessage()}}
+ {{.getMessage()}}
{{/.isInfo()}}
{{/alerts}}
diff --git a/src/se/hal/daemon/SensorDataAggregatorDaemon.java b/src/se/hal/daemon/SensorDataAggregatorDaemon.java
index 7bd9d1e1..5a6eb74e 100755
--- a/src/se/hal/daemon/SensorDataAggregatorDaemon.java
+++ b/src/se/hal/daemon/SensorDataAggregatorDaemon.java
@@ -91,39 +91,33 @@ public class SensorDataAggregatorDaemon implements HalDaemon {
DBConnection db = HalContext.getDB();
PreparedStatement stmt = null;
try {
-
- stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
- + " WHERE sensor_id == ?"
- + " AND timestamp_end-timestamp_start == ?");
- stmt.setLong(1, sensorId);
- switch(aggrPeriodLength){
- case SECOND: stmt.setLong(2, UTCTimeUtility.SECOND_IN_MS-1); break;
- case MINUTE: stmt.setLong(2, UTCTimeUtility.MINUTE_IN_MS-1); break;
- case FIVE_MINUTES: stmt.setLong(2, UTCTimeUtility.FIVE_MINUTES_IN_MS-1); break;
- case FIFTEEN_MINUTES: stmt.setLong(2, UTCTimeUtility.FIFTEEN_MINUTES_IN_MS-1); break;
- case HOUR: stmt.setLong(2, UTCTimeUtility.HOUR_IN_MS-1); break;
- case DAY: stmt.setLong(2, UTCTimeUtility.DAY_IN_MS-1); break;
- case WEEK: stmt.setLong(2, UTCTimeUtility.WEEK_IN_MS-1); break;
- default: logger.warning("aggregation period length is not supported."); return;
- }
- Long maxTimestampFoundForSensor = DBConnection.exec(stmt, new SimpleSQLResult());
- if(maxTimestampFoundForSensor == null)
- maxTimestampFoundForSensor = 0l;
+ Long maxAggrTimestampInDB = getLatestAggrTimestamp(db, sensor, aggrPeriodLength);
+ if(maxAggrTimestampInDB == null)
+ maxAggrTimestampInDB = 0l;
long latestCompletePeriodEndTimestamp = new UTCTimePeriod(aggregationStartTime, aggrPeriodLength).getPreviosPeriod().getEndTimestamp();
long oldestPeriodStartTimestamp = new UTCTimePeriod(aggregationStartTime-ageLimitInMs, aggrPeriodLength).getStartTimestamp();
-
- if(latestCompletePeriodEndTimestamp == maxTimestampFoundForSensor){
- logger.fine("no new data to evaluate - aggregation is up to date");
- // Check if the sensor has stopped responding
- if (maxTimestampFoundForSensor + sensor.getDeviceConfig().getDataInterval()*3 < System.currentTimeMillis()){
+
+ // Check if the sensor has stopped responding for 15 min or 3 times the data interval and alert the user
+ if (aggrPeriodLength == AggregationPeriodLength.FIVE_MINUTES) {
+ Long maxRawTimestampInDB = getLatestRawTimestamp(db, sensor);
+ long dataInterval = sensor.getDeviceConfig().getDataInterval();
+ if (dataInterval < UTCTimeUtility.FIVE_MINUTES_IN_MS)
+ dataInterval = UTCTimeUtility.FIVE_MINUTES_IN_MS;
+ if (maxRawTimestampInDB != null &&
+ maxRawTimestampInDB + (dataInterval * 3) < System.currentTimeMillis()) {
logger.fine("Sensor \"" + sensorId + "\" has stopped sending data");
- HalAlertManager.getInstance().addAlert(new HalAlert(AlertLevel.WARNING,
- "Sensor \""+sensor.getName()+"\" has stopped responding", AlertTTL.DISMISSED));
- }
+ HalAlertManager.getInstance().addAlert(new HalAlert(AlertLevel.WARNING,
+ "Sensor \"" + sensor.getName() + "\" has stopped responding " +
+ "since "+maxRawTimestampInDB+"", AlertTTL.DISMISSED));
+ }
+ }
+
+ if(latestCompletePeriodEndTimestamp == maxAggrTimestampInDB){
+ logger.fine("no new data to evaluate - aggregation is up to date");
return;
}else{
- logger.fine("evaluating period: "+ (maxTimestampFoundForSensor+1) + "=>" + latestCompletePeriodEndTimestamp + " (" + UTCTimeUtility.getDateString(maxTimestampFoundForSensor+1) + "=>" + UTCTimeUtility.getDateString(latestCompletePeriodEndTimestamp) + ") with expected sample count: " + expectedSampleCount);
+ logger.fine("evaluating period: "+ (maxAggrTimestampInDB+1) + "=>" + latestCompletePeriodEndTimestamp + " (" + UTCTimeUtility.getDateString(maxAggrTimestampInDB+1) + "=>" + UTCTimeUtility.getDateString(latestCompletePeriodEndTimestamp) + ") with expected sample count: " + expectedSampleCount);
}
stmt = db.getPreparedStatement("SELECT *, 1 AS confidence FROM sensor_data_raw"
@@ -133,7 +127,7 @@ public class SensorDataAggregatorDaemon implements HalDaemon {
+ " AND timestamp >= ? "
+" ORDER BY timestamp ASC");
stmt.setLong(1, sensorId);
- stmt.setLong(2, maxTimestampFoundForSensor);
+ stmt.setLong(2, maxAggrTimestampInDB);
stmt.setLong(3, latestCompletePeriodEndTimestamp);
stmt.setLong(4, oldestPeriodStartTimestamp);
DBConnection.exec(stmt, new DataAggregator(sensorId, aggrPeriodLength, expectedSampleCount, aggrMethod, aggregationStartTime));
@@ -141,7 +135,32 @@ public class SensorDataAggregatorDaemon implements HalDaemon {
logger.log(Level.SEVERE, null, e);
}
}
-
+
+ private Long getLatestAggrTimestamp(DBConnection db, Sensor sensor, AggregationPeriodLength aggrPeriodLength) throws SQLException {
+ PreparedStatement stmt = db.getPreparedStatement("SELECT MAX(timestamp_end) FROM sensor_data_aggr"
+ + " WHERE sensor_id == ?"
+ + " AND timestamp_end-timestamp_start == ?");
+ stmt.setLong(1, sensor.getId());
+ switch(aggrPeriodLength){
+ case SECOND: stmt.setLong(2, UTCTimeUtility.SECOND_IN_MS-1); break;
+ case MINUTE: stmt.setLong(2, UTCTimeUtility.MINUTE_IN_MS-1); break;
+ case FIVE_MINUTES: stmt.setLong(2, UTCTimeUtility.FIVE_MINUTES_IN_MS-1); break;
+ case FIFTEEN_MINUTES: stmt.setLong(2, UTCTimeUtility.FIFTEEN_MINUTES_IN_MS-1); break;
+ case HOUR: stmt.setLong(2, UTCTimeUtility.HOUR_IN_MS-1); break;
+ case DAY: stmt.setLong(2, UTCTimeUtility.DAY_IN_MS-1); break;
+ case WEEK: stmt.setLong(2, UTCTimeUtility.WEEK_IN_MS-1); break;
+ default:
+ throw new IllegalArgumentException("aggregation period length is not supported.");
+ }
+ return DBConnection.exec(stmt, new SimpleSQLResult());
+ }
+ private Long getLatestRawTimestamp(DBConnection db, Sensor sensor) throws SQLException {
+ PreparedStatement stmt = db.getPreparedStatement("SELECT MAX(timestamp) FROM sensor_data_raw WHERE sensor_id == ?");
+ stmt.setLong(1, sensor.getId());
+ return DBConnection.exec(stmt, new SimpleSQLResult());
+ }
+
+
/**
* Internal class for aggregating data to the aggregated DB table
*/
diff --git a/src/se/hal/page/HalAlertManager.java b/src/se/hal/page/HalAlertManager.java
index e71f0e80..1a2712a6 100755
--- a/src/se/hal/page/HalAlertManager.java
+++ b/src/se/hal/page/HalAlertManager.java
@@ -46,6 +46,7 @@ public class HalAlertManager implements HttpPage {
alerts.add(alert);
}
+
public Templator generateAlerts(){
try {
// clone alert list and update ttl of alerts
@@ -110,23 +111,19 @@ public class HalAlertManager implements HttpPage {
private int id;
private AlertLevel level;
private String msg;
- protected int ttl;
+ private int ttl;
public HalAlert(AlertLevel level, String msg, AlertTTL ttl) {
this.id = nextId++;
this.level = level;
this.msg = msg;
- switch (ttl){
- case ONE_VIEW: this.ttl = 1; break;
- case DISMISSED: this.ttl = Integer.MAX_VALUE; break;
- }
+ setTTL(ttl);
}
public int getId() {
return id;
}
-
public AlertLevel getLevel() {
return level;
}
@@ -134,11 +131,20 @@ public class HalAlertManager implements HttpPage {
public boolean isWarning(){ return level == AlertLevel.WARNING; }
public boolean isSuccess(){ return level == AlertLevel.SUCCESS; }
public boolean isInfo(){ return level == AlertLevel.INFO; }
-
public String getMessage() {
return msg;
}
+ public void setTTL(AlertTTL ttl){
+ switch (ttl){
+ case ONE_VIEW: this.ttl = 1; break;
+ case DISMISSED: this.ttl = Integer.MAX_VALUE; break;
+ }
+ }
+ public void dissmiss(){
+ ttl = -1;
+ }
+
@Override
public boolean equals(Object obj){
if (obj instanceof HalAlert)