mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-25 14:55:55 +01:00
[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:
parent
da1a95fbdd
commit
5fe6d325a3
@ -258,21 +258,22 @@ OPEN command to execute: *5*8#134##
|
||||
|
||||
#### `shutter` position
|
||||
|
||||
For Percent commands and position feedback to work correctly, the `shutterRun` Thing config parameter must be configured equal to the time (in ms) to go from full UP to full DOWN. It's possible to enter a value manually or set `shutterRun=AUTO` (default) to calibrate `shutterRun` automatically.
|
||||
For Percent commands and position feedback to work correctly, the `shutterRun` Thing config parameter must be configured equal to the time (in milliseconds) to go from full UP to full DOWN. It's possible to enter a value manually or set `shutterRun=AUTO` (default) to calibrate `shutterRun` automatically.
|
||||
|
||||
_Automatic calibration of `shutterRun`_
|
||||
##### Automatic calibration of `shutterRun`
|
||||
|
||||
If `shutterRun` is set to AUTO a _UP >> DOWN >> Position%_ cycle will be performed automatically the first time a Percent command is sent to the shutter. The binding then relies on the _STOP_ command sent by the actuator at the stop time set in the actuator's advanced configuration in the My Home Suite. Therefore the binding's automatic calibration of `shutterRun` only works correctly if the stop time is set to the time the shutters need to go from full UP to full DOWN.
|
||||
When `shutterRun` is set to `AUTO`, a _UP >> DOWN >> Position%_ cycle will be performed automatically the first time a Percent command is sent to the shutter: this way the binding will calculate the shutter "run time" and set the `shutterRun` parameter accordingly.
|
||||
|
||||
Older actuators that come without an ID and do not support advanced configuration via the My Home Suite have a fixed stop time of 60 seconds. In this case auto calibration of the binding cannot be used and `shutterRun` has to be set manually.
|
||||
**NOTE**
|
||||
A "stop time" parameter is usually set on the physical actuator (eg. F411U2) either via virtual configuration (MyHOME_Suite: parameters named "Stop time" or "M") or physical configuration (jumpers): check the actuator instructions to configure correctly this parameter on the actuator before performing auto calibration. If the "stop time" on the physical actuator is wrongly set or cannot be modified to the actual "run time" of the shutter, auto calibration cannot be used and `shutterRun` should be set manually to the actual runtime of the shutters.
|
||||
|
||||
_Notes on `shutter` position_
|
||||
##### Position estimation of the shutter
|
||||
|
||||
- if `shutterRun` is not set, or is set to `AUTO` but calibration has not been performed yet, then position estimation will remain `UNDEF` (undefined)
|
||||
- if `shutterRun` is wrongly set higher than the actual runtime, then position estimation will remain `UNDEF`: try to reduce shutterRun until you find the right value
|
||||
- before adding/configuring roller shutter Things it is suggested to have all roller shutters `UP`, otherwise the Percent command won’t work until the roller shutter is fully rolled up
|
||||
- if OH is restarted the binding does not know if a shutter position has changed in the meantime, so its position will be `UNDEF`. Move the shutter all `UP`/`DOWN` to synchronize again its position with the binding
|
||||
- the shutter position is estimated based on UP/DOWN timing: an error of ±2% is normal
|
||||
- if `shutterRun` is wrongly set *higher* than the actual runtime or the "stop time" of the actuator (see NOTE above), then position estimation will remain `UNDEF`: try to reduce `shutterRun` until you find the right value
|
||||
- before adding/configuring roller shutter Things it is suggested to have all roller shutters `UP`, otherwise the Percent command will not work until the roller shutter is fully rolled up
|
||||
- if openHAB is restarted the binding does not know if a shutter position has changed in the meantime, so its position will be `UNDEF`. Move the shutter all `UP`/`DOWN` to synchronise again its position with the binding
|
||||
- the shutter position is estimated based on UP/DOWN timings: an error of ±2% is normal
|
||||
|
||||
#### Scenario channels
|
||||
|
||||
@ -320,7 +321,7 @@ BUS gateway and things configuration:
|
||||
Bridge openwebnet:bus_gateway:mybridge "MyHOMEServer1" [ host="192.168.1.35", passwd="abcde", port=20000, discoveryByActivation=false ] {
|
||||
bus_on_off_switch LR_switch "Living Room Light" [ where="51" ]
|
||||
bus_dimmer LR_dimmer "Living Room Dimmer" [ where="0311#4#01" ]
|
||||
bus_automation LR_shutter "Living Room Shutter" [ where="93", shutterRun="10050"]
|
||||
bus_automation LR_shutter "Living Room Shutter" [ where="93", shutterRun="20050"]
|
||||
|
||||
bus_energy_meter CENTRAL_Ta "Energy Meter Ta" [ where="51" ]
|
||||
bus_energy_meter CENTRAL_Tb "Energy Meter Tb" [ where="52" ]
|
||||
@ -439,7 +440,7 @@ sitemap openwebnet label="OpenWebNet Binding Example Sitemap"
|
||||
Frame label="Living Room Thermo"
|
||||
{
|
||||
Default item=iLR_zone_temp label="Temperature" icon="fire" valuecolor=[<20="red"]
|
||||
Setpoint item=iLR_zone_set label="Setpoint [%.1f °C]" step=0.5 minValue=15 maxValue=30
|
||||
Setpoint item=iLR_zone_setTemp label="Setpoint [%.1f °C]" step=0.5 minValue=15 maxValue=30
|
||||
Selection item=iLR_zone_fanSpeed label="Fan Speed" icon="fan" mappings=[AUTO="AUTO", SPEED_1="Low", SPEED_2="Medium", SPEED_3="High"]
|
||||
Switch item=iLR_zone_mode label="Mode" icon="settings"
|
||||
Selection item=iLR_zone_func label="Function" icon="heating" mappings=[HEATING="Heating", COOLING="Cooling", GENERIC="Heating/Cooling"]
|
||||
@ -528,5 +529,7 @@ Special thanks for helping on testing this binding go to:
|
||||
[@aconte80](https://community.openhab.org/u/aconte80),
|
||||
[@rubenfuser](https://community.openhab.org/u/rubenfuser),
|
||||
[@stamate_viorel](https://community.openhab.org/u/stamate_viorel),
|
||||
[@marchino](https://community.openhab.org/u/marchino)
|
||||
[@marchino](https://community.openhab.org/u/marchino),
|
||||
[@the-ninth](https://community.openhab.org/u/the-ninth)
|
||||
|
||||
and many others at the fantastic openHAB community!
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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...
|
||||
|
Loading…
Reference in New Issue
Block a user