[bluetooth.daikinmadoka] null annotations (#13975)

* null annotations - sat warnings
* refactor handleResponses

Signed-off-by: Leo Siepel <leosiepel@gmail.com>
This commit is contained in:
lsiepel 2022-12-27 17:12:58 +01:00 committed by GitHub
parent a4a8d5d85f
commit 697373801b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 194 additions and 112 deletions

View File

@ -24,7 +24,6 @@ import java.util.concurrent.TimeoutException;
import javax.measure.quantity.Temperature; import javax.measure.quantity.Temperature;
import javax.measure.quantity.Time; import javax.measure.quantity.Time;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.BluetoothCharacteristic; import org.openhab.binding.bluetooth.BluetoothCharacteristic;
@ -84,7 +83,7 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
private final Logger logger = LoggerFactory.getLogger(DaikinMadokaHandler.class); private final Logger logger = LoggerFactory.getLogger(DaikinMadokaHandler.class);
private @Nullable DaikinMadokaConfiguration config; private DaikinMadokaConfiguration config = new DaikinMadokaConfiguration();
private @Nullable ExecutorService commandExecutor; private @Nullable ExecutorService commandExecutor;
@ -109,10 +108,10 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
// Load Configuration // Load Configuration
config = getConfigAs(DaikinMadokaConfiguration.class); config = getConfigAs(DaikinMadokaConfiguration.class);
DaikinMadokaConfiguration c = config;
logger.debug("[{}] Parameter value [refreshInterval]: {}", super.thing.getUID().getId(), c.refreshInterval); logger.debug("[{}] Parameter value [refreshInterval]: {}", super.thing.getUID().getId(),
logger.debug("[{}] Parameter value [commandTimeout]: {}", super.thing.getUID().getId(), c.commandTimeout); config.refreshInterval);
logger.debug("[{}] Parameter value [commandTimeout]: {}", super.thing.getUID().getId(), config.commandTimeout);
if (getBridge() == null) { if (getBridge() == null) {
logger.debug("[{}] Bridge is null. Exiting.", super.thing.getUID().getId()); logger.debug("[{}] Bridge is null. Exiting.", super.thing.getUID().getId());
@ -144,9 +143,9 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
} }
submitCommand(new GetEyeBrightnessCommand()); submitCommand(new GetEyeBrightnessCommand());
}, new Random().nextInt(30), c.refreshInterval, TimeUnit.SECONDS); // We introduce a random start time, it }, new Random().nextInt(30), config.refreshInterval, TimeUnit.SECONDS); // We introduce a random start time, it
// avoids when having multiple devices to // avoids when having multiple devices to
// have the commands sent simultaneously. // have the commands sent simultaneously.
} }
private void retrieveOperationHours() throws InterruptedException { private void retrieveOperationHours() throws InterruptedException {
@ -174,7 +173,6 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
.getCharacteristic(DaikinMadokaBindingConstants.CHAR_NOTIF_UUID); .getCharacteristic(DaikinMadokaBindingConstants.CHAR_NOTIF_UUID);
if (charNotif != null) { if (charNotif != null) {
@NonNull
BluetoothCharacteristic c = charNotif; BluetoothCharacteristic c = charNotif;
this.device.disableNotifications(c); this.device.disableNotifications(c);
} }
@ -443,8 +441,8 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
} }
} }
if (command.getState() == BRC1HCommand.State.SENT && this.config != null) { if (command.getState() == BRC1HCommand.State.SENT) {
if (!command.awaitStateChange(this.config.commandTimeout, TimeUnit.MILLISECONDS, if (!command.awaitStateChange(config.commandTimeout, TimeUnit.MILLISECONDS,
BRC1HCommand.State.SUCCEEDED, BRC1HCommand.State.FAILED)) { BRC1HCommand.State.SUCCEEDED, BRC1HCommand.State.FAILED)) {
logger.debug("[{}] Command {} to device {} timed out", super.thing.getUID().getId(), command, logger.debug("[{}] Command {} to device {} timed out", super.thing.getUID().getId(), command,
device.getAddress()); device.getAddress());
@ -825,7 +823,7 @@ public class DaikinMadokaHandler extends ConnectedBluetoothHandler implements Re
if (indicatorStatus != null) { if (indicatorStatus != null) {
this.madokaSettings.setCleanFilterIndicator(indicatorStatus); this.madokaSettings.setCleanFilterIndicator(indicatorStatus);
updateStateIfLinked(DaikinMadokaBindingConstants.CHANNEL_ID_CLEAN_FILTER_INDICATOR, updateStateIfLinked(DaikinMadokaBindingConstants.CHANNEL_ID_CLEAN_FILTER_INDICATOR,
indicatorStatus == true ? OnOffType.ON : OnOffType.OFF); OnOffType.from(indicatorStatus));
} }
} }

View File

@ -12,14 +12,17 @@
*/ */
package org.openhab.binding.bluetooth.daikinmadoka.internal; package org.openhab.binding.bluetooth.daikinmadoka.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/** /**
* The {@link DaikinMadokaConfiguration} class contains fields mapping thing configuration parameters. * The {@link DaikinMadokaConfiguration} class contains fields mapping thing configuration parameters.
* *
* @author Benjamin Lafois - Initial contribution * @author Benjamin Lafois - Initial contribution
*/ */
@NonNullByDefault
public class DaikinMadokaConfiguration { public class DaikinMadokaConfiguration {
public String address; public String address = "";
public Integer refreshInterval; public int refreshInterval;
public Integer commandTimeout; public int commandTimeout;
} }

View File

@ -18,8 +18,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Command used to disable the Clean Filter Indicator notification * Command used to disable the Clean Filter Indicator notification
@ -30,8 +28,6 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public class DisableCleanFilterIndicatorCommand extends BRC1HCommand { public class DisableCleanFilterIndicatorCommand extends BRC1HCommand {
private final Logger logger = LoggerFactory.getLogger(DisableCleanFilterIndicatorCommand.class);
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {

View File

@ -18,8 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.slf4j.Logger; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.LoggerFactory;
/** /**
* Command used to get the Clean Filter Indicator status * Command used to get the Clean Filter Indicator status
@ -30,15 +29,19 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public class GetCleanFilterIndicatorCommand extends BRC1HCommand { public class GetCleanFilterIndicatorCommand extends BRC1HCommand {
private final Logger logger = LoggerFactory.getLogger(GetCleanFilterIndicatorCommand.class);
private @Nullable Boolean cleanFilterIndicator; private @Nullable Boolean cleanFilterIndicator;
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
MadokaValue mValue = mm.getValues().get(0x62);
if (mValue == null) {
String message = "clean filter indicator is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
byte[] valueCleanFilterIndicator = mm.getValues().get(0x62).getRawValue(); byte[] valueCleanFilterIndicator = mValue.getRawValue();
if (valueCleanFilterIndicator == null || valueCleanFilterIndicator.length != 1) { if (valueCleanFilterIndicator == null || valueCleanFilterIndicator.length != 1) {
setState(State.FAILED); setState(State.FAILED);
throw new MadokaParsingException("Incorrect clean filter indicator value"); throw new MadokaParsingException("Incorrect clean filter indicator value");
@ -51,7 +54,12 @@ public class GetCleanFilterIndicatorCommand extends BRC1HCommand {
} }
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
public @Nullable Boolean getCleanFilterIndicator() { public @Nullable Boolean getCleanFilterIndicator() {

View File

@ -39,24 +39,32 @@ public class GetEyeBrightnessCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
byte[] bEyeBrightness = mm.getValues().get(0x33).getRawValue(); MadokaValue mValue = mm.getValues().get(0x33);
if (mValue == null) {
String message = "eye brightness is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
if (bEyeBrightness == null || bEyeBrightness == null) { byte[] bEyeBrightness = mValue.getRawValue();
if (bEyeBrightness == null) {
setState(State.FAILED); setState(State.FAILED);
throw new MadokaParsingException("Incorrect eye brightness value"); throw new MadokaParsingException("Incorrect eye brightness value");
} }
Integer iEyeBrightness = Integer.valueOf(bEyeBrightness[0]); Integer iEyeBrightness = Integer.valueOf(bEyeBrightness[0]);
// The values accepted by the device are from 0 to 19 - integers so conversion needed for Dimmer channel
if (iEyeBrightness != null) { eyeBrightness = new PercentType((int) Math.round(iEyeBrightness / 0.19));
// The values accepted by the device are from 0 to 19 - integers so conversion needed for Dimmer channel
eyeBrightness = new PercentType((int) Math.round(iEyeBrightness / 0.19));
}
logger.debug("Eye Brightness: {}", eyeBrightness); logger.debug("Eye Brightness: {}", eyeBrightness);
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
@Override @Override

View File

@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaProperties.FanSpeed; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaProperties.FanSpeed;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,9 +45,16 @@ public class GetFanspeedCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
MadokaValue coolValue = mm.getValues().get(0x20);
MadokaValue heatValue = mm.getValues().get(0x21);
if (heatValue == null || coolValue == null) {
String message = "heating or cooling fan speed is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
byte[] valueCoolingFanSpeed = mm.getValues().get(0x20).getRawValue(); byte[] valueCoolingFanSpeed = coolValue.getRawValue();
byte[] valueHeatingFanSpeed = mm.getValues().get(0x21).getRawValue(); byte[] valueHeatingFanSpeed = heatValue.getRawValue();
if (valueCoolingFanSpeed == null || valueHeatingFanSpeed == null) { if (valueCoolingFanSpeed == null || valueHeatingFanSpeed == null) {
setState(State.FAILED); setState(State.FAILED);
@ -60,7 +68,13 @@ public class GetFanspeedCommand extends BRC1HCommand {
logger.debug("heatingFanSpeed: {}", heatingFanSpeed); logger.debug("heatingFanSpeed: {}", heatingFanSpeed);
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this));
try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
@Override @Override

View File

@ -20,6 +20,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.SIUnits;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -47,9 +48,16 @@ public class GetIndoorOutoorTemperatures extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
byte[] bIndoorTemperature = mm.getValues().get(0x40).getRawValue(); MadokaValue indoorValue = mm.getValues().get(0x40);
byte[] bOutdoorTemperature = mm.getValues().get(0x41).getRawValue(); MadokaValue outdoorValue = mm.getValues().get(0x41);
if (outdoorValue == null || indoorValue == null) {
String message = "indoor or outdoor value is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
byte[] bIndoorTemperature = indoorValue.getRawValue();
byte[] bOutdoorTemperature = outdoorValue.getRawValue();
if (bIndoorTemperature == null || bOutdoorTemperature == null) { if (bIndoorTemperature == null || bOutdoorTemperature == null) {
setState(State.FAILED); setState(State.FAILED);
throw new MadokaParsingException("Incorrect indoor or outdoor temperature"); throw new MadokaParsingException("Incorrect indoor or outdoor temperature");
@ -66,9 +74,7 @@ public class GetIndoorOutoorTemperatures extends BRC1HCommand {
} }
} }
if (iIndoorTemperature != null) { indoorTemperature = new QuantityType<Temperature>(iIndoorTemperature, SIUnits.CELSIUS);
indoorTemperature = new QuantityType<Temperature>(iIndoorTemperature, SIUnits.CELSIUS);
}
if (iOutdoorTemperature != null) { if (iOutdoorTemperature != null) {
outdoorTemperature = new QuantityType<Temperature>(iOutdoorTemperature, SIUnits.CELSIUS); outdoorTemperature = new QuantityType<Temperature>(iOutdoorTemperature, SIUnits.CELSIUS);
@ -78,7 +84,13 @@ public class GetIndoorOutoorTemperatures extends BRC1HCommand {
logger.debug("Outdoor Temp: {}", outdoorTemperature); logger.debug("Outdoor Temp: {}", outdoorTemperature);
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this));
try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
public @Nullable QuantityType<Temperature> getIndoorTemperature() { public @Nullable QuantityType<Temperature> getIndoorTemperature() {

View File

@ -24,7 +24,6 @@ import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingEx
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.Units; import org.openhab.core.library.unit.Units;
import org.openhab.core.util.HexUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -62,33 +61,34 @@ public class GetOperationHoursCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
try { MadokaValue opHours = mm.getValues().get(0x40);
MadokaValue fanHours = mm.getValues().get(0x41);
byte[] msg = mm.getRawMessage(); MadokaValue powerHours = mm.getValues().get(0x42);
if (logger.isDebugEnabled() && msg != null) { if (opHours == null || fanHours == null || powerHours == null) {
logger.debug("Got response for {} : {}", this.getClass().getSimpleName(), HexUtils.bytesToHex(msg)); String message = "indoorOperationHours, indoorFanHours or indoorPowerHours is null when handling the response";
} setState(State.FAILED);
throw new MadokaParsingException(message);
// The specific GetOperationHours requires 2 consecutive runs for some reason. }
// If value size is 0, then it will be for the next query!
if (mm.getValues().get(0x40).getSize() == 0) {
setState(State.SUCCEEDED);
return;
}
Integer iIndoorOperationHours = (int) (mm.getValues().get(0x40).getComputedValue(ByteOrder.LITTLE_ENDIAN));
Integer iIndoorFanHours = (int) (mm.getValues().get(0x41).getComputedValue(ByteOrder.LITTLE_ENDIAN));
Integer iIndoorPowerHours = (int) (mm.getValues().get(0x42).getComputedValue(ByteOrder.LITTLE_ENDIAN));
this.indoorOperationHours = new QuantityType<Time>(iIndoorOperationHours, Units.HOUR);
this.indoorFanHours = new QuantityType<Time>(iIndoorFanHours, Units.HOUR);
this.indoorPowerHours = new QuantityType<Time>(iIndoorPowerHours, Units.HOUR);
logger.debug("indoorOperationHours: {}", indoorOperationHours);
logger.debug("indoorFanHours: {}", indoorFanHours);
logger.debug("indoorPowerHours: {}", indoorPowerHours);
if (opHours.getSize() == 0) {
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
return;
}
Integer iIndoorOperationHours = (int) (opHours.getComputedValue(ByteOrder.LITTLE_ENDIAN));
Integer iIndoorFanHours = (int) (fanHours.getComputedValue(ByteOrder.LITTLE_ENDIAN));
Integer iIndoorPowerHours = (int) (powerHours.getComputedValue(ByteOrder.LITTLE_ENDIAN));
this.indoorOperationHours = new QuantityType<Time>(iIndoorOperationHours, Units.HOUR);
this.indoorFanHours = new QuantityType<Time>(iIndoorFanHours, Units.HOUR);
this.indoorPowerHours = new QuantityType<Time>(iIndoorPowerHours, Units.HOUR);
logger.debug("indoorOperationHours: {}", indoorOperationHours);
logger.debug("indoorFanHours: {}", indoorFanHours);
logger.debug("indoorPowerHours: {}", indoorPowerHours);
setState(State.SUCCEEDED);
try {
executor.execute(() -> listener.receivedResponse(this)); executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) { } catch (Exception e) {
setState(State.FAILED); setState(State.FAILED);

View File

@ -19,6 +19,7 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaProperties.OperationMode; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaProperties.OperationMode;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -43,7 +44,13 @@ public class GetOperationmodeCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
byte[] bOperationMode = mm.getValues().get(0x20).getRawValue(); @Nullable
MadokaValue mode = mm.getValues().get(0x20);
if (mode == null) {
setState(State.FAILED);
throw new MadokaParsingException("Incorrect operation mode");
}
byte[] bOperationMode = mode.getRawValue();
if (bOperationMode == null) { if (bOperationMode == null) {
setState(State.FAILED); setState(State.FAILED);
throw new MadokaParsingException("Incorrect operation mode"); throw new MadokaParsingException("Incorrect operation mode");
@ -54,7 +61,12 @@ public class GetOperationmodeCommand extends BRC1HCommand {
logger.debug("operationMode: {}", operationMode); logger.debug("operationMode: {}", operationMode);
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
@Override @Override

View File

@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -42,8 +43,14 @@ public class GetPowerstateCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
byte[] powerStateValue = mm.getValues().get(0x20).getRawValue(); MadokaValue mValue = mm.getValues().get(0x20);
if (mValue == null) {
String message = "powerstate is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
byte[] powerStateValue = mValue.getRawValue();
if (powerStateValue == null || powerStateValue.length != 1) { if (powerStateValue == null || powerStateValue.length != 1) {
setState(State.FAILED); setState(State.FAILED);
throw new MadokaParsingException("Incorrect value for PowerState"); throw new MadokaParsingException("Incorrect value for PowerState");
@ -54,7 +61,12 @@ public class GetPowerstateCommand extends BRC1HCommand {
logger.debug("PowerState: {}", powerState); logger.debug("PowerState: {}", powerState);
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
@Override @Override

View File

@ -20,6 +20,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.QuantityType;
import org.openhab.core.library.unit.SIUnits; import org.openhab.core.library.unit.SIUnits;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -47,17 +48,25 @@ public class GetSetpointCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
MadokaValue heatValue = mm.getValues().get(0x21);
MadokaValue coolValue = mm.getValues().get(0x20);
if (heatValue == null || coolValue == null) {
String message = "heatingSetpoint or coolingSetpoint is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
Integer iHeatingSetpoint = (int) (heatValue.getComputedValue() / 128.);
Integer iCoolingSetpoint = (int) (coolValue.getComputedValue() / 128.);
this.heatingSetpoint = new QuantityType<Temperature>(iHeatingSetpoint, SIUnits.CELSIUS);
this.coolingSetpoint = new QuantityType<Temperature>(iCoolingSetpoint, SIUnits.CELSIUS);
logger.debug("heatingSetpoint: {}", heatingSetpoint);
logger.debug("coolingSetpoint: {}", coolingSetpoint);
setState(State.SUCCEEDED);
try { try {
Integer iHeatingSetpoint = (int) (mm.getValues().get(0x21).getComputedValue() / 128.);
Integer iCoolingSetpoint = (int) (mm.getValues().get(0x20).getComputedValue() / 128.);
this.heatingSetpoint = new QuantityType<Temperature>(iHeatingSetpoint, SIUnits.CELSIUS);
this.coolingSetpoint = new QuantityType<Temperature>(iCoolingSetpoint, SIUnits.CELSIUS);
logger.debug("heatingSetpoint: {}", heatingSetpoint);
logger.debug("coolingSetpoint: {}", coolingSetpoint);
setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) { } catch (Exception e) {
setState(State.FAILED); setState(State.FAILED);

View File

@ -18,6 +18,7 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
/** /**
* This command returns the firmware version * This command returns the firmware version
@ -39,10 +40,16 @@ public class GetVersionCommand extends BRC1HCommand {
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {
// In this method, we intentionally do not check for null values in mv45 and mv46. In case of null pointer MadokaValue mValue45 = mm.getValues().get(0x45);
// access, it will be catched by the global exception and be reported as a Parsing Reponse exception. MadokaValue mValue46 = mm.getValues().get(0x46);
byte[] mv45 = mm.getValues().get(0x45).getRawValue(); if (mValue45 == null || mValue46 == null) {
byte[] mv46 = mm.getValues().get(0x46).getRawValue(); String message = "version value is null when handling the response";
setState(State.FAILED);
throw new MadokaParsingException(message);
}
byte[] mv45 = mValue45.getRawValue();
byte[] mv46 = mValue46.getRawValue();
if (mv45 == null || mv45.length != 3 || mv46 == null || mv46.length != 2) { if (mv45 == null || mv45.length != 3 || mv46 == null || mv46.length != 2) {
setState(State.FAILED); setState(State.FAILED);
@ -60,7 +67,12 @@ public class GetVersionCommand extends BRC1HCommand {
this.communicationControllerVersion = commControllerMajor + "." + commControllerMinor; this.communicationControllerVersion = commControllerMajor + "." + commControllerMinor;
setState(State.SUCCEEDED); setState(State.SUCCEEDED);
executor.execute(() -> listener.receivedResponse(this)); try {
executor.execute(() -> listener.receivedResponse(this));
} catch (Exception e) {
setState(State.FAILED);
throw new MadokaParsingException(e);
}
} }
@Override @Override

View File

@ -18,8 +18,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaParsingException;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* Command used to reset the Clean Filter Indicator timer * Command used to reset the Clean Filter Indicator timer
@ -30,8 +28,6 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public class ResetCleanFilterTimerCommand extends BRC1HCommand { public class ResetCleanFilterTimerCommand extends BRC1HCommand {
private final Logger logger = LoggerFactory.getLogger(ResetCleanFilterTimerCommand.class);
@Override @Override
public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm) public void handleResponse(Executor executor, ResponseListener listener, MadokaMessage mm)
throws MadokaParsingException { throws MadokaParsingException {

View File

@ -33,7 +33,7 @@ import org.openhab.core.thing.binding.ThingHandler;
/** /**
* *
* @author Benjamin Lafois * @author Benjamin Lafois - Initial contribution
* *
*/ */
@NonNullByDefault @NonNullByDefault

View File

@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.*;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaMessage;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.MadokaValue;
@ -26,9 +27,10 @@ import org.openhab.core.library.types.OnOffType;
/** /**
* *
* @author blafois * @author blafois - Initial contribution
* *
*/ */
@NonNullByDefault
public class MadokaMessageTest { public class MadokaMessageTest {
@Test @Test
@ -42,8 +44,7 @@ public class MadokaMessageTest {
boolean powered = true; boolean powered = true;
MadokaValue mv = new MadokaValue(0x20, 1, new byte[] { 1 }); MadokaValue mv = new MadokaValue(0x20, 1, new byte[] { 1 });
byte[][] resp = MadokaMessage.createRequest(new SetPowerstateCommand(OnOffType.ON), mv); byte[][] resp = MadokaMessage.createRequest(new SetPowerstateCommand(OnOffType.ON), mv);
assertArrayEquals( assertArrayEquals(new byte[] { 0x00, 0x07, 0x00, 0x40, 0x20, 0x20, 0x01, (byte) (powered ? 0x01 : 0x00) },
new byte[] { 0x00, 0x07, 0x00, 0x40, 0x20, 0x20, 0x01, (byte) (powered == true ? 0x01 : 0x00) },
resp[0]); resp[0]);
} }

View File

@ -14,7 +14,7 @@ package org.openhab.binding.bluetooth.daikinmadoka.internal;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.commands.GetCleanFilterIndicatorCommand; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.commands.GetCleanFilterIndicatorCommand;
import org.openhab.binding.bluetooth.daikinmadoka.internal.model.commands.GetEyeBrightnessCommand; import org.openhab.binding.bluetooth.daikinmadoka.internal.model.commands.GetEyeBrightnessCommand;
@ -34,9 +34,10 @@ import org.openhab.binding.bluetooth.daikinmadoka.internal.model.commands.SetSet
/** /**
* *
* @author blafois * @author blafois - Initial contribution
* *
*/ */
@NonNullByDefault
public class UartProcessorTest implements ResponseListener { public class UartProcessorTest implements ResponseListener {
private boolean completed = false; private boolean completed = false;
@ -70,63 +71,63 @@ public class UartProcessorTest implements ResponseListener {
} }
@Override @Override
public void receivedResponse(byte @NonNull [] bytes) { public void receivedResponse(byte[] bytes) {
this.completed = true; this.completed = true;
} }
@Override @Override
public void receivedResponse(@NonNull GetVersionCommand command) { public void receivedResponse(GetVersionCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetFanspeedCommand command) { public void receivedResponse(GetFanspeedCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetOperationmodeCommand command) { public void receivedResponse(GetOperationmodeCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetPowerstateCommand command) { public void receivedResponse(GetPowerstateCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetSetpointCommand command) { public void receivedResponse(GetSetpointCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetIndoorOutoorTemperatures command) { public void receivedResponse(GetIndoorOutoorTemperatures command) {
} }
@Override @Override
public void receivedResponse(@NonNull SetPowerstateCommand command) { public void receivedResponse(SetPowerstateCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull SetSetpointCommand command) { public void receivedResponse(SetSetpointCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull SetOperationmodeCommand command) { public void receivedResponse(SetOperationmodeCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull SetFanspeedCommand command) { public void receivedResponse(SetFanspeedCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetOperationHoursCommand command) { public void receivedResponse(GetOperationHoursCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetEyeBrightnessCommand command) { public void receivedResponse(GetEyeBrightnessCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull GetCleanFilterIndicatorCommand command) { public void receivedResponse(GetCleanFilterIndicatorCommand command) {
} }
@Override @Override
public void receivedResponse(@NonNull SetEyeBrightnessCommand command) { public void receivedResponse(SetEyeBrightnessCommand command) {
} }
} }