[openwebnet] Improve shutterRun calibration (#14357)

* [openwebnet] improved shutterRun calibration and README
* [openwebnet] added Thing status detail when bridge is offline

--------

Signed-off-by: Massimo Valla <mvcode00@gmail.com>
This commit is contained in:
M Valla
2023-05-07 17:11:44 +02:00
committed by GitHub
parent da1a95fbdd
commit 5fe6d325a3
5 changed files with 79 additions and 57 deletions

View File

@@ -47,7 +47,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link OpenWebNetAutomationHandler} is responsible for handling commands/messages for an Automation OpenWebNet
* The {@link OpenWebNetAutomationHandler} is responsible for handling
* commands/messages for an Automation OpenWebNet
* device. It extends the abstract {@link OpenWebNetThingHandler}.
*
* @author Massimo Valla - Initial contribution
@@ -247,18 +248,21 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
positionRequested = percent;
} else if (shutterRun >= 1000 && positionEstimation != POSITION_UNKNOWN) {
// these two must be known to calculate moveTime.
// Calculate how much time we have to move and set a deadline to stop after that time
// Calculate how much time we have to move and set a deadline to stop after that
// time
int moveTime = Math
.round(((float) Math.abs(percent - positionEstimation) / POSITION_MAX_STEPS * shutterRun));
logger.debug("# {} # target moveTime={}", deviceWhere, moveTime);
if (moveTime > MIN_STEP_TIME_MSEC) {
ScheduledFuture<?> mSch = moveSchedule;
if (mSch != null && !mSch.isDone()) {
// a moveSchedule was already scheduled and is not done... let's cancel the schedule
// a moveSchedule was already scheduled and is not done... let's cancel the
// schedule
mSch.cancel(false);
logger.debug("# {} # new XX% requested, old moveSchedule cancelled", deviceWhere);
}
// send a requestFirmwareVersion message to BUS gateways to wake up the CMD connection before
// send a requestFirmwareVersion message to BUS gateways to wake up the CMD
// connection before
// sending further cmds
OpenWebNetBridgeHandler h = bridgeHandler;
if (h != null && h.isBusGateway()) {
@@ -270,7 +274,8 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
}
}
}
// REMINDER: start the schedule BEFORE sending the command, because the synch command waits for
// REMINDER: start the schedule BEFORE sending the command, because the synch
// command waits for
// ACK and can take some 300ms
logger.debug("# {} # Starting schedule...", deviceWhere);
moveSchedule = scheduler.schedule(() -> {
@@ -294,7 +299,7 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
}
} else {
logger.info(
"Command {} cannot be executed: unknown position or shutterRun configuration params not/wrongly set (thing={})",
"Command {} cannot be executed: UNDEF position or shutterRun configuration parameter not/wrongly set (thing={})",
command, thing.getUID());
}
}
@@ -312,12 +317,14 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
protected void handleMessage(BaseOpenMessage msg) {
logger.debug("handleMessage({}) for thing: {}", msg, thing.getUID());
updateAutomationState((Automation) msg);
// REMINDER: update automation state, and only after update thing status using the super method, to avoid delays
// REMINDER: update automation state, and only after update thing status using
// the super method, to avoid delays
super.handleMessage(msg);
}
/**
* Updates automation device state based on the Automation message received from OWN network
* Updates automation device state based on the Automation message received from
* OWN network
*
* @param msg the Automation message
*/
@@ -345,10 +352,12 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
logger.debug("& {} & CALIBRATION - started going ALL DOWN...", deviceWhere);
}
} else if (msg.isStop()) {
long stoppedAt = System.currentTimeMillis();
long measuredRuntime = System.currentTimeMillis() - startedMovingAtTS;
if (calibrating == CALIBRATION_GOING_DOWN && shutterRun == SHUTTER_RUN_UNDEFINED) {
shutterRun = (int) (stoppedAt - startedMovingAtTS);
logger.debug("& {} & CALIBRATION - reached DOWN ---> shutterRun={}", deviceWhere, shutterRun);
// since there are transmission delays we set shutterRun slightly less (-500ms
// and -2%) than measuredRuntime
shutterRun = (int) ((measuredRuntime - 500) * 0.98);
logger.debug("& {} & CALIBRATION - reached DOWN : measuredRuntime={}", deviceWhere, measuredRuntime);
updateMovingState(MOVING_STATE_STOPPED);
logger.debug("& {} & CALIBRATION - COMPLETED, now going to {}%", deviceWhere, positionRequested);
handleShutterCommand(new PercentType(positionRequested));
@@ -416,7 +425,8 @@ public class OpenWebNetAutomationHandler extends OpenWebNetThingHandler {
}
/**
* Updates positionEstimation and then channel state based on movedTime and current movingState
* Updates positionEstimation and then channel state based on movedTime and
* current movingState
*/
private void updatePosition() {
int newPos = POSITION_UNKNOWN;

View File

@@ -517,7 +517,7 @@ public class OpenWebNetBridgeHandler extends ConfigStatusBridgeHandler implement
|| (discoveryByActivation && !scanIsActive))) {
discoverByActivation(baseMsg);
} else {
logger.debug("ownId={} has NO DEVICE associated, ignoring it", ownId);
logger.debug("ownId={} has NO DEVICE associated to bridge {}: ignoring it", ownId, thing.getUID());
}
} else {
deviceHandler.handleMessage(baseMsg);

View File

@@ -46,9 +46,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link OpenWebNetThingHandler} is responsible for handling commands for an OpenWebNet device.
* It's the abstract class for all OpenWebNet things. It should be extended by each specific OpenWebNet category of
* device (WHO).
* The {@link OpenWebNetThingHandler} is responsible for handling commands for
* an OpenWebNet device.
* It's the abstract class for all OpenWebNet things. It should be extended by
* each specific OpenWebNet category of device (WHO).
*
* @author Massimo Valla - Initial contribution
*/
@@ -118,7 +119,7 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.NONE, "@text/unknown.waiting-state");
} else if (bridgeStatusInfo.getStatus() == ThingStatus.OFFLINE) {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE, "@text/offline.bridge-offline");
}
}
@@ -157,8 +158,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
protected abstract void handleChannelCommand(ChannelUID channel, Command command);
/**
* Handle incoming message from OWN network via bridge Thing, directed to this device.
* It should be further implemented by each specific device handler.
* Handle incoming message from OWN network via bridge Thing, directed to this
* device. It should be further implemented by each specific device handler.
*
* @param msg the message to handle
*/
@@ -203,8 +204,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
}
/**
* Request the state for the specified channel. If no answer is received within THING_STATE_REQ_TIMEOUT_SEC, it is
* put OFFLINE.
* Request the state for the specified channel. If no answer is received within
* THING_STATE_REQ_TIMEOUT_SEC, it is put OFFLINE.
* The method must be further implemented by each specific handler.
*
* @param channel the {@link ChannelUID} to request the state for
@@ -217,7 +218,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-where");
return;
}
// set a schedule to put device OFFLINE if no answer is received after THING_STATE_REQ_TIMEOUT_SEC
// set a schedule to put device OFFLINE if no answer is received after
// THING_STATE_REQ_TIMEOUT_SEC
requestChannelStateTimeout = scheduler.schedule(() -> {
if (thing.getStatus().equals(ThingStatus.UNKNOWN)) {
logger.debug("requestChannelState() TIMEOUT for thing {}", thing.getUID());
@@ -228,21 +230,24 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
}
/**
* Refresh a device, possibly using a single OWN command if refreshAll=true and if supported.
* The method must be further implemented by each specific handler.
* Refresh a device, possibly using a single OWN command if refreshAll=true and
* if supported. The method must be further implemented by each specific
* handler.
*
* @param refreshAll true if all devices for this handler must be refreshed with a single OWN command, if supported,
* otherwise just refresh the single device.
* @param refreshAll true if all devices for this handler must be refreshed with
* a single OWN command, if supported, otherwise just refresh
* the single device.
*/
protected abstract void refreshDevice(boolean refreshAll);
/**
* If the subclass supports refreshing all devices with a single OWN command, returns the last TS when a refreshAll
* was requested, or 0 if not requested yet. If not supported return -1 (default).
* If the subclass supports refreshing all devices with a single OWN command,
* returns the last TS when a refreshAll was requested, or 0 if not requested
* yet. If not supported return -1 (default).
* It must be implemented by each subclass that supports all devices refresh.
*
* @return timestamp when last refreshAll command was sent, 0 if not requested yet, or -1 if it's not supported by
* subclass.
* @return timestamp when last refreshAll command was sent, 0 if not requested
* yet, or -1 if it's not supported by subclass.
*/
protected long getRefreshAllLastTS() {
return -1;
@@ -266,8 +271,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
logger.debug("--- refreshAllDevices() : refresh all devices sent {}msec ago, skipping... ({})",
ALL_DEVICES_REFRESH_INTERVAL_MSEC, thing.getUID());
}
// sometimes GENERAL (e.g. #*1*0##) refresh requests do not return state for all devices, so let's
// schedule another single refresh device, just in case
// sometimes GENERAL (e.g. #*1*0##) refresh requests do not return state for all
// devices, so let's schedule another single refresh device, just in case
refreshTimeout = scheduler.schedule(() -> {
if (thing.getStatus().equals(ThingStatus.UNKNOWN)) {
logger.debug(
@@ -286,8 +291,9 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
}
/**
* Abstract builder for device Where address, to be implemented by each subclass to choose the right Where subclass
* (the method is used only if the Thing is associated to a BUS gateway).
* Abstract builder for device Where address, to be implemented by each subclass
* to choose the right Where subclass (the method is used only if the Thing is
* associated to a BUS gateway).
*
* @param wStr the WHERE string
*/
@@ -312,7 +318,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
}
/**
* Helper method to return a Quantity from a Number value or UnDefType.NULL if value is null
* Helper method to return a Quantity from a Number value or UnDefType.NULL if
* value is null
*
* @param value to be used
* @param unit to be used
@@ -323,7 +330,8 @@ public abstract class OpenWebNetThingHandler extends BaseThingHandler {
}
/**
* Returns a prefix String for ownId specific for each handler. To be implemented by sub-classes.
* Returns a prefix String for ownId specific for each handler.
* To be implemented by sub-classes.
*
* @return
*/

View File

@@ -290,13 +290,14 @@ channel-type.openwebnet.zoneAlarmTimestamp.description = Current alarm's timesta
# thing status descriptions
offline.comm-error-disconnected = Disconnected from gateway.
offline.comm-error-timeout = Connection to gateway timed out.
offline.comm-error-connection = Could not connect to gateway.
offline.comm-error-state = Could not get channel state.
offline.conf-error-no-ip-address = Cannot connect to gateway. No host/IP address has been provided in configuration.
offline.conf-error-no-serial-port = Cannot connect to gateway. No serial port has been provided in configuration.
offline.conf-error-where = OpenWebNet Address (where) parameter in configuration is null or invalid.
offline.conf-error-no-bridge = No bridge associated. Assign a bridge in configuration.
offline.conf-error-auth = Authentication failed. Check gateway password in configuration.
offline.comm-error-disconnected = Disconnected from gateway
offline.comm-error-timeout = Connection to gateway timed out
offline.comm-error-connection = Could not connect to gateway
offline.comm-error-state = Could not get channel state
offline.conf-error-no-ip-address = Cannot connect to gateway. No host/IP address has been provided in configuration
offline.conf-error-no-serial-port = Cannot connect to gateway. No serial port has been provided in configuration
offline.conf-error-where = OpenWebNet Address (where) parameter in configuration is null or invalid
offline.conf-error-no-bridge = No bridge associated. Assign a bridge in configuration
offline.conf-error-auth = Authentication failed. Check gateway password in configuration
offline.bridge-offline = Bridge offline
unknown.waiting-state = Waiting state update...