Added data report interval so the null values in the graphs are specific to different protocols
This commit is contained in:
parent
3be4168cf2
commit
1983f3a55d
10 changed files with 76 additions and 21 deletions
|
|
@ -15,6 +15,6 @@ public interface HalEventData {
|
||||||
* This method needs to be implemented.
|
* This method needs to be implemented.
|
||||||
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
|
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
|
||||||
*/
|
*/
|
||||||
boolean equals(Object obj);
|
boolean equals(HalEventData obj);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,13 +14,26 @@ public interface HalSensorData {
|
||||||
|
|
||||||
double getData();
|
double getData();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the intended data reporting interval in milliseconds.
|
||||||
|
*/
|
||||||
|
long getDataInterval();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return which aggregation method that should be used to aggregate the reported data.
|
||||||
|
*/
|
||||||
AggregationMethod getAggregationMethod();
|
AggregationMethod getAggregationMethod();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the Controller class where SensorData should be registered on
|
||||||
|
*/
|
||||||
Class<? extends HalSensorController> getSensorController();
|
Class<? extends HalSensorController> getSensorController();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method needs to be implemented.
|
* NOTE: it should only static or unique data for the sensor type.
|
||||||
* NOTE: it should not compare data and timestamp, only static or unique data for the event type.
|
* This method is used to associate reported data with registered sensors
|
||||||
*/
|
*/
|
||||||
boolean equals(Object obj);
|
boolean equals(HalSensorData obj);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,13 @@ public class MapHttpPage extends HalHttpPage implements HalHttpPage.HalJsonPage
|
||||||
} else if (request.containsKey("bgimage")) {
|
} else if (request.containsKey("bgimage")) {
|
||||||
if (bgImage == null)
|
if (bgImage == null)
|
||||||
loadBgImage();
|
loadBgImage();
|
||||||
out.setHeader("Content-Type", "image/"+bgType);
|
if (bgImage == null)
|
||||||
out.setHeader("Content-Length", ""+bgImage.length);
|
out.setStatusCode(404);
|
||||||
out.write(bgImage);
|
else {
|
||||||
|
out.setHeader("Content-Type", "image/" + bgType);
|
||||||
|
out.setHeader("Content-Length", "" + bgImage.length);
|
||||||
|
out.write(bgImage);
|
||||||
|
}
|
||||||
} else { // Run default Hal behaviour
|
} else { // Run default Hal behaviour
|
||||||
super.respond(out, header, session, cookie, request);
|
super.respond(out, header, session, cookie, request);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,12 @@ public class NutUpsDevice implements PowerConsumptionSensorData{
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj){
|
public long getDataInterval(){
|
||||||
|
return 60*1000; // 1 min
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(HalSensorData obj){
|
||||||
if (obj instanceof NutUpsDevice)
|
if (obj instanceof NutUpsDevice)
|
||||||
return deviceId != null && deviceId.equals(((NutUpsDevice)obj).deviceId);
|
return deviceId != null && deviceId.equals(((NutUpsDevice)obj).deviceId);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
8
src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java
Normal file → Executable file
8
src/se/hal/plugin/raspberry/RPiPowerConsumptionSensor.java
Normal file → Executable file
|
|
@ -1,6 +1,7 @@
|
||||||
package se.hal.plugin.raspberry;
|
package se.hal.plugin.raspberry;
|
||||||
|
|
||||||
import se.hal.intf.HalSensorController;
|
import se.hal.intf.HalSensorController;
|
||||||
|
import se.hal.intf.HalSensorData;
|
||||||
import se.hal.struct.PowerConsumptionSensorData;
|
import se.hal.struct.PowerConsumptionSensorData;
|
||||||
import zutil.ui.Configurator;
|
import zutil.ui.Configurator;
|
||||||
|
|
||||||
|
|
@ -32,6 +33,11 @@ public class RPiPowerConsumptionSensor implements PowerConsumptionSensorData {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDataInterval(){
|
||||||
|
return 60*1000; // 1 min
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AggregationMethod getAggregationMethod() {
|
public AggregationMethod getAggregationMethod() {
|
||||||
return AggregationMethod.SUM;
|
return AggregationMethod.SUM;
|
||||||
|
|
@ -42,7 +48,7 @@ public class RPiPowerConsumptionSensor implements PowerConsumptionSensorData {
|
||||||
return RPiController.class;
|
return RPiController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj){
|
public boolean equals(HalSensorData obj){
|
||||||
if(!(obj instanceof RPiPowerConsumptionSensor))
|
if(!(obj instanceof RPiPowerConsumptionSensor))
|
||||||
return false;
|
return false;
|
||||||
return ((RPiPowerConsumptionSensor)obj).gpioPin == gpioPin;
|
return ((RPiPowerConsumptionSensor)obj).gpioPin == gpioPin;
|
||||||
|
|
|
||||||
8
src/se/hal/plugin/raspberry/RPiTemperatureSensor.java
Normal file → Executable file
8
src/se/hal/plugin/raspberry/RPiTemperatureSensor.java
Normal file → Executable file
|
|
@ -1,6 +1,7 @@
|
||||||
package se.hal.plugin.raspberry;
|
package se.hal.plugin.raspberry;
|
||||||
|
|
||||||
import se.hal.intf.HalSensorController;
|
import se.hal.intf.HalSensorController;
|
||||||
|
import se.hal.intf.HalSensorData;
|
||||||
import se.hal.struct.TemperatureSensorData;
|
import se.hal.struct.TemperatureSensorData;
|
||||||
import zutil.ui.Configurator;
|
import zutil.ui.Configurator;
|
||||||
|
|
||||||
|
|
@ -31,6 +32,11 @@ public class RPiTemperatureSensor implements TemperatureSensorData {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDataInterval() {
|
||||||
|
return 10*60*1000; // 10 min
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AggregationMethod getAggregationMethod() {
|
public AggregationMethod getAggregationMethod() {
|
||||||
return AggregationMethod.AVERAGE;
|
return AggregationMethod.AVERAGE;
|
||||||
|
|
@ -41,7 +47,7 @@ public class RPiTemperatureSensor implements TemperatureSensorData {
|
||||||
return RPiController.class;
|
return RPiController.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj){
|
public boolean equals(HalSensorData obj){
|
||||||
if(obj instanceof RPiTemperatureSensor)
|
if(obj instanceof RPiTemperatureSensor)
|
||||||
return obj == this;
|
return obj == this;
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,4 @@ public abstract class TellstickProtocol {
|
||||||
public abstract String encode();
|
public abstract String encode();
|
||||||
public abstract void decode(byte[] data);
|
public abstract void decode(byte[] data);
|
||||||
|
|
||||||
public abstract boolean equals(Object obj);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
package se.hal.plugin.tellstick.protocols;
|
package se.hal.plugin.tellstick.protocols;
|
||||||
|
|
||||||
|
import se.hal.intf.HalEventData;
|
||||||
import se.hal.plugin.tellstick.TellstickGroupProtocol;
|
import se.hal.plugin.tellstick.TellstickGroupProtocol;
|
||||||
import se.hal.plugin.tellstick.TellstickProtocol;
|
import se.hal.plugin.tellstick.TellstickProtocol;
|
||||||
import se.hal.struct.SwitchEventData;
|
import se.hal.struct.SwitchEventData;
|
||||||
|
|
@ -147,7 +148,7 @@ public class NexaSelfLearning extends TellstickProtocol
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj){
|
public boolean equals(HalEventData obj){
|
||||||
if(obj instanceof NexaSelfLearning)
|
if(obj instanceof NexaSelfLearning)
|
||||||
return ((NexaSelfLearning) obj).house == house &&
|
return ((NexaSelfLearning) obj).house == house &&
|
||||||
((NexaSelfLearning) obj).group == group &&
|
((NexaSelfLearning) obj).group == group &&
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package se.hal.plugin.tellstick.protocols;
|
package se.hal.plugin.tellstick.protocols;
|
||||||
|
|
||||||
|
import se.hal.intf.HalSensorData;
|
||||||
import se.hal.plugin.tellstick.TellstickProtocol;
|
import se.hal.plugin.tellstick.TellstickProtocol;
|
||||||
import se.hal.struct.PowerConsumptionSensorData;
|
import se.hal.struct.PowerConsumptionSensorData;
|
||||||
import zutil.log.LogUtil;
|
import zutil.log.LogUtil;
|
||||||
|
|
@ -15,15 +16,19 @@ public class Oregon0x1A2D extends TellstickProtocol implements PowerConsumptionS
|
||||||
|
|
||||||
@Configurator.Configurable("Address")
|
@Configurator.Configurable("Address")
|
||||||
private int address = 0;
|
private int address = 0;
|
||||||
|
@Configurator.Configurable("Report Interval(ms)")
|
||||||
|
private int interval = 60*1000; // default 1 min
|
||||||
|
|
||||||
private double temperature = 0;
|
private double temperature = 0;
|
||||||
private double humidity = 0;
|
private double humidity = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Oregon0x1A2D(){
|
public Oregon0x1A2D(){
|
||||||
super("oregon", "0x1A2D");
|
super("oregon", "0x1A2D");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String encode() {
|
public String encode() {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -63,7 +68,7 @@ public class Oregon0x1A2D extends TellstickProtocol implements PowerConsumptionS
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object obj){
|
public boolean equals(HalSensorData obj){
|
||||||
if(! (obj instanceof Oregon0x1A2D))
|
if(! (obj instanceof Oregon0x1A2D))
|
||||||
return false;
|
return false;
|
||||||
return ((Oregon0x1A2D)obj).address == this.address;
|
return ((Oregon0x1A2D)obj).address == this.address;
|
||||||
|
|
@ -90,6 +95,11 @@ public class Oregon0x1A2D extends TellstickProtocol implements PowerConsumptionS
|
||||||
return temperature;
|
return temperature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getDataInterval() {
|
||||||
|
return interval;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AggregationMethod getAggregationMethod() {
|
public AggregationMethod getAggregationMethod() {
|
||||||
return AggregationMethod.SUM;
|
return AggregationMethod.SUM;
|
||||||
|
|
|
||||||
|
|
@ -54,15 +54,23 @@ public class AggregateDataListSqlResult implements SQLResultHandler<ArrayList<Ag
|
||||||
default: throw new IllegalArgumentException("selected aggrPeriodLength is not supported");
|
default: throw new IllegalArgumentException("selected aggrPeriodLength is not supported");
|
||||||
}
|
}
|
||||||
stmt.setLong(4, (System.currentTimeMillis() - ageLimitInMs) );
|
stmt.setLong(4, (System.currentTimeMillis() - ageLimitInMs) );
|
||||||
return DBConnection.exec(stmt , new AggregateDataListSqlResult());
|
return DBConnection.exec(stmt , new AggregateDataListSqlResult(sensor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Sensor sensor;
|
||||||
|
|
||||||
|
private AggregateDataListSqlResult(Sensor sensor){
|
||||||
|
this.sensor = sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ArrayList<AggregateData> handleQueryResult(Statement stmt, ResultSet result) throws SQLException {
|
public ArrayList<AggregateData> handleQueryResult(Statement stmt, ResultSet result) throws SQLException {
|
||||||
ArrayList<AggregateData> list = new ArrayList<>();
|
ArrayList<AggregateData> list = new ArrayList<>();
|
||||||
long previousTimestampEnd = -1;
|
long previousTimestampEnd = -1;
|
||||||
while(result.next()){
|
while (result.next()){
|
||||||
|
|
||||||
int id = result.getInt("id");
|
int id = result.getInt("id");
|
||||||
long timestampStart = result.getLong("timestamp_start");
|
long timestampStart = result.getLong("timestamp_start");
|
||||||
|
|
@ -70,18 +78,22 @@ public class AggregateDataListSqlResult implements SQLResultHandler<ArrayList<Ag
|
||||||
String username = result.getString("username");
|
String username = result.getString("username");
|
||||||
float confidence = result.getFloat("confidence");
|
float confidence = result.getFloat("confidence");
|
||||||
|
|
||||||
//Calculate the data point
|
// Calculate the data point
|
||||||
float data = result.getFloat("data"); //the "raw" recorded data
|
float data = result.getFloat("data"); //the "raw" recorded data
|
||||||
float estimatedData = data/confidence; //estimate the "real" value of the data by looking at the confidence value
|
float estimatedData = data/confidence; //estimate the "real" value of the data by looking at the confidence value
|
||||||
|
|
||||||
//add null data point to list if one or more periods of data is missing before this
|
// Only add nulls if the report interval is smaller than the aggregated interval
|
||||||
if(previousTimestampEnd != -1 && previousTimestampEnd+1 < timestampStart){
|
if (sensor.getDeviceData() == null ||
|
||||||
list.add(new AggregateData(id, previousTimestampEnd+1, null /*Float.NaN*/, username));
|
timestampStart-timestampEnd > sensor.getDeviceData().getDataInterval()) {
|
||||||
|
// Add null data point to list if one or more periods of data is missing before this
|
||||||
|
if (previousTimestampEnd != -1 && previousTimestampEnd + 1 < timestampStart) {
|
||||||
|
list.add(new AggregateData(id, previousTimestampEnd + 1, null /*Float.NaN*/, username));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.add(new AggregateData(id, timestampEnd, (estimatedData/1000f), username)); //add this data point to list
|
list.add(new AggregateData(id, timestampEnd, (estimatedData/1000f), username)); //add this data point to list
|
||||||
|
|
||||||
//update previous end timestamp
|
// Update previous end timestamp
|
||||||
previousTimestampEnd = timestampEnd;
|
previousTimestampEnd = timestampEnd;
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue