这是indexloc提供的服务,不要输入任何密码
Skip to content
This repository was archived by the owner on May 17, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@
* Circles maintain current energy usage by counting 'pulses' in a one or eight-second interval. Furthermore, they
* store hourly energy usage as well in a buffer. Each entry in the buffer contains usage for the last 4 full hours
* of consumption. In order to convert pulses to power (Watt) or KWh you need to apply a formula that uses some
* calibration
* information
* calibration information.
*
* @author Karel Goderis
* @since 1.1.0
Expand All @@ -45,7 +44,9 @@ public class Circle extends PlugwiseDevice {

private static Logger logger = LoggerFactory.getLogger(Circle.class);

private static final float PULSE_FACTOR = 2.1324759f;
private static final double PULSES_PER_KW_SECOND = 468.9385193;

private static final double PULSES_PER_W_SECOND = (PULSES_PER_KW_SECOND / 1000);

private static final int POWER_STATE_RETRIES = 3;

Expand All @@ -67,10 +68,10 @@ public String getStateAsString() {

// Calibration data, required to calculate energy consumption
protected boolean calibrated;
protected float gaina;
protected float gainb;
protected float offtot;
protected float offruis;
protected double gainA;
protected double gainB;
protected double offsetTotal;
protected double offsetNoise;

// System variables as kept/maintained by the Circle hardware
protected DateTime stamp;
Expand All @@ -82,6 +83,7 @@ public String getStateAsString() {
protected String hardwareVersion;
protected DateTime firmwareVersion;
protected Energy one;
protected Energy lastHour;

// Pending power state changes are tracked for retries and temporarily
// ignoring an outdated result of an InformationJob
Expand Down Expand Up @@ -155,48 +157,37 @@ public void updateEnergy(boolean completeHistory) {
} else {
previousLogAddress = 0;
}
while (previousLogAddress < recentLogAddress) {
while (previousLogAddress <= recentLogAddress) {
PowerBufferRequestMessage message = new PowerBufferRequestMessage(MAC, previousLogAddress);
previousLogAddress = previousLogAddress + 1;
stick.sendMessage(message);
}

}

public float getCurrentWatt() {
public double getCurrentWatt() {
if (one != null) {
return pulseToWatt(one);
} else {
return 0;
}
}

private float pulseToWatt(Energy energy) {
float averagePulses;
float correctedPulses;

if (energy.getInterval() != 0) {
averagePulses = energy.getPulses() / energy.getInterval();
} else {
private double correctPulses(double pulses) {
double correctedPulses = Math.pow(pulses + offsetNoise, 2) * gainB + (pulses + offsetNoise) * gainA
+ offsetTotal;
if ((pulses > 0 && correctedPulses < 0) || (pulses < 0 && correctedPulses > 0)) {
return 0;
}
correctedPulses = (float) (Math.pow(averagePulses + offruis, 2) * gainb + (averagePulses + offruis) * gaina
+ offtot);

return correctedPulses * PULSE_FACTOR;
return correctedPulses;
}

private float pulseTokWh(Energy energy) {
float joule = 0;
if (energy.getInterval() == 0) {
float correctedPulses = (float) (Math.pow(energy.getPulses() + offruis, 2) * gainb
+ (energy.getPulses() + offruis) * gaina + offtot);
joule = correctedPulses * PULSE_FACTOR;
} else {
joule = pulseToWatt(energy) * energy.getInterval();
}
private double pulseToWatt(Energy energy) {
double averagePulses = energy.getPulses() / energy.getInterval();
return correctPulses(averagePulses) / PULSES_PER_W_SECOND;
}

return joule / (3600 * 1000);
private double pulseTokWh(Energy energy) {
return pulseToWatt(energy) * energy.getInterval() / (3600 * 1000);
}

@Override
Expand All @@ -215,10 +206,10 @@ public boolean processMessage(Message message) {

case DEVICE_CALIBRATION_RESPONSE:

gaina = ((CalibrationResponseMessage) message).getGaina();
gainb = ((CalibrationResponseMessage) message).getGainb();
offtot = ((CalibrationResponseMessage) message).getOfftot();
offruis = ((CalibrationResponseMessage) message).getOffruis();
gainA = ((CalibrationResponseMessage) message).getGainA();
gainB = ((CalibrationResponseMessage) message).getGainB();
offsetTotal = ((CalibrationResponseMessage) message).getOffsetTotal();
offsetNoise = ((CalibrationResponseMessage) message).getOffsetNoise();
calibrated = true;

return true;
Expand Down Expand Up @@ -258,6 +249,10 @@ public boolean processMessage(Message message) {
postUpdate(MAC, PlugwiseCommandType.CURRENTSTATE, powerState);
}

if (lastHour == null) {
updateEnergy(false);
}

return true;

case POWER_INFORMATION_RESPONSE:
Expand All @@ -271,7 +266,7 @@ public boolean processMessage(Message message) {
return true;
}
one = ((PowerInformationResponseMessage) message).getOneSecond();
float watt = pulseToWatt(one);
double watt = pulseToWatt(one);
if (watt > 10000) {
logger.debug("{} with name: {} and MAC address: {} is in a kind of error state, "
+ "skipping power information response", type.name(), name, MAC);
Expand All @@ -283,21 +278,27 @@ public boolean processMessage(Message message) {

case POWER_BUFFER_RESPONSE:

// get the last hour energy consumption
Energy lastHour = ((PowerBufferResponseMessage) message).getEnergy(3);
if (lastHour == null) {
lastHour = ((PowerBufferResponseMessage) message).getEnergy(2);
}
if (lastHour == null) {
lastHour = ((PowerBufferResponseMessage) message).getEnergy(1);
if (!calibrated) {
return true;
}
if (lastHour == null) {
lastHour = ((PowerBufferResponseMessage) message).getEnergy(0);

// get the most recent energy consumption
Energy mostRecentEnergy = null;
for (int i = 0; i < 4; i++) {
Energy energy = ((PowerBufferResponseMessage) message).getEnergy(i);
if (energy != null) {
mostRecentEnergy = energy;
}
}

if (lastHour != null) {
postUpdate(MAC, PlugwiseCommandType.LASTHOURCONSUMPTION, pulseTokWh(lastHour));
postUpdate(MAC, PlugwiseCommandType.LASTHOURCONSUMPTIONSTAMP, lastHour.getTime());
if (mostRecentEnergy != null) {
// when the current time is '11:44:55.888', the last hour energy has time '10:00:00.000'
boolean isLastHour = mostRecentEnergy.getTime().isAfter(DateTime.now().minusHours(2));
if (isLastHour) {
lastHour = mostRecentEnergy;
postUpdate(MAC, PlugwiseCommandType.LASTHOURCONSUMPTION, pulseTokWh(lastHour));
postUpdate(MAC, PlugwiseCommandType.LASTHOURCONSUMPTIONSTAMP, lastHour.getTime());
}
}

return true;
Expand Down Expand Up @@ -342,4 +343,5 @@ public boolean postUpdate(String MAC, PlugwiseCommandType type, Object value) {
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class Energy {

private DateTime time;
private long pulses;
private int interval;
private double interval;

public Energy(String logdate, long l, int interval) {
public Energy(String logdate, long l, double interval) {

if (logdate.length() == 8) {

Expand Down Expand Up @@ -56,15 +56,15 @@ public Energy(String logdate, long l, int interval) {

}

public Energy(DateTime logdate, long pulses, int interval) {
public Energy(DateTime logdate, long pulses, double interval) {
time = logdate;
this.interval = interval;
this.pulses = pulses;
}

@Override
public String toString() {
return time.toString() + "-" + Integer.toString(interval) + "-" + Long.toString(pulses);
return time.toString() + "-" + Double.toString(interval) + "-" + Long.toString(pulses);
}

public DateTime getTime() {
Expand All @@ -75,7 +75,7 @@ public long getPulses() {
return pulses;
}

public int getInterval() {
public double getInterval() {
return interval;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ private State createStateForType(PlugwiseCommandType ctype, Object value) throws
// the logic below covers all possible command types and value types
if (typeClass == DecimalType.class && value instanceof Float) {
return new DecimalType((Float) value);
} else if (typeClass == DecimalType.class && value instanceof Double) {
return new DecimalType((Double) value);
} else if (typeClass == OnOffType.class && value instanceof Boolean) {
return ((Boolean) value).booleanValue() ? OnOffType.ON : OnOffType.OFF;
} else if (typeClass == DateTimeType.class && value instanceof Calendar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@ public class CalibrationResponseMessage extends Message {

private static final Pattern RESPONSE_PATTERN = Pattern.compile("(\\w{16})(\\w{8})(\\w{8})(\\w{8})(\\w{8})");

private float gaina;
private float gainb;
private float offtot;
private float offruis;
private double gainA;
private double gainB;
private double offsetTotal;
private double offsetNoise;

public float getGaina() {
return gaina;
public double getGainA() {
return gainA;
}

public float getGainb() {
return gainb;
public double getGainB() {
return gainB;
}

public float getOfftot() {
return offtot;
public double getOffsetTotal() {
return offsetTotal;
}

public float getOffruis() {
return offruis;
public double getOffsetNoise() {
return offsetNoise;
}

public CalibrationResponseMessage(int sequenceNumber, String payLoad) {
Expand All @@ -58,10 +58,10 @@ protected void parsePayLoad() {
if (matcher.matches()) {
MAC = matcher.group(1);

gaina = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(2), 16)));
gainb = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(3), 16)));
offtot = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(4), 16)));
offruis = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(5), 16)));
gainA = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(2), 16)));
gainB = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(3), 16)));
offsetTotal = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(4), 16)));
offsetNoise = Float.intBitsToFloat((int) (Long.parseLong(matcher.group(5), 16)));
} else {
logger.debug("Plugwise protocol RoleCallResponseMessage error: {} does not match", payLoad);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ protected void parsePayLoad() {
year = Integer.parseInt(matcher.group(2), 16) + 2000;
month = Integer.parseInt(matcher.group(3), 16);
minutes = Integer.parseInt(matcher.group(4), 16);
logAddress = (Integer.parseInt(matcher.group(5), 16) - 278528) / 8;
logAddress = (Integer.parseInt(matcher.group(5), 16) - 278528) / 32;
powerState = (matcher.group(6).equals("01"));
hertz = Integer.parseInt(matcher.group(7), 16);
hardwareVersion = StringUtils.left(matcher.group(8), 4) + "-" + StringUtils.mid(matcher.group(8), 4, 4)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public PowerBufferRequestMessage(String MAC, int logAddress) {

@Override
protected String payLoadToHexString() {
return String.format("%08X", (logAddress * 8 + 278528));
return String.format("%08X", (logAddress * 32 + 278528));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,22 @@ protected void parsePayLoad() {
datapoints[0] = null;
}
if (!matcher.group(4).equals("FFFFFFFF")) {
datapoints[1] = new Energy(matcher.group(2), Long.parseLong(matcher.group(5), 16), 3600);
datapoints[1] = new Energy(matcher.group(4), Long.parseLong(matcher.group(5), 16), 3600);
} else {
datapoints[1] = null;
}
if (!matcher.group(6).equals("FFFFFFFF")) {
datapoints[2] = new Energy(matcher.group(2), Long.parseLong(matcher.group(7), 16), 3600);
datapoints[2] = new Energy(matcher.group(6), Long.parseLong(matcher.group(7), 16), 3600);
} else {
datapoints[2] = null;
}
if (!matcher.group(8).equals("FFFFFFFF")) {
datapoints[3] = new Energy(matcher.group(2), Long.parseLong(matcher.group(9), 16), 3600);
datapoints[3] = new Energy(matcher.group(8), Long.parseLong(matcher.group(9), 16), 3600);
} else {
datapoints[3] = null;
}

logAddress = (Integer.parseInt(matcher.group(10), 16) - 278528) / 8;
logAddress = (Integer.parseInt(matcher.group(10), 16) - 278528) / 32;
} else {
logger.debug("Plugwise protocol PowerBufferResponseMessage error: {} does not match", payLoad);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@
public class PowerInformationResponseMessage extends Message {

private static final Pattern RESPONSE_PATTERN = Pattern
.compile("(\\w{16})(\\w{4})(\\w{4})(\\w{8})(\\w{4})(\\w{4})(\\w{4})");
.compile("(\\w{16})(\\w{4})(\\w{4})(\\w{8})(\\w{8})(\\w{4})");

private Energy oneSecond;
private Energy eightSecond;
private Energy allSeconds;
@SuppressWarnings("unused")
private int unknown1;
@SuppressWarnings("unused")
private int unknown2;
@SuppressWarnings("unused")
private int unknown3;
private Energy oneHourConsumed;
private Energy oneHourProduced;
private double secondsCorrection;

public PowerInformationResponseMessage(int sequenceNumber, String payLoad) {
super(sequenceNumber, payLoad);
Expand All @@ -51,13 +47,11 @@ protected void parsePayLoad() {
Matcher matcher = RESPONSE_PATTERN.matcher(payLoad);
if (matcher.matches()) {
MAC = matcher.group(1);
oneSecond = new Energy(DateTime.now(), Integer.parseInt(matcher.group(2), 16), 1);
eightSecond = new Energy(DateTime.now(), Integer.parseInt(matcher.group(3), 16), 8);
allSeconds = new Energy(DateTime.now(), Integer.parseInt(matcher.group(4), 16), 0);
unknown1 = Integer.parseInt(matcher.group(5), 16);
unknown2 = Integer.parseInt(matcher.group(6), 16);
unknown3 = Integer.parseInt(matcher.group(7), 16);

secondsCorrection = Integer.parseInt(matcher.group(6), 16) / 46875.0;
oneSecond = new Energy(DateTime.now(), Integer.parseInt(matcher.group(2), 16), 1 + secondsCorrection);
eightSecond = new Energy(DateTime.now(), Integer.parseInt(matcher.group(3), 16), 8 + secondsCorrection);
oneHourConsumed = new Energy(DateTime.now(), Long.parseLong(matcher.group(4), 16), 3600);
oneHourProduced = new Energy(DateTime.now(), Long.parseLong(matcher.group(5), 16), 3600);
} else {
logger.debug("Plugwise protocol PowerInformationResponseMessage error: {} does not match", payLoad);
}
Expand All @@ -71,7 +65,11 @@ public Energy getEightSecond() {
return eightSecond;
}

public Energy getAllSeconds() {
return allSeconds;
public Energy getOneHourConsumed() {
return oneHourConsumed;
}

public Energy getOneHourProduced() {
return oneHourProduced;
}
}