Improve error handling for unknown shades and timeouts. (#12181)

Fixes #12180

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen 2022-02-03 23:45:41 +01:00 committed by GitHub
parent 02776d8585
commit 97db73938d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 145 additions and 54 deletions

View File

@ -50,6 +50,7 @@ import org.openhab.binding.hdpowerview.internal.api.responses.Survey;
import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException; import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException; import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubShadeTimeoutException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -208,15 +209,16 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData moveShade(int shadeId, ShadePosition position) public ShadeData moveShade(int shadeId, ShadePosition position) throws HubInvalidResponseException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubProcessingException, HubMaintenanceException, HubShadeTimeoutException {
String jsonRequest = gson.toJson(new ShadeMove(position)); String jsonRequest = gson.toJson(new ShadeMove(position));
String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest); String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
} }
private ShadeData shadeDataFromJson(String json) throws HubInvalidResponseException { private ShadeData shadeDataFromJson(String json) throws HubInvalidResponseException, HubShadeTimeoutException {
try { try {
Shade shade = gson.fromJson(json, Shade.class); Shade shade = gson.fromJson(json, Shade.class);
if (shade == null) { if (shade == null) {
@ -226,6 +228,9 @@ public class HDPowerViewWebTargets {
if (shadeData == null) { if (shadeData == null) {
throw new HubInvalidResponseException("Missing 'shade.shade' element"); throw new HubInvalidResponseException("Missing 'shade.shade' element");
} }
if (Boolean.TRUE.equals(shadeData.timedOut)) {
throw new HubShadeTimeoutException("Timeout when sending request to the shade");
}
return shadeData; return shadeData;
} catch (JsonParseException e) { } catch (JsonParseException e) {
throw new HubInvalidResponseException("Error parsing shade response", e); throw new HubInvalidResponseException("Error parsing shade response", e);
@ -240,9 +245,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData stopShade(int shadeId) public ShadeData stopShade(int shadeId) throws HubInvalidResponseException, HubProcessingException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubMaintenanceException, HubShadeTimeoutException {
String jsonRequest = gson.toJson(new ShadeStop()); String jsonRequest = gson.toJson(new ShadeStop());
String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest); String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
@ -256,9 +262,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData jogShade(int shadeId) public ShadeData jogShade(int shadeId) throws HubInvalidResponseException, HubProcessingException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubMaintenanceException, HubShadeTimeoutException {
String jsonRequest = gson.toJson(new ShadeJog()); String jsonRequest = gson.toJson(new ShadeJog());
String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest); String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
@ -272,9 +279,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData calibrateShade(int shadeId) public ShadeData calibrateShade(int shadeId) throws HubInvalidResponseException, HubProcessingException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubMaintenanceException, HubShadeTimeoutException {
String jsonRequest = gson.toJson(new ShadeCalibrate()); String jsonRequest = gson.toJson(new ShadeCalibrate());
String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest); String jsonResponse = invoke(HttpMethod.PUT, shades + Integer.toString(shadeId), null, jsonRequest);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
@ -574,9 +582,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData getShade(int shadeId) public ShadeData getShade(int shadeId) throws HubInvalidResponseException, HubProcessingException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubMaintenanceException, HubShadeTimeoutException {
String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId), null, null); String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId), null, null);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
} }
@ -591,9 +600,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData refreshShadePosition(int shadeId) public ShadeData refreshShadePosition(int shadeId)
throws JsonParseException, HubProcessingException, HubMaintenanceException { throws JsonParseException, HubProcessingException, HubMaintenanceException, HubShadeTimeoutException {
String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId), String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId),
Query.of("refresh", Boolean.toString(true)), null); Query.of("refresh", Boolean.toString(true)), null);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);
@ -636,9 +646,10 @@ public class HDPowerViewWebTargets {
* @throws HubInvalidResponseException if response is invalid * @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
* @throws HubShadeTimeoutException if the shade did not respond to a request
*/ */
public ShadeData refreshShadeBatteryLevel(int shadeId) public ShadeData refreshShadeBatteryLevel(int shadeId) throws HubInvalidResponseException, HubProcessingException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubMaintenanceException, HubShadeTimeoutException {
String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId), String jsonResponse = invoke(HttpMethod.GET, shades + Integer.toString(shadeId),
Query.of("updateBatteryLevel", Boolean.toString(true)), null); Query.of("updateBatteryLevel", Boolean.toString(true)), null);
return shadeDataFromJson(jsonResponse); return shadeDataFromJson(jsonResponse);

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2022 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.hdpowerview.internal.exceptions;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* The {@link HubShadeTimeoutException} is a custom exception for the HD PowerView Hub
* which is thrown when a shade does not respond to a request.
*
* @author @author Jacob Laursen - Initial contribution
*/
@NonNullByDefault
public class HubShadeTimeoutException extends HubException {
private static final long serialVersionUID = -362347489903471011L;
public HubShadeTimeoutException(String message) {
super(message);
}
}

View File

@ -58,6 +58,7 @@ import org.openhab.core.thing.ChannelUID;
import org.openhab.core.thing.Thing; import org.openhab.core.thing.Thing;
import org.openhab.core.thing.ThingStatus; import org.openhab.core.thing.ThingStatus;
import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingStatusDetail;
import org.openhab.core.thing.ThingStatusInfo;
import org.openhab.core.thing.ThingUID; import org.openhab.core.thing.ThingUID;
import org.openhab.core.thing.binding.BaseBridgeHandler; import org.openhab.core.thing.binding.BaseBridgeHandler;
import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.thing.binding.ThingHandler;
@ -204,7 +205,11 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
if (childHandler instanceof HDPowerViewShadeHandler) { if (childHandler instanceof HDPowerViewShadeHandler) {
ShadeData shadeData = pendingShadeInitializations.remove(childThing.getUID()); ShadeData shadeData = pendingShadeInitializations.remove(childThing.getUID());
if (shadeData != null) { if (shadeData != null) {
if (shadeData.id > 0) {
updateShadeThing(shadeData.id, childThing, shadeData); updateShadeThing(shadeData.id, childThing, shadeData);
} else {
updateUnknownShadeThing(childThing);
}
} }
} }
super.childHandlerInitialized(childHandler, childThing); super.childHandlerInitialized(childHandler, childThing);
@ -354,15 +359,15 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
Thing thing = item.getKey(); Thing thing = item.getKey();
int shadeId = item.getValue(); int shadeId = item.getValue();
ShadeData shadeData = idShadeDataMap.get(shadeId); ShadeData shadeData = idShadeDataMap.get(shadeId);
if (shadeData != null) {
updateShadeThing(shadeId, thing, shadeData); updateShadeThing(shadeId, thing, shadeData);
} else {
updateUnknownShadeThing(thing);
}
} }
} }
private void updateShadeThing(int shadeId, Thing thing, @Nullable ShadeData shadeData) { private void updateShadeThing(int shadeId, Thing thing, ShadeData shadeData) {
if (shadeData == null) {
logger.debug("Shade '{}' has no data in hub", shadeId);
return;
}
HDPowerViewShadeHandler thingHandler = ((HDPowerViewShadeHandler) thing.getHandler()); HDPowerViewShadeHandler thingHandler = ((HDPowerViewShadeHandler) thing.getHandler());
if (thingHandler == null) { if (thingHandler == null) {
logger.debug("Shade '{}' handler not initialized", shadeId); logger.debug("Shade '{}' handler not initialized", shadeId);
@ -390,6 +395,36 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
} }
} }
private void updateUnknownShadeThing(Thing thing) {
String shadeId = thing.getUID().getId();
logger.debug("Shade '{}' has no data in hub", shadeId);
HDPowerViewShadeHandler thingHandler = ((HDPowerViewShadeHandler) thing.getHandler());
if (thingHandler == null) {
logger.debug("Shade '{}' handler not initialized", shadeId);
pendingShadeInitializations.put(thing.getUID(), new ShadeData());
return;
}
ThingStatus thingStatus = thingHandler.getThing().getStatus();
switch (thingStatus) {
case UNKNOWN:
case ONLINE:
case OFFLINE:
thing.setStatusInfo(new ThingStatusInfo(ThingStatus.OFFLINE, ThingStatusDetail.GONE,
"@text/offline.gone.shade-unknown-to-hub"));
break;
case UNINITIALIZED:
case INITIALIZING:
logger.debug("Shade '{}' handler not yet ready; status: {}", shadeId, thingStatus);
pendingShadeInitializations.put(thing.getUID(), new ShadeData());
break;
case REMOVING:
case REMOVED:
default:
logger.debug("Ignoring shade status update for shade '{}' in status {}", shadeId, thingStatus);
break;
}
}
private List<Scene> fetchScenes() private List<Scene> fetchScenes()
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException {
HDPowerViewWebTargets webTargets = this.webTargets; HDPowerViewWebTargets webTargets = this.webTargets;
@ -601,6 +636,11 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
Map<Thing, Integer> thingIdMap = getShadeThingIdMap(); Map<Thing, Integer> thingIdMap = getShadeThingIdMap();
for (Entry<Thing, Integer> item : thingIdMap.entrySet()) { for (Entry<Thing, Integer> item : thingIdMap.entrySet()) {
Thing thing = item.getKey(); Thing thing = item.getKey();
if (thing.getStatusInfo().getStatusDetail() == ThingStatusDetail.GONE) {
// Skip shades unknown to the Hub.
logger.debug("Shade '{}' is unknown, skipping position refresh", item.getValue());
continue;
}
ThingHandler handler = thing.getHandler(); ThingHandler handler = thing.getHandler();
if (handler instanceof HDPowerViewShadeHandler) { if (handler instanceof HDPowerViewShadeHandler) {
((HDPowerViewShadeHandler) handler).requestRefreshShadePosition(); ((HDPowerViewShadeHandler) handler).requestRefreshShadePosition();
@ -615,6 +655,11 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
Map<Thing, Integer> thingIdMap = getShadeThingIdMap(); Map<Thing, Integer> thingIdMap = getShadeThingIdMap();
for (Entry<Thing, Integer> item : thingIdMap.entrySet()) { for (Entry<Thing, Integer> item : thingIdMap.entrySet()) {
Thing thing = item.getKey(); Thing thing = item.getKey();
if (thing.getStatusInfo().getStatusDetail() == ThingStatusDetail.GONE) {
// Skip shades unknown to the Hub.
logger.debug("Shade '{}' is unknown, skipping battery level refresh", item.getValue());
continue;
}
ThingHandler handler = thing.getHandler(); ThingHandler handler = thing.getHandler();
if (handler instanceof HDPowerViewShadeHandler) { if (handler instanceof HDPowerViewShadeHandler) {
((HDPowerViewShadeHandler) handler).requestRefreshShadeBatteryLevel(); ((HDPowerViewShadeHandler) handler).requestRefreshShadeBatteryLevel();

View File

@ -37,6 +37,7 @@ import org.openhab.binding.hdpowerview.internal.exceptions.HubException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException; import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException; import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubShadeTimeoutException;
import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PercentType;
@ -177,6 +178,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
} }
} catch (HubMaintenanceException e) { } catch (HubMaintenanceException e) {
// exceptions are logged in HDPowerViewWebTargets // exceptions are logged in HDPowerViewWebTargets
} catch (HubShadeTimeoutException e) {
logger.warn("Shade {} timeout when sending command {}", shadeId, command);
} catch (HubException e) { } catch (HubException e) {
// ScheduledFutures will be cancelled by dispose(), naturally causing InterruptedException in invoke() // ScheduledFutures will be cancelled by dispose(), naturally causing InterruptedException in invoke()
// for any ongoing requests. Logging this would only cause confusion. // for any ongoing requests. Logging this would only cause confusion.
@ -187,7 +190,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
} }
private void handleShadeCommand(String channelId, Command command, HDPowerViewWebTargets webTargets, int shadeId) private void handleShadeCommand(String channelId, Command command, HDPowerViewWebTargets webTargets, int shadeId)
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException,
HubShadeTimeoutException {
switch (channelId) { switch (channelId) {
case CHANNEL_SHADE_POSITION: case CHANNEL_SHADE_POSITION:
if (command instanceof PercentType) { if (command instanceof PercentType) {
@ -244,10 +248,9 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
/** /**
* Update the state of the channels based on the ShadeData provided. * Update the state of the channels based on the ShadeData provided.
* *
* @param shadeData the ShadeData to be used; may be null. * @param shadeData the ShadeData to be used.
*/ */
protected void onReceiveUpdate(@Nullable ShadeData shadeData) { protected void onReceiveUpdate(ShadeData shadeData) {
if (shadeData != null) {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
updateCapabilities(shadeData); updateCapabilities(shadeData);
updateSoftProperties(shadeData); updateSoftProperties(shadeData);
@ -256,14 +259,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
if (shadePosition != null) { if (shadePosition != null) {
updatePositionStates(shadePosition); updatePositionStates(shadePosition);
} }
updateBatteryLevelStates(shadeData.batteryStatus); updateBatteryStates(shadeData.batteryStatus, shadeData.batteryStrength);
updateState(CHANNEL_SHADE_BATTERY_VOLTAGE,
shadeData.batteryStrength > 0 ? new QuantityType<>(shadeData.batteryStrength / 10, Units.VOLT)
: UnDefType.UNDEF);
updateState(CHANNEL_SHADE_SIGNAL_STRENGTH, new DecimalType(shadeData.signalStrength)); updateState(CHANNEL_SHADE_SIGNAL_STRENGTH, new DecimalType(shadeData.signalStrength));
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
}
} }
private void updateCapabilities(ShadeData shade) { private void updateCapabilities(ShadeData shade) {
@ -404,6 +401,12 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
updateState(CHANNEL_SHADE_SECONDARY_POSITION, shadePos.getState(capabilities, SECONDARY_POSITION)); updateState(CHANNEL_SHADE_SECONDARY_POSITION, shadePos.getState(capabilities, SECONDARY_POSITION));
} }
private void updateBatteryStates(int batteryStatus, double batteryStrength) {
updateBatteryLevelStates(batteryStatus);
updateState(CHANNEL_SHADE_BATTERY_VOLTAGE,
batteryStrength > 0 ? new QuantityType<>(batteryStrength / 10, Units.VOLT) : UnDefType.UNDEF);
}
private void updateBatteryLevelStates(int batteryStatus) { private void updateBatteryLevelStates(int batteryStatus) {
int mappedValue; int mappedValue;
switch (batteryStatus) { switch (batteryStatus) {
@ -427,7 +430,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
} }
private void moveShade(CoordinateSystem coordSys, int newPercent, HDPowerViewWebTargets webTargets, int shadeId) private void moveShade(CoordinateSystem coordSys, int newPercent, HDPowerViewWebTargets webTargets, int shadeId)
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException,
HubShadeTimeoutException {
ShadePosition newPosition = null; ShadePosition newPosition = null;
// (try to) read the positions from the hub // (try to) read the positions from the hub
ShadeData shadeData = webTargets.getShade(shadeId); ShadeData shadeData = webTargets.getShade(shadeId);
@ -443,21 +447,21 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
updateShadePositions(shadeData); updateShadePositions(shadeData);
} }
private void stopShade(HDPowerViewWebTargets webTargets, int shadeId) private void stopShade(HDPowerViewWebTargets webTargets, int shadeId) throws HubInvalidResponseException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubProcessingException, HubMaintenanceException, HubShadeTimeoutException {
updateShadePositions(webTargets.stopShade(shadeId)); updateShadePositions(webTargets.stopShade(shadeId));
// Positions in response from stop motion is not updated to to actual positions yet, // Positions in response from stop motion is not updated to to actual positions yet,
// so we need to request hard refresh. // so we need to request hard refresh.
requestRefreshShadePosition(); requestRefreshShadePosition();
} }
private void identifyShade(HDPowerViewWebTargets webTargets, int shadeId) private void identifyShade(HDPowerViewWebTargets webTargets, int shadeId) throws HubInvalidResponseException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubProcessingException, HubMaintenanceException, HubShadeTimeoutException {
updateShadePositions(webTargets.jogShade(shadeId)); updateShadePositions(webTargets.jogShade(shadeId));
} }
private void calibrateShade(HDPowerViewWebTargets webTargets, int shadeId) private void calibrateShade(HDPowerViewWebTargets webTargets, int shadeId) throws HubInvalidResponseException,
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { HubProcessingException, HubMaintenanceException, HubShadeTimeoutException {
updateShadePositions(webTargets.calibrateShade(shadeId)); updateShadePositions(webTargets.calibrateShade(shadeId));
} }
@ -526,6 +530,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
switch (kind) { switch (kind) {
case POSITION: case POSITION:
shadeData = webTargets.refreshShadePosition(shadeId); shadeData = webTargets.refreshShadePosition(shadeId);
updateShadePositions(shadeData);
updateHardProperties(shadeData);
break; break;
case SURVEY: case SURVEY:
Survey survey = webTargets.getShadeSurvey(shadeId); Survey survey = webTargets.getShadeSurvey(shadeId);
@ -534,19 +540,14 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
} else { } else {
logger.warn("No response from shade {} survey", shadeId); logger.warn("No response from shade {} survey", shadeId);
} }
return; break;
case BATTERY_LEVEL: case BATTERY_LEVEL:
shadeData = webTargets.refreshShadeBatteryLevel(shadeId); shadeData = webTargets.refreshShadeBatteryLevel(shadeId);
updateBatteryStates(shadeData.batteryStatus, shadeData.batteryStrength);
break; break;
default: default:
throw new NotSupportedException("Unsupported refresh kind " + kind.toString()); throw new NotSupportedException("Unsupported refresh kind " + kind.toString());
} }
if (Boolean.TRUE.equals(shadeData.timedOut)) {
logger.warn("Shade {} wireless refresh time out", shadeId);
} else if (kind == RefreshKind.POSITION) {
updateShadePositions(shadeData);
updateHardProperties(shadeData);
}
} catch (HubInvalidResponseException e) { } catch (HubInvalidResponseException e) {
Throwable cause = e.getCause(); Throwable cause = e.getCause();
if (cause == null) { if (cause == null) {
@ -556,6 +557,8 @@ public class HDPowerViewShadeHandler extends AbstractHubbedThingHandler {
} }
} catch (HubMaintenanceException e) { } catch (HubMaintenanceException e) {
// exceptions are logged in HDPowerViewWebTargets // exceptions are logged in HDPowerViewWebTargets
} catch (HubShadeTimeoutException e) {
logger.info("Shade {} wireless refresh time out", shadeId);
} catch (HubException e) { } catch (HubException e) {
// ScheduledFutures will be cancelled by dispose(), naturally causing InterruptedException in invoke() // ScheduledFutures will be cancelled by dispose(), naturally causing InterruptedException in invoke()
// for any ongoing requests. Logging this would only cause confusion. // for any ongoing requests. Logging this would only cause confusion.

View File

@ -52,6 +52,7 @@ channel-type.hdpowerview.shade-vane.description = The opening of the slats in th
offline.conf-error.no-host-address = Host address must be set offline.conf-error.no-host-address = Host address must be set
offline.conf-error.invalid-id = Configuration 'id' not a valid integer offline.conf-error.invalid-id = Configuration 'id' not a valid integer
offline.conf-error.invalid-bridge-handler = Invalid bridge handler offline.conf-error.invalid-bridge-handler = Invalid bridge handler
offline.gone.shade-unknown-to-hub = Shade is unknown to Hub
# dynamic channels # dynamic channels