Skip to content

Commit d5ad854

Browse files
committed
[senechome] Fix ArrayIndexOutOfBoundsException when less than 4 packs (openhab#17299)
* Fix issue and warnings * Fix operator Signed-off-by: Leo Siepel <[email protected]>
1 parent bec9863 commit d5ad854

12 files changed

+98
-76
lines changed

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeApi.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import org.eclipse.jetty.http.HttpMethod;
2828
import org.eclipse.jetty.http.HttpStatus;
2929
import org.eclipse.jetty.http.MimeTypes;
30-
import org.openhab.binding.senechome.internal.json.SenecHomeResponse;
30+
import org.openhab.binding.senechome.internal.dto.SenecHomeResponse;
3131
import org.slf4j.Logger;
3232
import org.slf4j.LoggerFactory;
3333

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecHomeHandler.java

+83-67
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import org.eclipse.jdt.annotation.NonNullByDefault;
3333
import org.eclipse.jdt.annotation.Nullable;
3434
import org.eclipse.jetty.client.HttpClient;
35-
import org.openhab.binding.senechome.internal.json.SenecHomeResponse;
35+
import org.openhab.binding.senechome.internal.dto.SenecHomeResponse;
3636
import org.openhab.core.cache.ExpiringCache;
3737
import org.openhab.core.library.types.DecimalType;
3838
import org.openhab.core.library.types.OnOffType;
@@ -67,8 +67,6 @@ public class SenecHomeHandler extends BaseThingHandler {
6767
private static final BigDecimal DIVISOR_MILLI_TO_KILO = BigDecimal.valueOf(1000000);
6868
// divisor to transform from milli to "iso" UNIT (e.g. mV => V)
6969
private static final BigDecimal DIVISOR_MILLI_TO_ISO = BigDecimal.valueOf(1000);
70-
// divisor to transform from "iso" to kilo UNIT (e.g. W => kW)
71-
private static final BigDecimal DIVISOR_ISO_TO_KILO = BigDecimal.valueOf(1000);
7270
// ix (x=1,3,8) types => hex encoded integer value
7371
private static final String VALUE_TYPE_INT1 = "i1";
7472
public static final String VALUE_TYPE_INT3 = "i3";
@@ -82,7 +80,7 @@ public class SenecHomeHandler extends BaseThingHandler {
8280

8381
private @Nullable ScheduledFuture<?> refreshJob;
8482
private @Nullable PowerLimitationStatusDTO limitationStatus = null;
85-
private final @Nullable SenecHomeApi senecHomeApi;
83+
private final SenecHomeApi senecHomeApi;
8684
private SenecHomeConfigurationDTO config = new SenecHomeConfigurationDTO();
8785
private final ExpiringCache<Boolean> refreshCache = new ExpiringCache<>(Duration.ofSeconds(5), this::refreshState);
8886

@@ -133,6 +131,18 @@ private void refresh() {
133131
refreshCache.getValue();
134132
}
135133

134+
private <Q extends Quantity<Q>> void updateQtyStateIfAvailable(String channel, String @Nullable [] valueArray,
135+
int arrayIndex, int scale, Unit<Q> unit) {
136+
updateQtyStateIfAvailable(channel, valueArray, arrayIndex, scale, unit, null);
137+
}
138+
139+
private <Q extends Quantity<Q>> void updateQtyStateIfAvailable(String channel, String @Nullable [] valueArray,
140+
int arrayIndex, int scale, Unit<Q> unit, @Nullable BigDecimal divisor) {
141+
if (valueArray != null && valueArray.length > arrayIndex) {
142+
updateQtyState(channel, valueArray[arrayIndex], scale, unit, divisor);
143+
}
144+
}
145+
136146
public @Nullable Boolean refreshState() {
137147
SenecHomeResponse response = null;
138148
try {
@@ -197,65 +207,68 @@ private void refresh() {
197207
updateQtyState(CHANNEL_SENEC_GRID_VOLTAGE_PH3, response.grid.currentGridVoltagePerPhase[2], 2, Units.VOLT);
198208
updateQtyState(CHANNEL_SENEC_GRID_FREQUENCY, response.grid.currentGridFrequency, 2, Units.HERTZ);
199209

200-
if (response.battery.chargedEnergy != null) {
201-
updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK1, response.battery.chargedEnergy[0], 2,
202-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
203-
updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK2, response.battery.chargedEnergy[1], 2,
204-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
205-
updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK3, response.battery.chargedEnergy[2], 2,
206-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
207-
updateQtyState(CHANNEL_SENEC_CHARGED_ENERGY_PACK4, response.battery.chargedEnergy[3], 2,
208-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
209-
}
210-
if (response.battery.dischargedEnergy != null) {
211-
updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK1, response.battery.dischargedEnergy[0], 2,
212-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
213-
updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK2, response.battery.dischargedEnergy[1], 2,
214-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
215-
updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK3, response.battery.dischargedEnergy[2], 2,
216-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
217-
updateQtyState(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK4, response.battery.dischargedEnergy[3], 2,
218-
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
219-
}
210+
updateQtyStateIfAvailable(CHANNEL_SENEC_CHARGED_ENERGY_PACK1, response.battery.chargedEnergy, 0, 2,
211+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
212+
updateQtyStateIfAvailable(CHANNEL_SENEC_CHARGED_ENERGY_PACK2, response.battery.chargedEnergy, 1, 2,
213+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
214+
updateQtyStateIfAvailable(CHANNEL_SENEC_CHARGED_ENERGY_PACK3, response.battery.chargedEnergy, 2, 2,
215+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
216+
updateQtyStateIfAvailable(CHANNEL_SENEC_CHARGED_ENERGY_PACK4, response.battery.chargedEnergy, 3, 2,
217+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
218+
219+
updateQtyStateIfAvailable(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK1, response.battery.dischargedEnergy, 0, 2,
220+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
221+
updateQtyStateIfAvailable(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK2, response.battery.dischargedEnergy, 1, 2,
222+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
223+
updateQtyStateIfAvailable(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK3, response.battery.dischargedEnergy, 2, 2,
224+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
225+
updateQtyStateIfAvailable(CHANNEL_SENEC_DISCHARGED_ENERGY_PACK4, response.battery.dischargedEnergy, 3, 2,
226+
Units.KILOWATT_HOUR, DIVISOR_MILLI_TO_KILO);
227+
220228
if (response.battery.cycles != null) {
221-
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK1, response.battery.cycles[0]);
222-
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK2, response.battery.cycles[1]);
223-
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK3, response.battery.cycles[2]);
224-
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK4, response.battery.cycles[3]);
225-
}
226-
if (response.battery.current != null) {
227-
updateQtyState(CHANNEL_SENEC_CURRENT_PACK1, response.battery.current[0], 2, Units.AMPERE);
228-
updateQtyState(CHANNEL_SENEC_CURRENT_PACK2, response.battery.current[1], 2, Units.AMPERE);
229-
updateQtyState(CHANNEL_SENEC_CURRENT_PACK3, response.battery.current[2], 2, Units.AMPERE);
230-
updateQtyState(CHANNEL_SENEC_CURRENT_PACK4, response.battery.current[3], 2, Units.AMPERE);
231-
}
232-
if (response.battery.voltage != null) {
233-
updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK1, response.battery.voltage[0], 2, Units.VOLT);
234-
updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK2, response.battery.voltage[1], 2, Units.VOLT);
235-
updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK3, response.battery.voltage[2], 2, Units.VOLT);
236-
updateQtyState(CHANNEL_SENEC_VOLTAGE_PACK4, response.battery.voltage[3], 2, Units.VOLT);
237-
}
238-
if (response.battery.maxCellVoltage != null) {
239-
updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK1, response.battery.maxCellVoltage[0], 3, Units.VOLT,
240-
DIVISOR_MILLI_TO_ISO);
241-
updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK2, response.battery.maxCellVoltage[1], 3, Units.VOLT,
242-
DIVISOR_MILLI_TO_ISO);
243-
updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK3, response.battery.maxCellVoltage[2], 3, Units.VOLT,
244-
DIVISOR_MILLI_TO_ISO);
245-
updateQtyState(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK4, response.battery.maxCellVoltage[3], 3, Units.VOLT,
246-
DIVISOR_MILLI_TO_ISO);
247-
}
248-
if (response.battery.minCellVoltage != null) {
249-
updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK1, response.battery.minCellVoltage[0], 3, Units.VOLT,
250-
DIVISOR_MILLI_TO_ISO);
251-
updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK2, response.battery.minCellVoltage[1], 3, Units.VOLT,
252-
DIVISOR_MILLI_TO_ISO);
253-
updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK3, response.battery.minCellVoltage[2], 3, Units.VOLT,
254-
DIVISOR_MILLI_TO_ISO);
255-
updateQtyState(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK4, response.battery.minCellVoltage[3], 3, Units.VOLT,
256-
DIVISOR_MILLI_TO_ISO);
229+
int length = response.battery.cycles.length;
230+
if (length > 0) {
231+
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK1, response.battery.cycles[0]);
232+
}
233+
if (length > 1) {
234+
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK2, response.battery.cycles[1]);
235+
}
236+
if (length > 2) {
237+
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK3, response.battery.cycles[2]);
238+
}
239+
if (length > 3) {
240+
updateDecimalState(CHANNEL_SENEC_CYCLES_PACK4, response.battery.cycles[3]);
241+
}
257242
}
258243

244+
updateQtyStateIfAvailable(CHANNEL_SENEC_CURRENT_PACK1, response.battery.current, 0, 2, Units.AMPERE);
245+
updateQtyStateIfAvailable(CHANNEL_SENEC_CURRENT_PACK2, response.battery.current, 1, 2, Units.AMPERE);
246+
updateQtyStateIfAvailable(CHANNEL_SENEC_CURRENT_PACK3, response.battery.current, 2, 2, Units.AMPERE);
247+
updateQtyStateIfAvailable(CHANNEL_SENEC_CURRENT_PACK4, response.battery.current, 3, 2, Units.AMPERE);
248+
249+
updateQtyStateIfAvailable(CHANNEL_SENEC_VOLTAGE_PACK1, response.battery.voltage, 0, 2, Units.VOLT);
250+
updateQtyStateIfAvailable(CHANNEL_SENEC_VOLTAGE_PACK2, response.battery.voltage, 1, 2, Units.VOLT);
251+
updateQtyStateIfAvailable(CHANNEL_SENEC_VOLTAGE_PACK3, response.battery.voltage, 2, 2, Units.VOLT);
252+
updateQtyStateIfAvailable(CHANNEL_SENEC_VOLTAGE_PACK4, response.battery.voltage, 3, 2, Units.VOLT);
253+
254+
updateQtyStateIfAvailable(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK1, response.battery.maxCellVoltage, 0, 3,
255+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
256+
updateQtyStateIfAvailable(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK2, response.battery.maxCellVoltage, 1, 3,
257+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
258+
updateQtyStateIfAvailable(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK3, response.battery.maxCellVoltage, 2, 3,
259+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
260+
updateQtyStateIfAvailable(CHANNEL_SENEC_MAX_CELL_VOLTAGE_PACK4, response.battery.maxCellVoltage, 3, 3,
261+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
262+
263+
updateQtyStateIfAvailable(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK1, response.battery.minCellVoltage, 0, 3,
264+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
265+
updateQtyStateIfAvailable(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK2, response.battery.minCellVoltage, 1, 3,
266+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
267+
updateQtyStateIfAvailable(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK3, response.battery.minCellVoltage, 2, 3,
268+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
269+
updateQtyStateIfAvailable(CHANNEL_SENEC_MIN_CELL_VOLTAGE_PACK4, response.battery.minCellVoltage, 3, 3,
270+
Units.VOLT, DIVISOR_MILLI_TO_ISO);
271+
259272
if (response.temperature != null) {
260273
updateQtyState(CHANNEL_SENEC_BATTERY_TEMPERATURE, response.temperature.batteryTemperature, 0,
261274
SIUnits.CELSIUS);
@@ -376,9 +389,10 @@ private static BigDecimal parseFloatValue(String value) {
376389
}
377390

378391
protected void updatePowerLimitationStatus(Channel channel, boolean status, int duration) {
379-
if (this.limitationStatus != null) {
380-
if (this.limitationStatus.state == status) {
381-
long stateSince = new Date().getTime() - this.limitationStatus.time;
392+
PowerLimitationStatusDTO limitationStatus = this.limitationStatus;
393+
if (limitationStatus != null) {
394+
if (limitationStatus.state == status) {
395+
long stateSince = new Date().getTime() - limitationStatus.time;
382396

383397
if (((int) (stateSince / 1000)) < duration) {
384398
// skip updating state (possible flapping state)
@@ -387,15 +401,17 @@ protected void updatePowerLimitationStatus(Channel channel, boolean status, int
387401
logger.debug("{} longer than required duration {}", status, duration);
388402
}
389403
} else {
390-
this.limitationStatus.state = status;
391-
this.limitationStatus.time = new Date().getTime();
404+
limitationStatus.state = status;
405+
limitationStatus.time = new Date().getTime();
406+
this.limitationStatus = limitationStatus;
392407

393408
// skip updating state (state changed, possible flapping state)
394409
return;
395410
}
396411
} else {
397-
this.limitationStatus = new PowerLimitationStatusDTO();
398-
this.limitationStatus.state = status;
412+
limitationStatus = new PowerLimitationStatusDTO();
413+
limitationStatus.state = status;
414+
this.limitationStatus = limitationStatus;
399415
}
400416

401417
logger.debug("Updating power limitation state {}", status);

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecSystemStatus.java

+3
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@
1212
*/
1313
package org.openhab.binding.senechome.internal;
1414

15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
1517
/**
1618
* The {@link SenecSystemStatus} class defines available Senec specific
1719
* system states.
1820
*
1921
* @author Steven Schwarznau - Initial contribution
2022
*
2123
*/
24+
@NonNullByDefault
2225
public enum SenecSystemStatus {
2326

2427
INITIALSTATE(0, "INITIAL STATE"),

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/SenecWallboxStatus.java

+3
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,14 @@
1212
*/
1313
package org.openhab.binding.senechome.internal;
1414

15+
import org.eclipse.jdt.annotation.NonNullByDefault;
16+
1517
/**
1618
* Enum with available Senec specific wallbox states.
1719
*
1820
* @author Erwin Guib - Initial Contribution
1921
*/
22+
@NonNullByDefault
2023
public enum SenecWallboxStatus {
2124
WAIT_FOR_EV(0xA1, "Waiting for EV"),
2225
EV_ASKING_CHARGE(0xB1, "EV asking for charge"),

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeBattery.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeBattery.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616
import java.util.Arrays;

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeEnergy.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeEnergy.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeGrid.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeGrid.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomePower.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomePower.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616
import java.util.Arrays;

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeResponse.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeResponse.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeStatistics.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeStatistics.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616
import java.util.Arrays;
+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616

bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/json/SenecHomeWallbox.java bundles/org.openhab.binding.senechome/src/main/java/org/openhab/binding/senechome/internal/dto/SenecHomeWallbox.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
* SPDX-License-Identifier: EPL-2.0
1212
*/
13-
package org.openhab.binding.senechome.internal.json;
13+
package org.openhab.binding.senechome.internal.dto;
1414

1515
import java.io.Serializable;
1616
import java.util.Arrays;

0 commit comments

Comments
 (0)