[somfytahoma] [Improvement] Fix cozytouch support and add waterheatersystem support (#11855)
* Add support for Cozytouch and WaterHeaterSystem Signed-off-by: Benjamin Lafois <benjamin.lafois@gmail.com>
This commit is contained in:
parent
56b2f47be6
commit
d6da67435a
|
@ -40,17 +40,18 @@ Any home automation system based on the OverKiz API is potentially supported.
|
|||
- sirens (battery status full/low/normal/verylow, siren control ON/OFF, setting memorized volume)
|
||||
- action groups (scenarios which can execute predefined Tahoma group of steps, e.g. send to all roller shutters DOWN command, one by one)
|
||||
- thermostats (read status and battery level)
|
||||
- water heater system (monitor and control)
|
||||
|
||||
Both Somfy Tahoma and Somfy Connexoon gateways have been confirmed working.
|
||||
|
||||
## Discovery
|
||||
|
||||
To start a discovery, just
|
||||
|
||||
|
||||
- Add a new bridge thing.
|
||||
- Configure the bridge selecting your cloud portal (www.tahomalink.com by default) and setting your email (login) and password to the cloud portal.
|
||||
|
||||
If the supplied credentials are correct, the automatic discovery can be used to scan and detect roller shutters, awnings, switches and action groups that will appear in your Inbox.
|
||||
|
||||
If the supplied credentials are correct, the automatic discovery can be used to scan and detect roller shutters, awnings, switches and action groups that will appear in your Inbox.
|
||||
|
||||
## Thing Configuration
|
||||
|
||||
|
@ -123,6 +124,18 @@ Please see the example below.
|
|||
| myfox camera, myfox alarm | cloud_status | cloud connection status |
|
||||
| myfox camera | shutter | controlling of the camera shutter |
|
||||
| myfox alarm | myfox_alarm_command | used for sending commands to Somfy Myfox alarm device |
|
||||
| waterheatersystem | middlewater_temperature | Number:Temperature indicating the temperature of the water at the middle of the heater |
|
||||
| waterheatersystem | boost_mode | Switch allowing to enable or disable the booster. When switching to ON, by default, the Boost duration will be set for 1 day.|
|
||||
| waterheatersystem | away_mode | Defines if away mode is On or Off (no water heating) |
|
||||
| waterheatersystem | away_mode_duration | Defines if away mode the duration in days. |
|
||||
| waterheatersystem | boost_mode_duration | The duration of the Boost mode in days. Valid from 1 to 7. |
|
||||
| waterheatersystem | power_heatpump | Current consumption/power of the heatpump in Watts. |
|
||||
| waterheatersystem | power_heatelec | Current consumption/power of the electric resistance in Watts. |
|
||||
| waterheatersystem | showers | Virtual channel, representing the number of desired showers - between 3 to 5. It actually switches the desired temperature to 50.0, 54.5 or 62.0 Celcius degrees. Please note that in ECO mode, only 3 and 4 showers are allowed. |
|
||||
| waterheatersystem | heat_pump_operating_time | Number of hours the heatpump has been operating |
|
||||
| waterheatersystem | electric_booster_operating_time | number of hours the electric booster has been operating. |
|
||||
| waterheatersystem | mode | The current mode of the boiler. Can be: autoMode / manualEcoInactive / manualEcoActive |
|
||||
| waterheatersystem | target_temperature | Water target temperature in degrees. Read only. Temperature desired is managed through mode and showers channels. |
|
||||
|
||||
To run a scenario inside a rule for example, the ID of the scenario will be required.
|
||||
You can list all the scenarios IDs with the following console command: `somfytahoma <bridgeUID> scenarios`.
|
||||
|
@ -174,7 +187,7 @@ Bridge somfytahoma:bridge:237dbae7 "Somfy Tahoma Bridge" [ email="my@email.com",
|
|||
}
|
||||
```
|
||||
|
||||
Awnings, garage doors, screens, blinds, and windows things have the same notation as roller shutters. Just use "awning", "garagedoor", "screen", "blind" or "window" instead of "rolleshutter" in thing definition.
|
||||
Awnings, garage doors, screens, blinds, and windows things have the same notation as roller shutters. Just use "awning", "garagedoor", "screen", "blind" or "window" instead of "rolleshutter" in thing definition.
|
||||
|
||||
.items file
|
||||
|
||||
|
@ -267,7 +280,7 @@ Slider item=HeatingLevel
|
|||
|
||||
## Alexa compatibility
|
||||
|
||||
This binding is compatible with the official Alexa Smart Home Skill.
|
||||
This binding is compatible with the official Alexa Smart Home Skill.
|
||||
Since Rolleshutter items are unsupported, only Dimmer with control channel can be used.
|
||||
Syntax in .item file is as follows:
|
||||
|
||||
|
|
|
@ -144,6 +144,9 @@ public class SomfyTahomaBindingConstants {
|
|||
// Electricity sensor
|
||||
public static final ThingTypeUID THING_TYPE_ELECTRICITYSENSOR = new ThingTypeUID(BINDING_ID, "electricitysensor");
|
||||
|
||||
// Water Heating System
|
||||
public static final ThingTypeUID THING_TYPE_WATERHEATINGSYSTEM = new ThingTypeUID(BINDING_ID, "waterheatingsystem");
|
||||
|
||||
// Dock
|
||||
public static final ThingTypeUID THING_TYPE_DOCK = new ThingTypeUID(BINDING_ID, "dock");
|
||||
|
||||
|
@ -260,6 +263,20 @@ public class SomfyTahomaBindingConstants {
|
|||
// ElectricitySensor
|
||||
public static final String ENERGY_CONSUMPTION = "energy_consumption";
|
||||
|
||||
// WaterHeaterSystem
|
||||
public static final String MIDDLEWATER_TEMPERATURE = "middlewater_temperature";
|
||||
public static final String BOOST_MODE = "boost_mode";
|
||||
public static final String AWAY_MODE = "away_mode";
|
||||
public static final String BOOST_MODE_DURATION = "boost_mode_duration";
|
||||
public static final String AWAY_MODE_DURATION = "away_mode_duration";
|
||||
public static final String HEAT_PUMP_OPERATING_TIME = "heat_pump_operating_time";
|
||||
public static final String POWER_HEAT_PUMP = "power_heatpump";
|
||||
public static final String POWER_HEAT_ELEC = "power_heatelec";
|
||||
public static final String WATER_HEATER_MODE = "mode";
|
||||
public static final String WATER_TEMPERATURE = "water_temperature";
|
||||
public static final String ELECTRIC_BOOSTER_OPERATING_TIME = "electric_booster_operating_time";
|
||||
public static final String SHOWERS = "showers";
|
||||
|
||||
// Dock
|
||||
public static final String BATTERY_STATUS = "battery_status";
|
||||
public static final String SIREN_STATUS = "siren_status";
|
||||
|
@ -281,7 +298,12 @@ public class SomfyTahomaBindingConstants {
|
|||
public static final String SHUTTER = "shutter";
|
||||
|
||||
// Constants
|
||||
public static final String COZYTOUCH_PORTAL = "ha110-1.overkiz.com";
|
||||
public static final String TAHOMA_PORTAL = "www.tahomalink.com";
|
||||
public static final String COZYTOUCH_OAUTH2_URL = "api.groupe-atlantic.com";
|
||||
public static final String COZYTOUCH_OAUTH2_BASICAUTH = "czduc0RZZXdWbjVGbVV4UmlYN1pVSUM3ZFI4YTphSDEzOXZmbzA1ZGdqeDJkSFVSQkFTbmhCRW9h";
|
||||
public static final String COZYTOUCH_OAUTH2_TOKEN_URL = "/token";
|
||||
public static final String COZYTOUCH_OAUTH2_JWT_URL = "/gacoma/gacomawcfservice/accounts/jwt";
|
||||
public static final String API_BASE_URL = "/enduser-mobile-web/enduserAPI/";
|
||||
public static final String EVENTS_URL = "events/";
|
||||
public static final String SETUP_URL = "setup/";
|
||||
|
@ -300,6 +322,7 @@ public class SomfyTahomaBindingConstants {
|
|||
public static final int TYPE_BOOLEAN = 6;
|
||||
public static final String UNAVAILABLE = "unavailable";
|
||||
public static final String AUTHENTICATION_CHALLENGE = "HTTP protocol violation: Authentication challenge without WWW-Authenticate header";
|
||||
public static final String AUTHENTICATION_OAUTH_GRANT_ERROR = "Provided Authorization Grant is invalid.";
|
||||
public static final String TOO_MANY_REQUESTS = "Too many requests, try again later";
|
||||
public static final int SUSPEND_TIME = 120;
|
||||
public static final int RECONCILIATION_TIME = 600;
|
||||
|
@ -324,8 +347,24 @@ public class SomfyTahomaBindingConstants {
|
|||
public static final String COMMAND_STOP = "stop";
|
||||
public static final String COMMAND_OFF = "off";
|
||||
public static final String COMMAND_CHECK_TRIGGER = "checkEventTrigger";
|
||||
public static final String COMMAND_SET_BOOST_MODE_DURATION = "setBoostModeDuration";
|
||||
public static final String COMMAND_SET_WATER_HEATER_MODE = "setDHWMode";
|
||||
public static final String COMMAND_SET_AWAY_MODE_DURATION = "setAwayModeDuration";
|
||||
public static final String COMMAND_SET_CURRENT_OPERATING_MODE = "setCurrentOperatingMode";
|
||||
public static final String COMMAND_SET_TARGET_TEMPERATURE = "setTargetTemperature";
|
||||
public static final String COMMAND_REFRESH_DHWMODE = "refreshDHWMode";
|
||||
public static final String COMMAND_REFRESH_BOOST_MODE_DURATION = "refreshBoostModeDuration";
|
||||
|
||||
// States
|
||||
public static final String OPERATING_MODE_STATE = "core:OperatingModeState";
|
||||
public static final String ELECTRIC_BOOSTER_OPERATING_TIME_STATE = "io:ElectricBoosterOperatingTimeState";
|
||||
public static final String WATER_HEATER_MODE_STATE = "io:DHWModeState";
|
||||
public static final String POWER_HEAT_ELEC_STATE = "io:PowerHeatElectricalState";
|
||||
public static final String POWER_HEAT_PUMP_STATE = "io:PowerHeatPumpState";
|
||||
public static final String HEAT_PUMP_OPERATING_TIME_STATE = "io:HeatPumpOperatingTimeState";
|
||||
public static final String BOOST_MODE_DURATION_STATE = "core:BoostModeDurationState";
|
||||
public static final String AWAY_MODE_DURATION_STATE = "io:AwayModeDurationState";
|
||||
public static final String MIDDLE_WATER_TEMPERATURE_STATE = "io:MiddleWaterTemperatureState";
|
||||
public static final String NAME_STATE = "core:NameState";
|
||||
public static final String RSSI_LEVEL_STATE = "core:RSSILevelState";
|
||||
public static final String STATUS_STATE = "core:StatusState";
|
||||
|
@ -341,6 +380,7 @@ public class SomfyTahomaBindingConstants {
|
|||
public static final String BATTERY_LEVEL_STATE = "core:BatteryLevelState";
|
||||
public static final String SIREN_STATUS_STATE = "internal:SirenStatusState";
|
||||
public static final String TARGET_TEMPERATURE_STATE = "core:TargetTemperatureState";
|
||||
public static final String TEMPERATURE_STATE = "core:TemperatureState";
|
||||
public static final String TARGET_ROOM_TEMPERATURE_STATE = "core:TargetRoomTemperatureState";
|
||||
public static final String SMOKE_STATE = "core:SmokeState";
|
||||
public static final String SENSOR_DEFECT_STATE = "core:SensorDefectState";
|
||||
|
@ -379,6 +419,7 @@ public class SomfyTahomaBindingConstants {
|
|||
public static final String CLASS_SIREN = "Siren";
|
||||
public static final String CLASS_ADJUSTABLE_SLATS_ROLLER_SHUTTER = "AdjustableSlatsRollerShutter";
|
||||
public static final String CLASS_CAMERA = "Camera";
|
||||
public static final String CLASS_WATER_HEATING_SYSTEM = "WaterHeatingSystem";
|
||||
|
||||
// unsupported uiClasses
|
||||
public static final String THING_PROTOCOL_GATEWAY = "ProtocolGateway";
|
||||
|
@ -401,7 +442,7 @@ public class SomfyTahomaBindingConstants {
|
|||
THING_TYPE_ADJUSTABLE_SLATS_ROLLERSHUTTER, THING_TYPE_MYFOX_CAMERA, THING_TYPE_ROLLERSHUTTER_UNO,
|
||||
THING_TYPE_WATERSENSOR, THING_TYPE_HUMIDITYSENSOR, THING_TYPE_MYFOX_ALARM, THING_TYPE_THERMOSTAT,
|
||||
THING_TYPE_DIMMER_LIGHT, THING_TYPE_EXTERIOR_HEATING_SYSTEM, THING_TYPE_VALVE_HEATING_SYSTEM,
|
||||
THING_TYPE_BIOCLIMATIC_PERGOLA));
|
||||
THING_TYPE_BIOCLIMATIC_PERGOLA, THING_TYPE_WATERHEATINGSYSTEM));
|
||||
|
||||
// somfy gateways
|
||||
public static Map<Integer, String> gatewayTypes = new HashMap<Integer, String>() {
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaThermostatHan
|
|||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaUnoRollerShutterHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaValveHeatingSystemHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaVenetianBlindHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaWaterHeatingSystemHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaWaterSensorHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaWindowHandleHandler;
|
||||
import org.openhab.binding.somfytahoma.internal.handler.SomfyTahomaWindowHandler;
|
||||
|
@ -184,6 +185,8 @@ public class SomfyTahomaHandlerFactory extends BaseThingHandlerFactory {
|
|||
return new SomfyTahomaMyfoxAlarmHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_THERMOSTAT)) {
|
||||
return new SomfyTahomaThermostatHandler(thing);
|
||||
} else if (thingTypeUID.equals(THING_TYPE_WATERHEATINGSYSTEM)) {
|
||||
return new SomfyTahomaWaterHeatingSystemHandler(thing);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -300,6 +300,14 @@ public class SomfyTahomaItemDiscoveryService extends AbstractDiscoveryService
|
|||
logUnsupportedDevice(device);
|
||||
}
|
||||
break;
|
||||
case CLASS_WATER_HEATING_SYSTEM:
|
||||
// widget: DomesticHotWaterProduction
|
||||
if ("DomesticHotWaterProduction".equals(device.getWidget())) {
|
||||
deviceDiscovered(device, THING_TYPE_WATERHEATINGSYSTEM, place);
|
||||
} else {
|
||||
logUnsupportedDevice(device);
|
||||
}
|
||||
break;
|
||||
case CLASS_DOCK:
|
||||
// widget: Dock
|
||||
deviceDiscovered(device, THING_TYPE_DOCK, place);
|
||||
|
@ -323,6 +331,7 @@ public class SomfyTahomaItemDiscoveryService extends AbstractDiscoveryService
|
|||
// widget: AlarmRemoteController
|
||||
case THING_NETWORK_COMPONENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
logUnsupportedDevice(device);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.util.concurrent.ScheduledFuture;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
|
@ -44,6 +46,8 @@ import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaApplyResponse;
|
|||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaDevice;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaEvent;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaLoginResponse;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaOauth2Error;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaOauth2Reponse;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaRegisterEventsResponse;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaSetup;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaState;
|
||||
|
@ -212,8 +216,17 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
|
|||
reLoginNeeded = false;
|
||||
|
||||
try {
|
||||
String urlParameters = "userId=" + urlEncode(thingConfig.getEmail()) + "&userPassword="
|
||||
+ urlEncode(thingConfig.getPassword());
|
||||
|
||||
String urlParameters = "";
|
||||
|
||||
// if cozytouch, must use oauth server
|
||||
if (thingConfig.getCloudPortal().equalsIgnoreCase(COZYTOUCH_PORTAL)) {
|
||||
logger.debug("CozyTouch Oauth2 authentication flow");
|
||||
urlParameters = "jwt=" + loginCozytouch();
|
||||
} else {
|
||||
urlParameters = "userId=" + urlEncode(thingConfig.getEmail()) + "&userPassword="
|
||||
+ urlEncode(thingConfig.getPassword());
|
||||
}
|
||||
|
||||
ContentResponse response = sendRequestBuilder("login", HttpMethod.POST)
|
||||
.content(new StringContentProvider(urlParameters),
|
||||
|
@ -250,7 +263,7 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
|
|||
logger.debug("Received invalid data (login)", e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Received invalid data (login)");
|
||||
} catch (ExecutionException e) {
|
||||
if (isAuthenticationChallenge(e)) {
|
||||
if (isAuthenticationChallenge(e) || isOAuthGrantError(e)) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
"Error logging in (check your credentials)");
|
||||
setTooManyRequests();
|
||||
|
@ -646,6 +659,63 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
|
|||
.agent(TAHOMA_AGENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the login for Cozytouch using OAUTH2 authorization.
|
||||
*
|
||||
* @return JSESSION ID cookie value.
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
* @throws InterruptedException
|
||||
* @throws JsonSyntaxException
|
||||
*/
|
||||
private String loginCozytouch()
|
||||
throws InterruptedException, TimeoutException, ExecutionException, JsonSyntaxException {
|
||||
String authBaseUrl = "https://" + COZYTOUCH_OAUTH2_URL;
|
||||
|
||||
String urlParameters = "grant_type=password&username=" + urlEncode(thingConfig.getEmail()) + "&password="
|
||||
+ urlEncode(thingConfig.getPassword());
|
||||
|
||||
ContentResponse response = httpClient.newRequest(authBaseUrl + COZYTOUCH_OAUTH2_TOKEN_URL)
|
||||
.method(HttpMethod.POST).header(HttpHeader.ACCEPT_LANGUAGE, "en-US,en")
|
||||
.header(HttpHeader.ACCEPT_ENCODING, "gzip, deflate").header("X-Requested-With", "XMLHttpRequest")
|
||||
.header(HttpHeader.AUTHORIZATION, "Basic " + COZYTOUCH_OAUTH2_BASICAUTH)
|
||||
.timeout(TAHOMA_TIMEOUT, TimeUnit.SECONDS).agent(TAHOMA_AGENT)
|
||||
.content(new StringContentProvider(urlParameters), "application/x-www-form-urlencoded; charset=UTF-8")
|
||||
.send();
|
||||
|
||||
if (response.getStatus() != 200) {
|
||||
// Login error
|
||||
if (response.getHeaders().getField(HttpHeader.CONTENT_TYPE).getValue()
|
||||
.equalsIgnoreCase(MediaType.APPLICATION_JSON)) {
|
||||
try {
|
||||
SomfyTahomaOauth2Error error = gson.fromJson(response.getContentAsString(),
|
||||
SomfyTahomaOauth2Error.class);
|
||||
throw new ExecutionException(error.getErrorDescription(), null);
|
||||
} catch (JsonSyntaxException e) {
|
||||
|
||||
}
|
||||
}
|
||||
throw new ExecutionException("Unknown error while attempting to log in.", null);
|
||||
}
|
||||
|
||||
SomfyTahomaOauth2Reponse oauth2response = gson.fromJson(response.getContentAsString(),
|
||||
SomfyTahomaOauth2Reponse.class);
|
||||
|
||||
logger.debug("OAuth2 Access Token: {}", oauth2response.getAccessToken());
|
||||
|
||||
response = httpClient.newRequest(authBaseUrl + COZYTOUCH_OAUTH2_JWT_URL).method(HttpMethod.GET)
|
||||
.header(HttpHeader.AUTHORIZATION, "Bearer " + oauth2response.getAccessToken())
|
||||
.timeout(TAHOMA_TIMEOUT, TimeUnit.SECONDS).send();
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
String jwt = response.getContentAsString();
|
||||
return jwt.replace("\"", "");
|
||||
} else {
|
||||
throw new ExecutionException(String.format("Failed to retrieve JWT token. ResponseCode=%d, ResponseText=%s",
|
||||
response.getStatus(), response.getContentAsString()), null);
|
||||
}
|
||||
}
|
||||
|
||||
private String getApiFullUrl(String subUrl) {
|
||||
return "https://" + thingConfig.getCloudPortal() + API_BASE_URL + subUrl;
|
||||
}
|
||||
|
@ -796,6 +866,11 @@ public class SomfyTahomaBridgeHandler extends BaseBridgeHandler {
|
|||
return msg != null && msg.contains(AUTHENTICATION_CHALLENGE);
|
||||
}
|
||||
|
||||
private boolean isOAuthGrantError(Exception ex) {
|
||||
String msg = ex.getMessage();
|
||||
return msg != null && msg.contains(AUTHENTICATION_OAUTH_GRANT_ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleConfigurationUpdate(Map<String, Object> configurationParameters) {
|
||||
super.handleConfigurationUpdate(configurationParameters);
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
/**
|
||||
* 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.somfytahoma.internal.handler;
|
||||
|
||||
import static org.openhab.binding.somfytahoma.internal.SomfyTahomaBindingConstants.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.somfytahoma.internal.model.SomfyTahomaState;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link SomfyTahomaWaterHeatingSystemHandler} is responsible for handling commands,
|
||||
* which are sent to one of the channels of the Water Heating system thing.
|
||||
*
|
||||
* @author Benjamin Lafois - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SomfyTahomaWaterHeatingSystemHandler extends SomfyTahomaBaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SomfyTahomaWaterHeatingSystemHandler.class);
|
||||
|
||||
private boolean boostMode = false;
|
||||
private boolean awayMode = false;
|
||||
|
||||
public SomfyTahomaWaterHeatingSystemHandler(Thing thing) {
|
||||
super(thing);
|
||||
|
||||
stateNames.put(MIDDLEWATER_TEMPERATURE, MIDDLE_WATER_TEMPERATURE_STATE);
|
||||
stateNames.put(TARGET_TEMPERATURE, TARGET_TEMPERATURE_STATE);
|
||||
stateNames.put(WATER_HEATER_MODE, WATER_HEATER_MODE_STATE);
|
||||
|
||||
stateNames.put(BOOST_MODE_DURATION, BOOST_MODE_DURATION_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(BOOST_MODE_DURATION_STATE, TYPE_DECIMAL);
|
||||
|
||||
stateNames.put(AWAY_MODE_DURATION, AWAY_MODE_DURATION_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(AWAY_MODE_DURATION_STATE, TYPE_DECIMAL);
|
||||
|
||||
stateNames.put(HEAT_PUMP_OPERATING_TIME, HEAT_PUMP_OPERATING_TIME_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(HEAT_PUMP_OPERATING_TIME_STATE, TYPE_DECIMAL);
|
||||
|
||||
stateNames.put(ELECTRIC_BOOSTER_OPERATING_TIME, ELECTRIC_BOOSTER_OPERATING_TIME_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(ELECTRIC_BOOSTER_OPERATING_TIME_STATE, TYPE_DECIMAL);
|
||||
|
||||
stateNames.put(POWER_HEAT_PUMP, POWER_HEAT_PUMP_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(POWER_HEAT_PUMP_STATE, TYPE_DECIMAL);
|
||||
|
||||
stateNames.put(POWER_HEAT_ELEC, POWER_HEAT_ELEC_STATE);
|
||||
// override state type because the cloud sends consumption in percent
|
||||
cacheStateType(POWER_HEAT_ELEC_STATE, TYPE_DECIMAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateThingChannels(SomfyTahomaState state) {
|
||||
if (OPERATING_MODE_STATE.equals(state.getName()) && state.getValue() instanceof Map) {
|
||||
logger.debug("Operating Mode State: {} {}", state.getValue().getClass().getName(), state.getValue());
|
||||
|
||||
Map<String, String> data = (Map<String, String>) state.getValue();
|
||||
|
||||
Object relaunchValue = data.get("relaunch");
|
||||
if (relaunchValue != null) {
|
||||
this.boostMode = relaunchValue.toString().equalsIgnoreCase("on");
|
||||
logger.debug("Boost Value: {}", this.boostMode);
|
||||
updateState(BOOST_MODE, OnOffType.from(this.boostMode));
|
||||
}
|
||||
|
||||
Object awayValue = data.get("absence");
|
||||
if (awayValue != null) {
|
||||
this.awayMode = awayValue.toString().equalsIgnoreCase("on");
|
||||
logger.debug("Away Value: {}", this.awayMode);
|
||||
updateState(AWAY_MODE, OnOffType.from(this.awayMode));
|
||||
}
|
||||
} else if (TARGET_TEMPERATURE_STATE.equals(state.getName())) {
|
||||
logger.debug("Target Temperature: {}", state.getValue());
|
||||
// 50 -> 3
|
||||
// 54.5 -> 4
|
||||
// 62 -> 5
|
||||
Double temp = null;
|
||||
try {
|
||||
temp = Double.parseDouble(state.getValue().toString());
|
||||
|
||||
int v = 0;
|
||||
if (temp == 50) {
|
||||
v = 3;
|
||||
} else if (temp == 54.5) {
|
||||
v = 4;
|
||||
} else if (temp == 62) {
|
||||
v = 5;
|
||||
}
|
||||
|
||||
updateState(SHOWERS, new DecimalType(v));
|
||||
} catch (NumberFormatException e) {
|
||||
logger.warn("Unexpected pre-defined value for Target State Temperature: {}", state.getValue());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
super.updateThingChannels(state);
|
||||
}
|
||||
|
||||
private void sendOperatingMode() {
|
||||
sendCommand(COMMAND_SET_CURRENT_OPERATING_MODE, String.format("[ { \"relaunch\":\"%s\", \"absence\":\"%s\"} ]",
|
||||
(this.boostMode ? "on" : "off"), (this.awayMode ? "on" : "off")));
|
||||
}
|
||||
|
||||
private void sendBoostDuration(int duration) {
|
||||
sendCommand(COMMAND_SET_BOOST_MODE_DURATION, "[ " + duration + " ]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
super.handleCommand(channelUID, command);
|
||||
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Command received: {}/{}", channelUID.getId(), command.toString());
|
||||
|
||||
if (BOOST_MODE_DURATION.equals(channelUID.getId())) {
|
||||
int duration = 0;
|
||||
try {
|
||||
duration = Integer.parseInt(command.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
logger.debug("Invalid value received for boost mode duration: {}", command);
|
||||
return;
|
||||
}
|
||||
if (duration == 0) {
|
||||
this.boostMode = false;
|
||||
sendOperatingMode();
|
||||
} else if (duration > 0 && duration < 8) {
|
||||
this.boostMode = true;
|
||||
sendOperatingMode();
|
||||
sendBoostDuration(duration);
|
||||
}
|
||||
} else if (WATER_HEATER_MODE.equals(channelUID.getId())) {
|
||||
sendCommand(COMMAND_SET_WATER_HEATER_MODE, "[ \"" + command.toString() + "\" ]");
|
||||
} else if (AWAY_MODE_DURATION.equals(channelUID.getId())) {
|
||||
sendCommand(COMMAND_SET_AWAY_MODE_DURATION, "[ \"" + command.toString() + "\" ]");
|
||||
} else if (BOOST_MODE.equals(channelUID.getId()) && command instanceof OnOffType) {
|
||||
if (command == OnOffType.ON) {
|
||||
if (this.boostMode) {
|
||||
return;
|
||||
}
|
||||
this.boostMode = true;
|
||||
|
||||
scheduler.execute(() -> {
|
||||
sendBoostDuration(1); // by default, boost for 1 day
|
||||
});
|
||||
|
||||
scheduler.schedule(() -> {
|
||||
sendCommand(COMMAND_REFRESH_DHWMODE, "[ ]");
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
|
||||
scheduler.schedule(() -> {
|
||||
sendOperatingMode();
|
||||
}, 2, TimeUnit.SECONDS);
|
||||
|
||||
scheduler.schedule(() -> {
|
||||
sendCommand(COMMAND_REFRESH_BOOST_MODE_DURATION, "[ ]");
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
|
||||
} else {
|
||||
this.boostMode = false;
|
||||
sendOperatingMode();
|
||||
}
|
||||
} else if (AWAY_MODE.equals(channelUID.getId()) && command instanceof OnOffType) {
|
||||
if (command == OnOffType.ON) {
|
||||
this.boostMode = false;
|
||||
this.awayMode = true;
|
||||
} else {
|
||||
this.awayMode = false;
|
||||
}
|
||||
sendOperatingMode();
|
||||
} else if (SHOWERS.equals(channelUID.getId())) {
|
||||
int showers = 0;
|
||||
try {
|
||||
showers = Integer.parseInt(command.toString());
|
||||
} catch (NumberFormatException e) {
|
||||
logger.info("Received an invalid value for desired number of showers: {}", command);
|
||||
return;
|
||||
}
|
||||
Double value = 0.0;
|
||||
|
||||
switch (showers) {
|
||||
case 3:
|
||||
value = 50.0;
|
||||
break;
|
||||
case 4:
|
||||
value = 54.5;
|
||||
break;
|
||||
case 5:
|
||||
value = 62.0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sendCommand(COMMAND_SET_TARGET_TEMPERATURE, "[ " + value.toString() + " ]");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 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.somfytahoma.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link SomfyTahomaOauth2Error} is used to parse login error from API server.
|
||||
*
|
||||
* @author Benjamin Lafois - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SomfyTahomaOauth2Error {
|
||||
|
||||
private String error = "";
|
||||
@SerializedName("error_description")
|
||||
private String errorDescription = "";
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getErrorDescription() {
|
||||
return errorDescription;
|
||||
}
|
||||
|
||||
public void setErrorDescription(String errorDescription) {
|
||||
this.errorDescription = errorDescription;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* 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.somfytahoma.internal.model;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link SomfyTahomaOauth2Reponse} holds information about Oauth2 login
|
||||
* response to your CozyTouch account.
|
||||
*
|
||||
* @author Benjamin Lafois - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SomfyTahomaOauth2Reponse {
|
||||
private String scope = "";
|
||||
|
||||
@SerializedName("token_type")
|
||||
private String tokenType = "";
|
||||
|
||||
@SerializedName("expires_in")
|
||||
private int expiresIn = 0;
|
||||
|
||||
@SerializedName("refresh_token")
|
||||
private String refreshToken = "";
|
||||
|
||||
@SerializedName("access_token")
|
||||
private String accessToken = "";
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public int getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(int expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@ thing-type.somfytahoma.temperaturesensor.label = Somfy Temperature Sensor
|
|||
thing-type.somfytahoma.thermostat.label = Somfy Thermostat
|
||||
thing-type.somfytahoma.valveheatingsystem.label = Somfy Thermostatic Valve
|
||||
thing-type.somfytahoma.venetianblind.label = Somfy Venetian Blind
|
||||
thing-type.somfytahoma.waterheatingsystem.label = Somfy Water Heating System
|
||||
thing-type.somfytahoma.watersensor.label = Somfy Water Sensor
|
||||
thing-type.somfytahoma.window.label = Somfy Window
|
||||
thing-type.somfytahoma.windowhandle.label = Somfy Window Handle
|
||||
|
@ -95,10 +96,18 @@ channel-type.somfytahoma.alarm_command.state.option.alarmPartial1 = ARM_PARTIAL_
|
|||
channel-type.somfytahoma.alarm_command.state.option.alarmPartial2 = ARM_PARTIAL_2
|
||||
channel-type.somfytahoma.alarm_state.label = Alarm State
|
||||
channel-type.somfytahoma.alarm_state.description = A state of the Somfy Alarm
|
||||
channel-type.somfytahoma.away_mode.label = Away
|
||||
channel-type.somfytahoma.away_mode.description = Away Mode (ON or OFF)
|
||||
channel-type.somfytahoma.away_mode_duration.label = Away Mode Duration
|
||||
channel-type.somfytahoma.away_mode_duration.description = Duration for Away Mode
|
||||
channel-type.somfytahoma.battery.label = Battery State
|
||||
channel-type.somfytahoma.battery.description = Battery Condition State (full, low, normal, verylow)
|
||||
channel-type.somfytahoma.battery_status.label = Battery Status State
|
||||
channel-type.somfytahoma.battery_status.description = Battery Status State
|
||||
channel-type.somfytahoma.boost_mode.label = Boost
|
||||
channel-type.somfytahoma.boost_mode.description = Boost Mode (ON or OFF)
|
||||
channel-type.somfytahoma.boost_mode_duration.label = Boost Mode Duration
|
||||
channel-type.somfytahoma.boost_mode_duration.description = Duration for Boost Mode
|
||||
channel-type.somfytahoma.closure_orientation.label = Set Closure And Orientation
|
||||
channel-type.somfytahoma.closure_orientation.description = A channel for setting closure and orientation of the blind
|
||||
channel-type.somfytahoma.cloud_status.label = Cloud Status State
|
||||
|
@ -127,6 +136,8 @@ channel-type.somfytahoma.derogation_heating_mode.command.option.comfort = Home
|
|||
channel-type.somfytahoma.derogation_heating_mode.command.option.frost\ protection = Frost protection
|
||||
channel-type.somfytahoma.derogation_heating_mode.command.option.manual = Manual
|
||||
channel-type.somfytahoma.derogation_heating_mode.command.option.eco = Night
|
||||
channel-type.somfytahoma.electric_booster_operating_time.label = Electric Bosster Operating Time
|
||||
channel-type.somfytahoma.electric_booster_operating_time.description = Time the Electric Bosster has been operating in hours
|
||||
channel-type.somfytahoma.energy_consumption.label = Energy Consumption
|
||||
channel-type.somfytahoma.energy_consumption.description = The energy consumption reported by the sensor
|
||||
channel-type.somfytahoma.execute_action.label = Somfy Action Group Trigger
|
||||
|
@ -143,6 +154,8 @@ channel-type.somfytahoma.gate_state.label = Gate Status
|
|||
channel-type.somfytahoma.gate_state.description = A channel used for getting the gate state (open, closed, pedestrian)
|
||||
channel-type.somfytahoma.handle_state.label = Handle State
|
||||
channel-type.somfytahoma.handle_state.description = A state of the Somfy Window Handle
|
||||
channel-type.somfytahoma.heat_pump_operating_time.label = Heat Pump Operating Time
|
||||
channel-type.somfytahoma.heat_pump_operating_time.description = Time the Heat Pump has been operating in hours
|
||||
channel-type.somfytahoma.heating_level.label = Heating Level
|
||||
channel-type.somfytahoma.heating_level.description = The level of the heating
|
||||
channel-type.somfytahoma.heating_mode.label = Heating Mode
|
||||
|
@ -171,6 +184,8 @@ channel-type.somfytahoma.memorized_volume.label = Memorized Volume
|
|||
channel-type.somfytahoma.memorized_volume.description = A channel used for controlling siren's volume state
|
||||
channel-type.somfytahoma.memorized_volume.state.option.normal = NORMAL
|
||||
channel-type.somfytahoma.memorized_volume.state.option.highest = HIGHEST
|
||||
channel-type.somfytahoma.middlewater_temperature.label = Middle Water Temperature
|
||||
channel-type.somfytahoma.middlewater_temperature.description = Describes the temperature at the middle sensor
|
||||
channel-type.somfytahoma.myfox_alarm_command.label = Command
|
||||
channel-type.somfytahoma.myfox_alarm_command.description = A channel used for sending commands to Somfy Myfox Alarm device
|
||||
channel-type.somfytahoma.myfox_alarm_command.state.option.arm = ARM
|
||||
|
@ -189,6 +204,10 @@ channel-type.somfytahoma.pergola_command.description = A channel used for sendin
|
|||
channel-type.somfytahoma.pergola_command.state.option.closeSlats = Close slats
|
||||
channel-type.somfytahoma.pergola_command.state.option.openSlats = Open slats
|
||||
channel-type.somfytahoma.pergola_command.state.option.stop = Stop
|
||||
channel-type.somfytahoma.power_heatelec.label = Electrical Heater Active
|
||||
channel-type.somfytahoma.power_heatelec.description = Indicates current status of electrical heater in watts
|
||||
channel-type.somfytahoma.power_heatpump.label = Heat Pump Power
|
||||
channel-type.somfytahoma.power_heatpump.description = Indicates current status of heatpump in watts
|
||||
channel-type.somfytahoma.radio_battery.label = Radio Part Battery State
|
||||
channel-type.somfytahoma.radio_battery.description = State of the radio part of the Somfy sensor
|
||||
channel-type.somfytahoma.rocker.label = Rocker Position
|
||||
|
@ -203,6 +222,8 @@ channel-type.somfytahoma.sensor_defect.label = Sensor Defect State
|
|||
channel-type.somfytahoma.sensor_defect.description = State of the Somfy sensor (dead, lowBattery, noDefect...)
|
||||
channel-type.somfytahoma.short_beep.label = Dock Short Beep Test
|
||||
channel-type.somfytahoma.short_beep.description = A channel for testing the dock's short beeping
|
||||
channel-type.somfytahoma.showers.label = Number of showers
|
||||
channel-type.somfytahoma.showers.description = 3 to 5 showers
|
||||
channel-type.somfytahoma.shutter.label = Myfox Shutter
|
||||
channel-type.somfytahoma.shutter.description = A channel for controlling the shutter
|
||||
channel-type.somfytahoma.siren_status.label = Siren Status State
|
||||
|
@ -224,3 +245,8 @@ channel-type.somfytahoma.target_temperature.label = Target Temperature
|
|||
channel-type.somfytahoma.target_temperature.description = The target temperature of the heating system
|
||||
channel-type.somfytahoma.temperature.label = Temperature
|
||||
channel-type.somfytahoma.temperature.description = The temperature value of the sensor
|
||||
channel-type.somfytahoma.water_heater_mode.label = Mode
|
||||
channel-type.somfytahoma.water_heater_mode.description = Describes the water heater mode
|
||||
channel-type.somfytahoma.water_heater_mode.state.option.manualEcoActive = Manual - Eco
|
||||
channel-type.somfytahoma.water_heater_mode.state.option.manualEcoInactive = Manual
|
||||
channel-type.somfytahoma.water_heater_mode.state.option.autoMode = Auto
|
||||
|
|
|
@ -424,4 +424,87 @@
|
|||
<state pattern="%.1f" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boost_mode_duration">
|
||||
<item-type>Number</item-type>
|
||||
<label>Boost Mode Duration</label>
|
||||
<description>Duration for Boost Mode</description>
|
||||
<state min="0" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="away_mode_duration">
|
||||
<item-type>Number</item-type>
|
||||
<label>Away Mode Duration</label>
|
||||
<description>Duration for Away Mode</description>
|
||||
<state min="0" max="7" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="heat_pump_operating_time">
|
||||
<item-type>Number</item-type>
|
||||
<label>Heat Pump Operating Time</label>
|
||||
<description>Time the Heat Pump has been operating in hours</description>
|
||||
<state pattern="%d" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="electric_booster_operating_time">
|
||||
<item-type>Number</item-type>
|
||||
<label>Electric Bosster Operating Time</label>
|
||||
<description>Time the Electric Bosster has been operating in hours</description>
|
||||
<state pattern="%d" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power_heatpump">
|
||||
<item-type>Number</item-type>
|
||||
<label>Heat Pump Power</label>
|
||||
<description>Indicates current status of heatpump in watts</description>
|
||||
<state pattern="%d" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="power_heatelec">
|
||||
<item-type>Number</item-type>
|
||||
<label>Electrical Heater Active</label>
|
||||
<description>Indicates current status of electrical heater in watts</description>
|
||||
<state pattern="%d" readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
|
||||
<channel-type id="water_heater_mode">
|
||||
<item-type>String</item-type>
|
||||
<label>Mode</label>
|
||||
<description>Describes the water heater mode</description>
|
||||
<state>
|
||||
<options>
|
||||
<option value="manualEcoActive">Manual - Eco</option>
|
||||
<option value="manualEcoInactive">Manual</option>
|
||||
<option value="autoMode">Auto</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="showers">
|
||||
<item-type>Number</item-type>
|
||||
<label>Number of showers</label>
|
||||
<description>3 to 5 showers</description>
|
||||
<state min="3" max="5" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="middlewater_temperature">
|
||||
<item-type>Number:Temperature</item-type>
|
||||
<label>Middle Water Temperature</label>
|
||||
<description>Describes the temperature at the middle sensor</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="boost_mode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Boost</label>
|
||||
<description>Boost Mode (ON or OFF)</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="away_mode">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Away</label>
|
||||
<description>Away Mode (ON or OFF)</description>
|
||||
</channel-type>
|
||||
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="somfytahoma"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<thing-type id="waterheatingsystem">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="bridge"/>
|
||||
</supported-bridge-type-refs>
|
||||
<label>Somfy Water Heating System</label>
|
||||
<channels>
|
||||
<channel id="target_temperature" typeId="temperature"></channel>
|
||||
<channel id="middlewater_temperature" typeId="middlewater_temperature"></channel>
|
||||
<channel id="boost_mode" typeId="boost_mode"></channel>
|
||||
<channel id="away_mode" typeId="away_mode"></channel>
|
||||
<channel id="boost_mode_duration" typeId="boost_mode_duration"></channel>
|
||||
<channel id="away_mode_duration" typeId="away_mode_duration"></channel>
|
||||
<channel id="heat_pump_operating_time" typeId="heat_pump_operating_time"></channel>
|
||||
<channel id="electric_booster_operating_time" typeId="electric_booster_operating_time"></channel>
|
||||
<channel id="power_heatpump" typeId="power_heatpump"></channel>
|
||||
<channel id="power_heatelec" typeId="power_heatelec"></channel>
|
||||
<channel id="mode" typeId="water_heater_mode"></channel>
|
||||
<channel id="showers" typeId="showers"></channel>
|
||||
</channels>
|
||||
<representation-property>url</representation-property>
|
||||
<config-description-ref uri="thing-type:somfytahoma:device"/>
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
Loading…
Reference in New Issue