This PR is just to reduce the delta before I create the PR for Plus/Pro (#13176)

support. In general Gen1 and Gen2 devices have a total different API so
I spliced the API code in version/gen 1 and 2. This means restructuring
the classes (e.h. api+coap became api+api1+api2) and therefor dummy
changes in the code, e.g. import statements. This creates a lot of
overhead and separating those "dummy changes" simplifies merging the
actual PR.

Signed-off-by: Markus Michels <markus7017@gmail.com>
This commit is contained in:
Markus Michels 2022-07-29 19:48:10 +02:00 committed by GitHub
parent d5b657c6fd
commit 8aa88bc3d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 869 additions and 478 deletions

View File

@ -27,6 +27,8 @@ Also check out the [Shelly Manager](doc/ShellyManager.md), which
## Supported Devices
### Generation 1:
| thing-type | Model | Vendor ID |
|--------------------|--------------------------------------------------------|-----------|
| shelly1 | Shelly 1 Single Relay Switch | SHSW-1 |
@ -745,22 +747,28 @@ Using the Thing configuration option `brightnessAutoOn` you could decide if the
`true`: Brightness will be set and device output is powered = light turns on with the new brightness
`false`: Brightness will be set, but output stays unchanged so light will not be switched on when it's currently off.
### Shelly RGBW2 in White Mode (thing-type: shellyrgbw2-color)
### Shelly RGBW2 in Color Mode (thing-type: shellyrgbw2-color)
|Group |Channel |Type |read-only|Description |
|----------|-------------|---------|---------|-----------------------------------------------------------------------|
|control |power |Switch |r/w |Switch light ON/OFF |
| |input |Switch |yes |State of Input |
| |autoOn |Number |r/w |Sets a timer to turn the device ON after every OFF; in sec |
| |autoOff |Number |r/w |Sets a timer to turn the device OFF after every ON: in sec |
| |autoOn |Number |r/w |Sets a timer to turn the device ON after every OFF command; in seconds|
| |autoOff |Number |r/w |Sets a timer to turn the device OFF after every ON command; in seconds|
| |timerActive |Switch |yes |ON: An auto-on/off timer is active |
|color | | | |Color settings: only valid in COLOR mode |
| |hsb |HSB |r/w |Represents the color picker (HSBType), control r/g/b, but not white |
|meter |currentWatts |Number |yes |Current power consumption in Watts (all channels) |
Please note that the settings of channel group color are only valid in color mode and vice versa for white mode.
The current firmware doesn't support the timestamp report for the meters.
The binding emulates this by using the system time on every update.
|color |hsb |HSB |r/w |Represents the color picker (HSBType), control r/g/b, bight not white |
| |full |String |r/w |Set Red / Green / Blue / Yellow / White mode and switch mode |
| | | |r/w |Valid settings: "red", "green", "blue", "yellow", "white" or "r,g,b,w" |
| |red |Dimmer |r/w |Red brightness: 0..100% or 0..255 (control only the red channel) |
| |green |Dimmer |r/w |Green brightness: 0..100% or 0..255 (control only the green channel) |
| |blue |Dimmer |r/w |Blue brightness: 0..100% or 0..255 (control only the blue channel) |
| |white |Dimmer |r/w |White brightness: 0..100% or 0..255 (control only the white channel) |
| |gain |Dimmer |r/w |Gain setting: 0..100% or 0..100 |
| |effect |Number |r/w |Puts the light into effect mode: 0..3) |
| | | | |0=No effect, 1=Meteor Shower, 2=Gradual Change, 3=Flash |
|meter |currentWatts |Number |yes |Current power consumption in Watts |
| |lastPower1 |Number |yes |Energy consumption for a round minute, 1 minute ago |
| |totalKWH |Number |yes |Total energy consumption in kWh since the device powered up (resets on restart)|
| |lastUpdate |DateTime |yes |Timestamp of the last measurement |
### Shelly RGBW2 in White Mode (thing-type: shellyrgbw2-white)

View File

@ -12,6 +12,8 @@
*/
package org.openhab.binding.shelly.internal;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;
@ -33,174 +35,6 @@ public class ShellyBindingConstants {
public static final String BINDING_ID = "shelly";
public static final String SYSTEM_ID = "system";
// Type names
public static final String THING_TYPE_SHELLY1_STR = "shelly1";
public static final String THING_TYPE_SHELLY1L_STR = "shelly1l";
public static final String THING_TYPE_SHELLY1PM_STR = "shelly1pm";
public static final String THING_TYPE_SHELLYEM_STR = "shellyem";
public static final String THING_TYPE_SHELLY3EM_STR = "shellyem3"; // bad: misspelled product name, it's 3EM
public static final String THING_TYPE_SHELLY2_PREFIX = "shellyswitch";
public static final String THING_TYPE_SHELLY2_RELAY_STR = "shelly2-relay";
public static final String THING_TYPE_SHELLY2_ROLLER_STR = "shelly2-roller";
public static final String THING_TYPE_SHELLY25_PREFIX = "shellyswitch25";
public static final String THING_TYPE_SHELLY25_RELAY_STR = "shelly25-relay";
public static final String THING_TYPE_SHELLY25_ROLLER_STR = "shelly25-roller";
public static final String THING_TYPE_SHELLY4PRO_STR = "shelly4pro";
public static final String THING_TYPE_SHELLYPLUG_STR = "shellyplug";
public static final String THING_TYPE_SHELLYPLUGS_STR = "shellyplugs";
public static final String THING_TYPE_SHELLYPLUGU1_STR = "shellyplugu1"; // Shely Plug US
public static final String THING_TYPE_SHELLYDIMMER_STR = "shellydimmer";
public static final String THING_TYPE_SHELLYDIMMER2_STR = "shellydimmer2";
public static final String THING_TYPE_SHELLYIX3_STR = "shellyix3";
public static final String THING_TYPE_SHELLYBULB_STR = "shellybulb";
public static final String THING_TYPE_SHELLYDUO_STR = "shellybulbduo";
public static final String THING_TYPE_SHELLYVINTAGE_STR = "shellyvintage";
public static final String THING_TYPE_SHELLYRGBW2_PREFIX = "shellyrgbw2";
public static final String THING_TYPE_SHELLYRGBW2_COLOR_STR = THING_TYPE_SHELLYRGBW2_PREFIX + "-color";
public static final String THING_TYPE_SHELLYRGBW2_WHITE_STR = THING_TYPE_SHELLYRGBW2_PREFIX + "-white";
public static final String THING_TYPE_SHELLYDUORGBW_STR = "shellycolorbulb";
public static final String THING_TYPE_SHELLYHT_STR = "shellyht";
public static final String THING_TYPE_SHELLYSMOKE_STR = "shellysmoke";
public static final String THING_TYPE_SHELLYGAS_STR = "shellygas";
public static final String THING_TYPE_SHELLYFLOOD_STR = "shellyflood";
public static final String THING_TYPE_SHELLYDOORWIN_STR = "shellydw";
public static final String THING_TYPE_SHELLYDOORWIN2_STR = "shellydw2";
public static final String THING_TYPE_SHELLYEYE_STR = "shellyseye";
public static final String THING_TYPE_SHELLYSENSE_STR = "shellysense";
public static final String THING_TYPE_SHELLYTRV_STR = "shellytrv";
public static final String THING_TYPE_SHELLYMOTION_STR = "shellymotion";
public static final String THING_TYPE_SHELLYMOTION2_STR = "shellymotion2";
public static final String THING_TYPE_SHELLYBUTTON1_STR = "shellybutton1";
public static final String THING_TYPE_SHELLYBUTTON2_STR = "shellybutton2";
public static final String THING_TYPE_SHELLYUNI_STR = "shellyuni";
// Shelly Plus Seriens
public static final String THING_TYPE_SHELLYPLUS1_STR = "shellyplus1";
public static final String THING_TYPE_SHELLYPLUS1PM_STR = "shellyplus1pm";
public static final String THING_TYPE_SHELLYPLUS2PM_RELAY_STR = "shellyplus2pm-relay";
public static final String THING_TYPE_SHELLYPLUS2PM_ROLLER_STR = "shellyplus2pm-roller";
public static final String THING_TYPE_SHELLYPLUSI4_STR = "shellyplusi4";
public static final String THING_TYPE_SHELLYPLUSHT_STR = "shellyplusht";
public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus";
// Shelly Pro Series
public static final String THING_TYPE_SHELLYPRO1_STR = "shellypro1";
public static final String THING_TYPE_SHELLYPRO1PM_STR = "shellypro1pm";
public static final String THING_TYPE_SHELLYPRO2_RELAY_STR = "shellypro2-relay";
public static final String THING_TYPE_SHELLYPRO2_ROLLER_STR = "shellypro2-roller";
public static final String THING_TYPE_SHELLYPRO2PM_RELAY_STR = "shellypro2pm-relay";
public static final String THING_TYPE_SHELLYPRO2PM_ROLLER_STR = "shellypro2pm-roller";
public static final String THING_TYPE_SHELLYPRO4PM_STR = "shellypro4pm";
public static final String THING_TYPE_SHELLYPROTECTED_STR = "shellydevice";
public static final String THING_TYPE_SHELLYUNKNOWN_STR = "shellyunknown";
// Device Types
public static final String SHELLYDT_1 = "SHSW-1";
public static final String SHELLYDT_1PM = "SHSW-PM";
public static final String SHELLYDT_1L = "SHSW-L";
public static final String SHELLYDT_SHPLG = "SHPLG-1";
public static final String SHELLYDT_SHPLG_S = "SHPLG-S";
public static final String SHELLYDT_SHPLG_U1 = "SHPLG-U1";
public static final String SHELLYDT_SHELLY2 = "SHSW-21";
public static final String SHELLYDT_SHELLY25 = "SHSW-25";
public static final String SHELLYDT_SHPRO = "SHSW-44";
public static final String SHELLYDT_EM = "SHEM";
public static final String SHELLYDT_3EM = "SHEM-3";
public static final String SHELLYDT_HT = "SHHT-1";
public static final String SHELLYDT_DW = "SHDW-1";
public static final String SHELLYDT_DW2 = "SHDW-2";
public static final String SHELLYDT_SENSE = "SHSEN-1";
public static final String SHELLYDT_MOTION = "SHMOS-01";
public static final String SHELLYDT_MOTION2 = "SHMOS-02";
public static final String SHELLYDT_GAS = "SHGS-1";
public static final String SHELLYDT_DIMMER = "SHDM-1";
public static final String SHELLYDT_DIMMER2 = "SHDM-2";
public static final String SHELLYDT_IX3 = "SHIX3-1";
public static final String SHELLYDT_BULB = "SHBLB-1";
public static final String SHELLYDT_DUO = "SHBDUO-1";
public static final String SHELLYDT_DUORGBW = "SHCB-1";
public static final String SHELLYDT_VINTAGE = "SHVIN-1";
public static final String SHELLYDT_RGBW2 = "SHRGBW2";
public static final String SHELLYDT_BUTTON1 = "SHBTN-1";
public static final String SHELLYDT_BUTTON2 = "SHBTN-2";
public static final String SHELLYDT_UNI = "SHUNI-1";
public static final String SHELLYDT_TRV = "SHTRV-01";
// Shelly Plus Series
public static final String SHELLYDT_PLUS1 = "SNSW-001X16EU";
public static final String SHELLYDT_PLUS1PM = "SNSW-001P16EU";
public static final String SHELLYDT_PLUS2PM_RELAY = "SNSW-002P16EU-relay";
public static final String SHELLYDT_PLUS2PM_ROLLER = "SNSW-002P16EU-roller";
public static final String SHELLYDT_PLUSPLUGUS = "SNPL-00116US";
public static final String SHELLYDT_PLUSI4 = "SNSN-0024X";
public static final String SHELLYDT_PLUSHT = "SNSN-0013A";
// Shelly Pro Series
public static final String SHELLYDT_PRO1 = "SPSW-001XE16EU";
public static final String SHELLYDT_PRO1PM = "SPSW-001PE16EU";
public static final String SHELLYDT_PRO2_RELAY = "SPSW-002XE16EU-relay";
public static final String SHELLYDT_PRO2_ROLLER = "SPSW-002XE16EU-roller";
public static final String SHELLYDT_PRO2PM_RELAY = "SPSW-002PE16EU-relay";
public static final String SHELLYDT_PRO2PM_ROLLER = "SPSW-002PE16EU-roller";
public static final String SHELLYDT_PRO4PM = "SPSW-004PE16EU";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_SHELLY1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1_STR);
public static final ThingTypeUID THING_TYPE_SHELLY1L = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1L_STR);
public static final ThingTypeUID THING_TYPE_SHELLY1PM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1PM_STR);
public static final ThingTypeUID THING_TYPE_SHELLYEM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYEM_STR);
public static final ThingTypeUID THING_TYPE_SHELLY3EM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY3EM_STR);
public static final ThingTypeUID THING_TYPE_SHELLY2_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY2_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLY2_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY2_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLY25_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY25_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLY25_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY25_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLY4PRO = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY4PRO_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUG = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUG_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUGS = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUGS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUGU1 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUGU1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYUNI = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYUNI_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDIMMER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDIMMER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDIMMER2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDIMMER2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYIX3 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYIX3_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBULB = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYBULB_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDUO = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYDUO_STR);
public static final ThingTypeUID THING_TYPE_SHELLYVINTAGE = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYVINTAGE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDUORGBW = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDUORGBW_STR);
public static final ThingTypeUID THING_TYPE_SHELLYHT = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYHT_STR);
public static final ThingTypeUID THING_TYPE_SHELLYSENSE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYSENSE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYSMOKE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYSMOKE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYGAS = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYGAS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYFLOOD = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYFLOOD_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDOORWIN = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDOORWIN_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDOORWIN2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDOORWIN2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYTRV = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYTRV_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBUTTON1 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYBUTTON1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBUTTON2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYBUTTON2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYEYE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYEYE_STR);
public static final ThingTypeUID THING_TYPE_SHELLMOTION = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYMOTION_STR);
public static final ThingTypeUID THING_TYPE_SHELLYRGBW2_COLOR = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYRGBW2_COLOR_STR);
public static final ThingTypeUID THING_TYPE_SHELLYRGBW2_WHITE = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYRGBW2_WHITE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPROTECTED = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPROTECTED_STR);
public static final ThingTypeUID THING_TYPE_SHELLYUNKNOWN = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYUNKNOWN_STR);
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
.unmodifiableSet(Stream.of(THING_TYPE_SHELLY1, THING_TYPE_SHELLY1L, THING_TYPE_SHELLY1PM,
THING_TYPE_SHELLYEM, THING_TYPE_SHELLY3EM, THING_TYPE_SHELLY2_RELAY, THING_TYPE_SHELLY2_ROLLER,

View File

@ -12,7 +12,7 @@
*/
package org.openhab.binding.shelly.internal;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import java.util.HashMap;
import java.util.Map;
@ -21,7 +21,7 @@ import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.coap.ShellyCoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyBaseHandler;
import org.openhab.binding.shelly.internal.handler.ShellyLightHandler;
@ -62,7 +62,7 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(ShellyHandlerFactory.class);
private final HttpClient httpClient;
private final ShellyTranslationProvider messages;
private final ShellyCoapServer coapServer;
private final Shelly1CoapServer coapServer;
private final ShellyThingTable thingTable;
private ShellyBindingConfiguration bindingConfig = new ShellyBindingConfiguration();
@ -81,7 +81,6 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
@Reference ShellyTranslationProvider translationProvider, @Reference ShellyThingTable thingTable,
@Reference HttpClientFactory httpClientFactory, ComponentContext componentContext,
Map<String, Object> configProperties) {
logger.debug("Activate Shelly HandlerFactory");
super.activate(componentContext);
messages = translationProvider;
// Save bindingConfig & pass it to all registered listeners
@ -103,10 +102,7 @@ public class ShellyHandlerFactory extends BaseThingHandlerFactory {
logger.debug("Using OH HTTP port {}", httpPort);
this.thingTable = thingTable;
this.coapServer = new ShellyCoapServer();
// Promote Shelly Manager usage
logger.info("{}", messages.get("status.managerstarted", localIP, httpPort));
this.coapServer = new Shelly1CoapServer();
}
@Override

View File

@ -15,15 +15,15 @@ package org.openhab.binding.shelly.internal.api;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
/**
@ -47,11 +47,11 @@ public interface ShellyApiInterface {
public void setSleepTime(int value) throws ShellyApiException;
public ShellyStatusRelay getRelayStatus(Integer relayIndex) throws ShellyApiException;
public ShellyStatusRelay getRelayStatus(int relayIndex) throws ShellyApiException;
public void setRelayTurn(int id, String turnMode) throws ShellyApiException;
public ShellyControlRoller getRollerStatus(int rollerIndex) throws ShellyApiException;
public ShellyRollerStatus getRollerStatus(int rollerIndex) throws ShellyApiException;
public void setRollerTurn(int relayIndex, String turnMode) throws ShellyApiException;

View File

@ -13,7 +13,7 @@
package org.openhab.binding.shelly.internal.api;
import static org.eclipse.jetty.http.HttpStatus.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@ -33,6 +33,7 @@ public class ShellyApiResult {
public String response = "";
public int httpCode = -1;
public String httpReason = "";
public String authResponse = "";
public ShellyApiResult() {
}

View File

@ -13,7 +13,8 @@
package org.openhab.binding.shelly.internal.api;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.HashMap;
@ -23,12 +24,12 @@ import java.util.regex.Pattern;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsGlobal;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsInput;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsGlobal;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsInput;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.util.ShellyVersionDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -63,6 +64,7 @@ public class ShellyDeviceProfile {
public boolean discoverable = true;
public boolean auth = false;
public boolean alwaysOn = true;
public boolean isGen2 = false;
public String hwRev = "";
public String hwBatchId = "";
@ -93,7 +95,7 @@ public class ShellyDeviceProfile {
public boolean isHT = false; // true for H&T
public boolean isDW = false; // true for Door Window sensor
public boolean isButton = false; // true for a Shelly Button 1
public boolean isIX3 = false; // true for a Shelly IX
public boolean isIX = false; // true for a Shelly IX
public boolean isTRV = false; // true for a Shelly TRV
public int minTemp = 0; // Bulb/Duo: Min Light Temp
@ -202,11 +204,12 @@ public class ShellyDeviceProfile {
boolean isSmoke = thingType.equals(THING_TYPE_SHELLYSMOKE_STR);
boolean isGas = thingType.equals(THING_TYPE_SHELLYGAS_STR);
boolean isUNI = thingType.equals(THING_TYPE_SHELLYUNI_STR);
isHT = thingType.equals(THING_TYPE_SHELLYHT_STR);
isHT = thingType.equals(THING_TYPE_SHELLYHT_STR) || thingType.equals(THING_TYPE_SHELLYPLUSHT_STR);
isDW = thingType.equals(THING_TYPE_SHELLYDOORWIN_STR) || thingType.equals(THING_TYPE_SHELLYDOORWIN2_STR);
isMotion = thingType.startsWith(THING_TYPE_SHELLYMOTION_STR);
isSense = thingType.equals(THING_TYPE_SHELLYSENSE_STR);
isIX3 = thingType.equals(THING_TYPE_SHELLYIX3_STR);
isIX = thingType.equals(THING_TYPE_SHELLYIX3_STR) || thingType.equals(THING_TYPE_SHELLYPLUSI4_STR)
|| thingType.equals(THING_TYPE_SHELLYPLUSI4DC_STR);
isButton = thingType.equals(THING_TYPE_SHELLYBUTTON1_STR) || thingType.equals(THING_TYPE_SHELLYBUTTON2_STR);
isSensor = isHT || isFlood || isDW || isSmoke || isGas || isButton || isUNI || isMotion || isSense || isTRV;
hasBattery = isHT || isFlood || isDW || isSmoke || isButton || isMotion || isTRV;
@ -261,7 +264,7 @@ public class ShellyDeviceProfile {
int idx = i + 1; // group names are 1-based
if (isRGBW2) {
return CHANNEL_GROUP_LIGHT_CONTROL;
} else if (isIX3) {
} else if (isIX) {
return CHANNEL_GROUP_STATUS + idx;
} else if (isButton) {
return CHANNEL_GROUP_STATUS;
@ -275,7 +278,7 @@ public class ShellyDeviceProfile {
public String getInputSuffix(int i) {
int idx = i + 1; // channel names are 1-based
if (isRGBW2 || isIX3) {
if (isRGBW2 || isIX) {
return ""; // RGBW2 has only 1 channel
} else if (isRoller || isDimmer) {
// Roller has 2 relays, but it will be mapped to 1 roller with 2 inputs
@ -294,7 +297,7 @@ public class ShellyDeviceProfile {
String btnType = "";
if (isButton) {
return true;
} else if (isIX3 && settings.inputs != null && idx < settings.inputs.size()) {
} else if (isIX && settings.inputs != null && idx < settings.inputs.size()) {
ShellySettingsInput input = settings.inputs.get(idx);
btnType = getString(input.btnType);
} else if (isDimmer) {

View File

@ -0,0 +1,245 @@
/**
* 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.shelly.internal.api;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.SHELLY_API_TIMEOUT_MS;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
/**
* {@link ShellyHttpClient} implements basic HTTP access
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyHttpClient {
private final Logger logger = LoggerFactory.getLogger(ShellyHttpClient.class);
public static final String HTTP_HEADER_AUTH = "Authorization";
public static final String HTTP_AUTH_TYPE_BASIC = "Basic";
public static final String CONTENT_TYPE_JSON = "application/json; charset=UTF-8";
public static final String CONTENT_TYPE_FORM_URLENC = "application/x-www-form-urlencoded";
protected final HttpClient httpClient;
protected ShellyThingConfiguration config = new ShellyThingConfiguration();
protected String thingName;
protected final Gson gson = new Gson();
protected int timeoutErrors = 0;
protected int timeoutsRecovered = 0;
private ShellyDeviceProfile profile;
public ShellyHttpClient(String thingName, ShellyThingInterface thing) {
this(thingName, thing.getThingConfig(), thing.getHttpClient());
this.profile = thing.getProfile();
profile.initFromThingType(thingName);
}
public ShellyHttpClient(String thingName, ShellyThingConfiguration config, HttpClient httpClient) {
profile = new ShellyDeviceProfile();
this.thingName = thingName;
setConfig(thingName, config);
this.httpClient = httpClient;
}
public void initialize() throws ShellyApiException {
}
public void setConfig(String thingName, ShellyThingConfiguration config) {
this.thingName = thingName;
this.config = config;
}
/**
* Submit GET request and return response, check for invalid responses
*
* @param uri: URI (e.g. "/settings")
*/
public <T> T callApi(String uri, Class<T> classOfT) throws ShellyApiException {
String json = httpRequest(uri);
return fromJson(gson, json, classOfT);
}
public <T> T postApi(String uri, String data, Class<T> classOfT) throws ShellyApiException {
String json = httpPost(uri, data);
return fromJson(gson, json, classOfT);
}
protected String httpRequest(String uri) throws ShellyApiException {
ShellyApiResult apiResult = new ShellyApiResult();
int retries = 3;
boolean timeout = false;
while (retries > 0) {
try {
apiResult = innerRequest(HttpMethod.GET, uri, "");
if (timeout) {
logger.debug("{}: API timeout #{}/{} recovered ({})", thingName, timeoutErrors, timeoutsRecovered,
apiResult.getUrl());
timeoutsRecovered++;
}
return apiResult.response; // successful
} catch (ShellyApiException e) {
if ((!e.isTimeout() && !apiResult.isHttpServerError()) && !apiResult.isNotFound() || profile.hasBattery
|| (retries == 0)) {
// Sensor in sleep mode or API exception for non-battery device or retry counter expired
throw e; // non-timeout exception
}
timeout = true;
retries--;
timeoutErrors++; // count the retries
logger.debug("{}: API Timeout, retry #{} ({})", thingName, timeoutErrors, e.toString());
}
}
throw new ShellyApiException("API Timeout or inconsistent result"); // successful
}
public String httpPost(String uri, String data) throws ShellyApiException {
return innerRequest(HttpMethod.POST, uri, data).response;
}
private ShellyApiResult innerRequest(HttpMethod method, String uri, String data) throws ShellyApiException {
Request request = null;
String url = "http://" + config.deviceIp + uri;
ShellyApiResult apiResult = new ShellyApiResult(method.toString(), url);
try {
request = httpClient.newRequest(url).method(method.toString()).timeout(SHELLY_API_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
if (!config.password.isEmpty() && !getString(data).contains("\"auth\":{")) {
String value = config.userId + ":" + config.password;
request.header(HTTP_HEADER_AUTH,
HTTP_AUTH_TYPE_BASIC + " " + Base64.getEncoder().encodeToString(value.getBytes()));
}
fillPostData(request, data);
logger.trace("{}: HTTP {} for {} {}", thingName, method, url, data);
// Do request and get response
ContentResponse contentResponse = request.send();
apiResult = new ShellyApiResult(contentResponse);
apiResult.httpCode = contentResponse.getStatus();
String response = contentResponse.getContentAsString().replace("\t", "").replace("\r\n", "").trim();
logger.trace("{}: HTTP Response {}: {}", thingName, contentResponse.getStatus(), response);
HttpFields headers = contentResponse.getHeaders();
String auth = headers.get(HttpHeader.WWW_AUTHENTICATE);
if (!getString(auth).isEmpty()) {
apiResult.authResponse = auth;
}
// validate response, API errors are reported as Json
if (apiResult.httpCode != HttpStatus.OK_200) {
throw new ShellyApiException(apiResult);
}
if (response.isEmpty() || !response.startsWith("{") && !response.startsWith("[") && !url.contains("/debug/")
&& !url.contains("/sta_cache_reset")) {
throw new ShellyApiException("Unexpected response: " + response);
}
} catch (ExecutionException | InterruptedException | TimeoutException | IllegalArgumentException e) {
ShellyApiException ex = new ShellyApiException(apiResult, e);
if (!ex.isTimeout()) { // will be handled by the caller
logger.trace("{}: API call returned exception", thingName, ex);
}
throw ex;
}
return apiResult;
}
/**
* Fill in POST data, set http headers
*
* @param request HTTP request structure
* @param data POST data, might be empty
*/
private void fillPostData(Request request, String data) {
boolean json = data.startsWith("{") || data.contains("\": {");
String type = json ? CONTENT_TYPE_JSON : CONTENT_TYPE_FORM_URLENC;
request.header(HttpHeader.CONTENT_TYPE, type);
if (!data.isEmpty()) {
StringContentProvider postData;
postData = new StringContentProvider(type, data, StandardCharsets.UTF_8);
request.content(postData);
request.header(HttpHeader.CONTENT_LENGTH, Long.toString(postData.getLength()));
}
}
/**
* Format POST body depending on content type (JSON or form encoded)
*
* @param dataMap Field list
* @param json true=JSON format, false=form encoded
* @return formatted body
*/
public static String buildPostData(Map<String, String> dataMap, boolean json) {
String data = "";
for (Map.Entry<String, String> e : dataMap.entrySet()) {
data = data + (data.isEmpty() ? "" : json ? ", " : "&");
if (!json) {
data = data + e.getKey() + "=" + e.getValue();
} else {
data = data + "\"" + e.getKey() + "\" : \"" + e.getValue() + "\"";
}
}
return json ? "{ " + data + " }" : data;
}
public String getControlUriPrefix(Integer id) {
String uri = "";
if (profile.isLight || profile.isDimmer) {
if (profile.isDuo || profile.isDimmer) {
// Duo + Dimmer
uri = SHELLY_URL_CONTROL_LIGHT;
} else {
// Bulb + RGBW2
uri = "/" + (profile.inColor ? SHELLY_MODE_COLOR : SHELLY_MODE_WHITE);
}
} else {
// Roller, Relay
uri = SHELLY_URL_CONTROL_RELEAY;
}
uri = uri + "/" + id;
return uri;
}
public int getTimeoutErrors() {
return timeoutErrors;
}
public int getTimeoutsRecovered() {
return timeoutsRecovered;
}
}

View File

@ -10,22 +10,22 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.api;
package org.openhab.binding.shelly.internal.api1;
import java.util.ArrayList;
import java.util.List;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor.ShellyMotionSettings;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyMotionSettings;
import org.openhab.core.thing.CommonTriggerEvents;
import com.google.gson.annotations.SerializedName;
/**
* The {@link ShellyApiJsonDTO} is used for the JSon/GSon mapping
* The {@link Shelly1ApiJsonDTO} is used for the JSon/GSon mapping
*
* @author Markus Michels - Initial contribution
*/
public class ShellyApiJsonDTO {
public class Shelly1ApiJsonDTO {
public static final String SHELLY_NULL_URL = "null";
public static final String SHELLY_URL_DEVINFO = "/shelly";
public static final String SHELLY_URL_STATUS = "/status";
@ -264,6 +264,7 @@ public class ShellyApiJsonDTO {
public String hostname;
public String fw;
public Boolean auth;
public Integer gen;
@SerializedName("coiot") // Shelly Motion Multicast Endpoint
public String coiot;
@ -495,6 +496,7 @@ public class ShellyApiJsonDTO {
public String name;
public Boolean ison; // true: output is ON
public Integer brightness;
public Integer temp;
public Integer transition;
@SerializedName("default_state")
public String defaultState;
@ -728,7 +730,7 @@ public class ShellyApiJsonDTO {
public ArrayList<ShellySettingsEMeter> emeters;
// Internal device temp
public ShellyStatusSensor.ShellySensorTmp tmp; // Shelly 1PM
public ShellySensorTmp tmp; // Shelly 1PM
public Double temperature = SHELLY_API_INVTEMP; // Shelly 2.5
public Boolean overtemperature;
@ -818,7 +820,7 @@ public class ShellyApiJsonDTO {
public ShellyStatusSensor.ShellyExtHumidity extHumidity; // Shelly 1/1PM: sensor values
public Double temperature; // device temp acc. on the selected temp unit
public ShellyStatusSensor.ShellySensorTmp tmp;
public ShellySensorTmp tmp;
}
public static class ShellyStatusDimmer {
@ -827,14 +829,14 @@ public class ShellyApiJsonDTO {
public ArrayList<ShellyShortLightStatus> lights; // relay status
public ArrayList<ShellySettingsMeter> meters; // current meter value
public ShellyStatusSensor.ShellySensorTmp tmp;
public ShellySensorTmp tmp;
public Boolean overtemperature;
public Boolean loaderror;
public Boolean overload;
}
public static class ShellyControlRoller {
public static class ShellyRollerStatus {
public String name; // FW 1.8: Symbolic name is configurable
@SerializedName("roller_pos")
@ -900,17 +902,17 @@ public class ShellyApiJsonDTO {
public Integer boostMinutes;
}
public static class ShellySensorTmp {
public Double value; // Temperature in configured unites
public String units; // 'C' or 'F'
public Double tC; // temperature in deg C
public Double tF; // temperature in deg F
@SerializedName("is_valid")
public Boolean isValid; // whether the internal sensor is operating properly
}
public static class ShellyStatusSensor {
// https://shelly-api-docs.shelly.cloud/#h-amp-t-settings
public static class ShellySensorTmp {
public Double value; // Temperature in configured unites
public String units; // 'C' or 'F'
public Double tC; // temperature in deg C
public Double tF; // temperature in deg F
@SerializedName("is_valid")
public Boolean isValid; // whether the internal sensor is operating properly
}
public static class ShellySensorHum {
public Double value; // relative humidity in %
}

View File

@ -10,26 +10,26 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.core.types.State;
/**
* The {@link ShellyCoapListener} describes the listening interface to process Coap responses
* The {@link Shelly1CoapListener} describes the listening interface to process Coap responses
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public interface ShellyCoIoTInterface {
public interface Shelly1CoIoTInterface {
public int getVersion();
public CoIotDescrSen fixDescription(@Nullable CoIotDescrSen sen, Map<String, CoIotDescrBlk> blkMap);

View File

@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.List;
@ -23,9 +23,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.library.types.OnOffType;
@ -41,13 +41,13 @@ import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
/**
* The {@link ShellyCoIoTProtocol} implements common functions for the CoIoT implementations
* The {@link Shelly1CoIoTProtocol} implements common functions for the CoIoT implementations
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyCoIoTProtocol {
private final Logger logger = LoggerFactory.getLogger(ShellyCoIoTProtocol.class);
public class Shelly1CoIoTProtocol {
private final Logger logger = LoggerFactory.getLogger(Shelly1CoIoTProtocol.class);
protected final String thingName;
protected final ShellyThingInterface thingHandler;
protected final ShellyDeviceProfile profile;
@ -63,7 +63,7 @@ public class ShellyCoIoTProtocol {
protected String[] inputEvent = { "", "", "", "", "", "", "", "" };
protected String lastWakeup = "";
public ShellyCoIoTProtocol(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
public Shelly1CoIoTProtocol(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
Map<String, CoIotDescrSen> sensorMap) {
this.thingName = thingName;
this.thingHandler = thingHandler;

View File

@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.List;
@ -21,9 +21,9 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.library.types.OnOffType;
@ -35,22 +35,22 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link ShellyCoIoTVersion1} implements the parsing for CoIoT version 1
* The {@link Shelly1CoIoTVersion1} implements the parsing for CoIoT version 1
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyCoIoTVersion1 extends ShellyCoIoTProtocol implements ShellyCoIoTInterface {
private final Logger logger = LoggerFactory.getLogger(ShellyCoIoTVersion1.class);
public class Shelly1CoIoTVersion1 extends Shelly1CoIoTProtocol implements Shelly1CoIoTInterface {
private final Logger logger = LoggerFactory.getLogger(Shelly1CoIoTVersion1.class);
public ShellyCoIoTVersion1(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
public Shelly1CoIoTVersion1(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
Map<String, CoIotDescrSen> sensorMap) {
super(thingName, thingHandler, blkMap, sensorMap);
}
@Override
public int getVersion() {
return ShellyCoapJSonDTO.COIOT_VERSION_1;
return Shelly1CoapJSonDTO.COIOT_VERSION_1;
}
/**

View File

@ -11,14 +11,14 @@
* SPDX-License-Identifier: EPL-2.0
*/
/**
* The {@link ShellyCoIoTVersion1} implements the parsing for CoIoT version 1
* The {@link Shelly1CoIoTVersion1} implements the parsing for CoIoT version 1
*
* @author Markus Michels - Initial contribution
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.List;
@ -26,9 +26,9 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.library.types.OnOffType;
@ -41,22 +41,22 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link ShellyCoIoTVersion1} implements the parsing for CoIoT version 2
* The {@link Shelly1CoIoTVersion1} implements the parsing for CoIoT version 2
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyCoIoTVersion2 extends ShellyCoIoTProtocol implements ShellyCoIoTInterface {
private final Logger logger = LoggerFactory.getLogger(ShellyCoIoTVersion2.class);
public class Shelly1CoIoTVersion2 extends Shelly1CoIoTProtocol implements Shelly1CoIoTInterface {
private final Logger logger = LoggerFactory.getLogger(Shelly1CoIoTVersion2.class);
public ShellyCoIoTVersion2(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
public Shelly1CoIoTVersion2(String thingName, ShellyThingInterface thingHandler, Map<String, CoIotDescrBlk> blkMap,
Map<String, CoIotDescrSen> sensorMap) {
super(thingName, thingHandler, blkMap, sensorMap);
}
@Override
public int getVersion() {
return ShellyCoapJSonDTO.COIOT_VERSION_2;
return Shelly1CoapJSonDTO.COIOT_VERSION_2;
}
/**

View File

@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.net.SocketException;
@ -38,13 +38,13 @@ import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDevDescrTypeAdapter;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotDevDescription;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotGenericSensorList;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.CoIotSensorTypeAdapter;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrBlk;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDescrSen;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDevDescrTypeAdapter;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotDevDescription;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotGenericSensorList;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.CoIotSensorTypeAdapter;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyColorUtils;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
@ -58,15 +58,15 @@ import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
/**
* The {@link ShellyCoapHandler} handles the CoIoT/CoAP registration and events.
* The {@link Shelly1CoapHandler} handles the CoIoT/CoAP registration and events.
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyCoapHandler implements ShellyCoapListener {
public class Shelly1CoapHandler implements Shelly1CoapListener {
private static final byte[] EMPTY_BYTE = new byte[0];
private final Logger logger = LoggerFactory.getLogger(ShellyCoapHandler.class);
private final Logger logger = LoggerFactory.getLogger(Shelly1CoapHandler.class);
private final ShellyThingInterface thingHandler;
private ShellyThingConfiguration config = new ShellyThingConfiguration();
private final GsonBuilder gsonBuilder = new GsonBuilder();
@ -74,10 +74,10 @@ public class ShellyCoapHandler implements ShellyCoapListener {
private String thingName;
private boolean coiotBound = false;
private ShellyCoIoTInterface coiot;
private Shelly1CoIoTInterface coiot;
private int coiotVers = -1;
private final ShellyCoapServer coapServer;
private final Shelly1CoapServer coapServer;
private @Nullable CoapClient statusClient;
private Request reqDescription = new Request(Code.GET, Type.CON);
private Request reqStatus = new Request(Code.GET, Type.CON);
@ -93,13 +93,13 @@ public class ShellyCoapHandler implements ShellyCoapListener {
private ShellyDeviceProfile profile;
private ShellyApiInterface api;
public ShellyCoapHandler(ShellyThingInterface thingHandler, ShellyCoapServer coapServer) {
public Shelly1CoapHandler(ShellyThingInterface thingHandler, Shelly1CoapServer coapServer) {
this.thingHandler = thingHandler;
this.thingName = thingHandler.getThingName();
this.profile = thingHandler.getProfile();
this.api = thingHandler.getApi();
this.coapServer = coapServer;
this.coiot = new ShellyCoIoTVersion2(thingName, thingHandler, blkMap, sensorMap); // Default: V2
this.coiot = new Shelly1CoIoTVersion2(thingName, thingHandler, blkMap, sensorMap); // Default: V2
gsonBuilder.registerTypeAdapter(CoIotDevDescription.class, new CoIotDevDescrTypeAdapter());
gsonBuilder.registerTypeAdapter(CoIotGenericSensorList.class, new CoIotSensorTypeAdapter());
@ -240,9 +240,9 @@ public class ShellyCoapHandler implements ShellyCoapListener {
thingHandler.updateProperties(PROPERTY_COAP_VERSION, sVersion);
logger.debug("{}: CoIoT Version {} detected", thingName, iVersion);
if (iVersion == COIOT_VERSION_1) {
coiot = new ShellyCoIoTVersion1(thingName, thingHandler, blkMap, sensorMap);
coiot = new Shelly1CoIoTVersion1(thingName, thingHandler, blkMap, sensorMap);
} else if (iVersion == COIOT_VERSION_2) {
coiot = new ShellyCoIoTVersion2(thingName, thingHandler, blkMap, sensorMap);
coiot = new Shelly1CoIoTVersion2(thingName, thingHandler, blkMap, sensorMap);
} else {
logger.warn("{}: Unsupported CoAP version detected: {}", thingName, sVersion);
return;

View File

@ -10,7 +10,7 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import java.io.IOException;
import java.util.ArrayList;
@ -23,11 +23,11 @@ import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
/**
* The {@link ShellyCoapJSonDTO} helps the CoIoT Json into Java objects
* The {@link Shelly1CoapJSonDTO} helps the CoIoT Json into Java objects
*
* @author Markus Michels - Initial contribution
*/
public class ShellyCoapJSonDTO {
public class Shelly1CoapJSonDTO {
// Coap
public static final int COIOT_VERSION_1 = 1;
public static final int COIOT_VERSION_2 = 2;

View File

@ -10,18 +10,18 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import org.eclipse.californium.core.coap.Response;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* The {@link ShellyCoapListener} describes the listening interface to process Coap responses
* The {@link Shelly1CoapListener} describes the listening interface to process Coap responses
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public interface ShellyCoapListener {
public interface Shelly1CoapListener {
public void processResponse(@Nullable Response response);
}

View File

@ -10,9 +10,9 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.coap;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO.COIOT_PORT;
import static org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO.COIOT_PORT;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -38,24 +38,24 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The {@link ShellyCoapServer} implements the UDP listener and status event processor (for /cit/s messages)
* The {@link Shelly1CoapServer} implements the UDP listener and status event processor (for /cit/s messages)
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyCoapServer {
private final Logger logger = LoggerFactory.getLogger(ShellyCoapServer.class);
public class Shelly1CoapServer {
private final Logger logger = LoggerFactory.getLogger(Shelly1CoapServer.class);
boolean started = false;
private CoapEndpoint statusEndpoint = new CoapEndpoint.Builder().build();
private @Nullable UdpMulticastConnector statusConnector;
private CoapServer server = new CoapServer(NetworkConfig.getStandard(), COIOT_PORT);
private final Set<ShellyCoapListener> coapListeners = ConcurrentHashMap.newKeySet();
private final Set<Shelly1CoapListener> coapListeners = ConcurrentHashMap.newKeySet();
protected class ShellyStatusListener extends CoapResource {
private ShellyCoapServer listener;
private Shelly1CoapServer listener;
public ShellyStatusListener(String uri, ShellyCoapServer listener) {
public ShellyStatusListener(String uri, Shelly1CoapServer listener) {
super(uri, true);
getAttributes().setTitle("ShellyCoapListener");
this.listener = listener;
@ -78,7 +78,7 @@ public class ShellyCoapServer {
}
}
public synchronized void start(String localIp, int port, ShellyCoapListener listener)
public synchronized void start(String localIp, int port, Shelly1CoapListener listener)
throws UnknownHostException, SocketException {
if (!started) {
logger.debug("Initializing CoIoT listener (local IP={}:{})", localIp, port);
@ -125,7 +125,7 @@ public class ShellyCoapServer {
/**
* Cancel pending requests and shutdown the client
*/
public void stop(ShellyCoapListener listener) {
public void stop(Shelly1CoapListener listener) {
coapListeners.remove(listener);
if (coapListeners.isEmpty()) {
stop();

View File

@ -10,10 +10,10 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.binding.shelly.internal.api;
package org.openhab.binding.shelly.internal.api1;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.nio.charset.StandardCharsets;
@ -31,61 +31,59 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySendKeyList;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySenseKeyCode;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsUpdate;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpClient;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySendKeyList;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySenseKeyCode;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsUpdate;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.library.unit.ImperialUnits;
import org.openhab.core.library.unit.SIUnits;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
/**
* {@link ShellyHttpApi} wraps the Shelly REST API and provides various low level function to access the device api (not
* {@link Shelly1HttpApi} wraps the Shelly REST API and provides various low level function to access the device api
* (not
* cloud api).
*
* @author Markus Michels - Initial contribution
*/
@NonNullByDefault
public class ShellyHttpApi implements ShellyApiInterface {
public static final String HTTP_HEADER_AUTH = "Authorization";
public static final String HTTP_AUTH_TYPE_BASIC = "Basic";
public static final String CONTENT_TYPE_JSON = "application/json; charset=UTF-8";
public class Shelly1HttpApi extends ShellyHttpClient implements ShellyApiInterface {
private final Logger logger = LoggerFactory.getLogger(Shelly1HttpApi.class);
private final ShellyDeviceProfile profile;
private final Logger logger = LoggerFactory.getLogger(ShellyHttpApi.class);
private final HttpClient httpClient;
private ShellyThingConfiguration config = new ShellyThingConfiguration();
private String thingName;
private final Gson gson = new Gson();
private int timeoutErrors = 0;
private int timeoutsRecovered = 0;
private ShellyDeviceProfile profile = new ShellyDeviceProfile();
public ShellyHttpApi(String thingName, ShellyThingConfiguration config, HttpClient httpClient) {
this.httpClient = httpClient;
this.thingName = thingName;
setConfig(thingName, config);
profile.initFromThingType(thingName);
public Shelly1HttpApi(String thingName, ShellyThingInterface thing) {
super(thingName, thing);
profile = thing.getProfile();
}
@Override
public void setConfig(String thingName, ShellyThingConfiguration config) {
this.thingName = thingName;
this.config = config;
/**
* Simple initialization - called by discovery handler
*
* @param thingName Symbolic thing name
* @param config Thing Configuration
* @param httpClient HTTP Client to be passed to ShellyHttpClient
*/
public Shelly1HttpApi(String thingName, ShellyThingConfiguration config, HttpClient httpClient) {
super(thingName, config, httpClient);
this.profile = new ShellyDeviceProfile();
}
@Override
@ -112,7 +110,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
*/
@Override
public ShellyDeviceProfile getDeviceProfile(String thingType) throws ShellyApiException {
String json = request(SHELLY_URL_SETTINGS);
String json = httpRequest(SHELLY_URL_SETTINGS);
if (json.contains("\"type\":\"SHDM-")) {
logger.trace("{}: Detected a Shelly Dimmer: fix Json (replace lights[] tag with dimmers[]", thingName);
json = fixDimmerJson(json);
@ -151,7 +149,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
public ShellySettingsStatus getStatus() throws ShellyApiException {
String json = "";
try {
json = request(SHELLY_URL_STATUS);
json = httpRequest(SHELLY_URL_STATUS);
// Dimmer2 returns invalid json type for loaderror :-(
json = getString(json.replace("\"loaderror\":0,", "\"loaderror\":false,"));
json = getString(json.replace("\"loaderror\":1,", "\"loaderror\":true,"));
@ -164,8 +162,8 @@ public class ShellyHttpApi implements ShellyApiInterface {
}
@Override
public ShellyStatusRelay getRelayStatus(Integer relayIndex) throws ShellyApiException {
return callApi(SHELLY_URL_STATUS_RELEAY + "/" + relayIndex.toString(), ShellyStatusRelay.class);
public ShellyStatusRelay getRelayStatus(int relayIndex) throws ShellyApiException {
return callApi(SHELLY_URL_STATUS_RELEAY + "/" + relayIndex, ShellyStatusRelay.class);
}
@Override
@ -183,27 +181,23 @@ public class ShellyHttpApi implements ShellyApiInterface {
@Override
public void setBrightness(int id, int brightness, boolean autoOn) throws ShellyApiException {
String turn = autoOn ? SHELLY_LIGHT_TURN + "=" + SHELLY_API_ON + "&" : "";
request(getControlUriPrefix(id) + "?" + turn + "brightness=" + brightness);
httpRequest(getControlUriPrefix(id) + "?" + turn + "brightness=" + brightness);
}
@Override
public ShellyControlRoller getRollerStatus(int idx) throws ShellyApiException {
String uri = SHELLY_URL_CONTROL_ROLLER + "/" + idx + "/pos";
return callApi(uri, ShellyControlRoller.class);
public ShellyRollerStatus getRollerStatus(int rollerIndex) throws ShellyApiException {
String uri = SHELLY_URL_CONTROL_ROLLER + "/" + rollerIndex + "/pos";
return callApi(uri, ShellyRollerStatus.class);
}
@Override
public void setRollerTurn(int idx, String turnMode) throws ShellyApiException {
request(SHELLY_URL_CONTROL_ROLLER + "/" + idx + "?go=" + turnMode);
public void setRollerTurn(int relayIndex, String turnMode) throws ShellyApiException {
httpRequest(SHELLY_URL_CONTROL_ROLLER + "/" + relayIndex + "?go=" + turnMode);
}
@Override
public void setRollerPos(int id, int position) throws ShellyApiException {
request(SHELLY_URL_CONTROL_ROLLER + "/" + id + "?go=to_pos&roller_pos=" + position);
}
public void setRollerTimer(int idx, int timer) throws ShellyApiException {
request(SHELLY_URL_CONTROL_ROLLER + "/" + idx + "?timer=" + timer);
public void setRollerPos(int relayIndex, int position) throws ShellyApiException {
httpRequest(SHELLY_URL_CONTROL_ROLLER + "/" + relayIndex + "?go=to_pos&roller_pos=" + position);
}
@Override
@ -239,12 +233,12 @@ public class ShellyHttpApi implements ShellyApiInterface {
type = SHELLY_CLASS_LIGHT;
}
String uri = SHELLY_URL_SETTINGS + "/" + type + "/" + index + "?" + timerName + "=" + value;
request(uri);
httpRequest(uri);
}
@Override
public void setSleepTime(int value) throws ShellyApiException {
request(SHELLY_URL_SETTINGS + "?sleep_time=" + value);
httpRequest(SHELLY_URL_SETTINGS + "?sleep_time=" + value);
}
@Override
@ -258,7 +252,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
if (auto) {
uri = uri + "&target_t=" + getDouble(profile.settings.thermostats.get(0).targetTemp.value);
}
request(uri); // percentage to open the valve
httpRequest(uri); // percentage to open the valve
}
@Override
@ -280,12 +274,12 @@ public class ShellyHttpApi implements ShellyApiInterface {
@Override
public void startValveBoost(int valveId, int value) throws ShellyApiException {
int minutes = value != -1 ? value : getInteger(profile.settings.thermostats.get(0).boostMinutes);
request("/thermostat/" + valveId + "?boost_minutes=" + minutes);
httpRequest("/thermostat/0?boost_minutes=" + minutes);
}
@Override
public void setLedStatus(String ledName, Boolean value) throws ShellyApiException {
request(SHELLY_URL_SETTINGS + "?" + ledName + "=" + (value ? SHELLY_API_TRUE : SHELLY_API_FALSE));
httpRequest(SHELLY_URL_SETTINGS + "?" + ledName + "=" + (value ? SHELLY_API_TRUE : SHELLY_API_FALSE));
}
public ShellySettingsLight getLightSettings() throws ShellyApiException {
@ -298,7 +292,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
}
public void setLightSetting(String parm, String value) throws ShellyApiException {
request(SHELLY_URL_SETTINGS + "?" + parm + "=" + value);
httpRequest(SHELLY_URL_SETTINGS + "?" + parm + "=" + value);
}
@Override
@ -396,7 +390,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
public void setLightParm(int lightIndex, String parm, String value) throws ShellyApiException {
// Bulb, RGW2: /<color mode>/<light id>?parm?value
// Dimmer: /light/<light id>?parm=value
request(getControlUriPrefix(lightIndex) + "?" + parm + "=" + value);
httpRequest(getControlUriPrefix(lightIndex) + "?" + parm + "=" + value);
}
@Override
@ -410,7 +404,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
url = url + key + "=" + parameters.get(key);
i++;
}
request(url);
httpRequest(url);
}
/**
@ -422,7 +416,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
* @throws ShellyApiException
*/
public Map<String, String> getIRCodeList() throws ShellyApiException {
String result = request(SHELLY_URL_LIST_IR);
String result = httpRequest(SHELLY_URL_LIST_IR);
// take pragmatic approach to make the returned JSon into named arrays for Gson parsing
String keyList = substringAfter(result, "[");
keyList = substringBeforeLast(keyList, "]");
@ -468,11 +462,11 @@ public class ShellyHttpApi implements ShellyApiInterface {
} else if (type.equals(SHELLY_IR_CODET_PRONTO_HEX)) {
url = url + "&" + SHELLY_IR_CODET_PRONTO_HEX + "=" + keyCode;
}
request(url);
httpRequest(url);
}
public void setSenseSetting(String setting, String value) throws ShellyApiException {
request(SHELLY_URL_SETTINGS + "?" + setting + "=" + value);
httpRequest(SHELLY_URL_SETTINGS + "?" + setting + "=" + value);
}
/**
@ -500,7 +494,8 @@ public class ShellyHttpApi implements ShellyApiInterface {
private void setDimmerEvents() throws ShellyApiException {
if (profile.settings.dimmers != null) {
for (int i = 0; i < profile.settings.dimmers.size(); i++) {
int sz = profile.settings.dimmers.size();
for (int i = 0; i < sz; i++) {
setEventUrls(i);
}
} else if (profile.isLight) {
@ -574,7 +569,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
if (!profile.settingsJson.contains(testUrl)) {
// Current Action URL is != new URL
logger.debug("{}: Set new url for event type {}: {}", thingName, eventType, newUrl);
request(SHELLY_URL_SETTINGS + "?" + mkEventUrl(eventType) + "=" + urlEncode(newUrl));
httpRequest(SHELLY_URL_SETTINGS + "?" + mkEventUrl(eventType) + "=" + urlEncode(newUrl));
}
}
}
@ -597,8 +592,8 @@ public class ShellyHttpApi implements ShellyApiInterface {
if (!profile.settingsJson.contains(test)) {
// Current Action URL is != new URL
logger.debug("{}: Set URL for type {} to {}", thingName, eventType, newUrl);
request(SHELLY_URL_SETTINGS + "/" + deviceClass + "/" + index + "?" + mkEventUrl(eventType) + "="
+ urlEncode(newUrl));
httpRequest(SHELLY_URL_SETTINGS + "/" + deviceClass + "/" + index + "?" + mkEventUrl(eventType)
+ "=" + urlEncode(newUrl));
}
}
}
@ -613,6 +608,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
*
* @param uri: URI (e.g. "/settings")
*/
@Override
public <T> T callApi(String uri, Class<T> classOfT) throws ShellyApiException {
String json = request(uri);
return fromJson(gson, json, classOfT);
@ -687,6 +683,7 @@ public class ShellyHttpApi implements ShellyApiInterface {
return apiResult;
}
@Override
public String getControlUriPrefix(Integer id) {
String uri = "";
if (profile.isLight || profile.isDimmer) {

View File

@ -29,7 +29,7 @@ import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpApi;
import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyBaseHandler;
@ -140,7 +140,7 @@ public class ShellyDiscoveryParticipant implements MDNSDiscoveryParticipant {
config.password = bindingConfig.defaultPassword;
try {
ShellyHttpApi api = new ShellyHttpApi(name, config, httpClient);
Shelly1HttpApi api = new Shelly1HttpApi(name, config, httpClient);
profile = api.getDeviceProfile(thingType);
logger.debug("{}: Shelly settings : {}", name, profile.settingsJson);

View File

@ -12,8 +12,8 @@
*/
package org.openhab.binding.shelly.internal.discovery;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.BINDING_ID;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.LinkedHashMap;
@ -30,6 +30,219 @@ import org.openhab.core.thing.ThingUID;
*/
@NonNullByDefault
public class ShellyThingCreator {
// Device Types
public static final String SHELLYDT_1 = "SHSW-1";
public static final String SHELLYDT_1PM = "SHSW-PM";
public static final String SHELLYDT_1L = "SHSW-L";
public static final String SHELLYDT_SHPLG = "SHPLG-1";
public static final String SHELLYDT_SHPLG_S = "SHPLG-S";
public static final String SHELLYDT_SHPLG_U1 = "SHPLG-U1";
public static final String SHELLYDT_SHELLY2 = "SHSW-21";
public static final String SHELLYDT_SHELLY25 = "SHSW-25";
public static final String SHELLYDT_SHPRO = "SHSW-44";
public static final String SHELLYDT_EM = "SHEM";
public static final String SHELLYDT_3EM = "SHEM-3";
public static final String SHELLYDT_HT = "SHHT-1";
public static final String SHELLYDT_DW = "SHDW-1";
public static final String SHELLYDT_DW2 = "SHDW-2";
public static final String SHELLYDT_SENSE = "SHSEN-1";
public static final String SHELLYDT_MOTION = "SHMOS-01";
public static final String SHELLYDT_MOTION2 = "SHMOS-02";
public static final String SHELLYDT_GAS = "SHGS-1";
public static final String SHELLYDT_DIMMER = "SHDM-1";
public static final String SHELLYDT_DIMMER2 = "SHDM-2";
public static final String SHELLYDT_IX3 = "SHIX3-1";
public static final String SHELLYDT_BULB = "SHBLB-1";
public static final String SHELLYDT_DUO = "SHBDUO-1";
public static final String SHELLYDT_DUORGBW = "SHCB-1";
public static final String SHELLYDT_VINTAGE = "SHVIN-1";
public static final String SHELLYDT_RGBW2 = "SHRGBW2";
public static final String SHELLYDT_BUTTON1 = "SHBTN-1";
public static final String SHELLYDT_BUTTON2 = "SHBTN-2";
public static final String SHELLYDT_UNI = "SHUNI-1";
public static final String SHELLYDT_TRV = "SHTRV-01";
// Shelly Plus Series
public static final String SHELLYDT_PLUS1 = "SNSW-001X16EU";
public static final String SHELLYDT_PLUS1PM = "SNSW-001P16EU";
public static final String SHELLYDT_PLUS1UL = "SNSW-001X15UL";
public static final String SHELLYDT_PLUS1PMUL = "SNSW-001P15UL";
public static final String SHELLYDT_PLUS2PM_RELAY = "SNSW-002P16EU-relay";
public static final String SHELLYDT_PLUS2PM_ROLLER = "SNSW-002P16EU-roller";
public static final String SHELLYDT_PLUSPLUGUS = "SNPL-00116US";
public static final String SHELLYDT_PLUSI4 = "SNSN-0024X";
public static final String SHELLYDT_PLUSI4DC = "SNSN-0D24X";
public static final String SHELLYDT_PLUSHT = "SNSN-0013A";
// Shelly Pro Series
public static final String SHELLYDT_PRO1 = "SPSW-001XE16EU";
public static final String SHELLYDT_PRO1_2 = "SPSW-101XE16EU";
public static final String SHELLYDT_PRO1PM = "SPSW-001PE16EU";
public static final String SHELLYDT_PRO1PM_ = "SPSW-201PE16EU";
public static final String SHELLYDT_PRO1PM_2 = "SPSW-101PE16EU";
public static final String SHELLYDT_PRO2_RELAY = "SPSW-002XE16EU-relay";
public static final String SHELLYDT_PRO2_ROLLER = "SPSW-002XE16EU-roller";
public static final String SHELLYDT_PRO2_RELAY_2 = "SPSW-102XE16EU-relay";
public static final String SHELLYDT_PRO2_ROLLER_2 = "SPSW-102XE16EU-roller";
public static final String SHELLYDT_PRO2PM_RELAY = "SPSW-002PE16EU-relay";
public static final String SHELLYDT_PRO2PM_ROLLER = "SPSW-002PE16EU-roller";
public static final String SHELLYDT_PRO2PM_RELAY_2 = "SPSW-002PE16EU-relay";
public static final String SHELLYDT_PRO2PM_ROLLER_2 = "SPSW-002PE16EU-roller";
public static final String SHELLYDT_PRO3 = "SPSW-003XE16EU";
public static final String SHELLYDT_PRO4PM = "SPSW-004PE16EU";
public static final String SHELLYDT_PRO4PM_2 = "SPSW-104PE16EU";
// Thing names
public static final String THING_TYPE_SHELLY1_STR = "shelly1";
public static final String THING_TYPE_SHELLY1L_STR = "shelly1l";
public static final String THING_TYPE_SHELLY1PM_STR = "shelly1pm";
public static final String THING_TYPE_SHELLYEM_STR = "shellyem";
public static final String THING_TYPE_SHELLY3EM_STR = "shellyem3"; // bad: misspelled product name, it's 3EM
public static final String THING_TYPE_SHELLY2_PREFIX = "shellyswitch";
public static final String THING_TYPE_SHELLY2_RELAY_STR = "shelly2-relay";
public static final String THING_TYPE_SHELLY2_ROLLER_STR = "shelly2-roller";
public static final String THING_TYPE_SHELLY25_PREFIX = "shellyswitch25";
public static final String THING_TYPE_SHELLY25_RELAY_STR = "shelly25-relay";
public static final String THING_TYPE_SHELLY25_ROLLER_STR = "shelly25-roller";
public static final String THING_TYPE_SHELLY4PRO_STR = "shelly4pro";
public static final String THING_TYPE_SHELLYPLUG_STR = "shellyplug";
public static final String THING_TYPE_SHELLYPLUGS_STR = "shellyplugs";
public static final String THING_TYPE_SHELLYPLUGU1_STR = "shellyplugu1"; // Shely Plug US
public static final String THING_TYPE_SHELLYDIMMER_STR = "shellydimmer";
public static final String THING_TYPE_SHELLYDIMMER2_STR = "shellydimmer2";
public static final String THING_TYPE_SHELLYIX3_STR = "shellyix3";
public static final String THING_TYPE_SHELLYBULB_STR = "shellybulb";
public static final String THING_TYPE_SHELLYDUO_STR = "shellybulbduo";
public static final String THING_TYPE_SHELLYVINTAGE_STR = "shellyvintage";
public static final String THING_TYPE_SHELLYRGBW2_PREFIX = "shellyrgbw2";
public static final String THING_TYPE_SHELLYRGBW2_COLOR_STR = THING_TYPE_SHELLYRGBW2_PREFIX + "-color";
public static final String THING_TYPE_SHELLYRGBW2_WHITE_STR = THING_TYPE_SHELLYRGBW2_PREFIX + "-white";
public static final String THING_TYPE_SHELLYDUORGBW_STR = "shellycolorbulb";
public static final String THING_TYPE_SHELLYHT_STR = "shellyht";
public static final String THING_TYPE_SHELLYSMOKE_STR = "shellysmoke";
public static final String THING_TYPE_SHELLYGAS_STR = "shellygas";
public static final String THING_TYPE_SHELLYFLOOD_STR = "shellyflood";
public static final String THING_TYPE_SHELLYDOORWIN_STR = "shellydw";
public static final String THING_TYPE_SHELLYDOORWIN2_STR = "shellydw2";
public static final String THING_TYPE_SHELLYEYE_STR = "shellyseye";
public static final String THING_TYPE_SHELLYSENSE_STR = "shellysense";
public static final String THING_TYPE_SHELLYTRV_STR = "shellytrv";
public static final String THING_TYPE_SHELLYMOTION_STR = "shellymotion";
public static final String THING_TYPE_SHELLYMOTION2_STR = "shellymotion2";
public static final String THING_TYPE_SHELLYBUTTON1_STR = "shellybutton1";
public static final String THING_TYPE_SHELLYBUTTON2_STR = "shellybutton2";
public static final String THING_TYPE_SHELLYUNI_STR = "shellyuni";
// Shelly Plus Seriens
public static final String THING_TYPE_SHELLYPLUS1_STR = "shellyplus1";
public static final String THING_TYPE_SHELLYPLUS1PM_STR = "shellyplus1pm";
public static final String THING_TYPE_SHELLYPLUS2PM_RELAY_STR = "shellyplus2pm-relay";
public static final String THING_TYPE_SHELLYPLUS2PM_ROLLER_STR = "shellyplus2pm-roller";
public static final String THING_TYPE_SHELLYPLUSI4_STR = "shellyplusi4";
public static final String THING_TYPE_SHELLYPLUSI4DC_STR = "shellyplusi4dc";
public static final String THING_TYPE_SHELLYPLUSHT_STR = "shellyplusht";
public static final String THING_TYPE_SHELLYPLUSPLUGUS_STR = "shellyplusplugus";
// Shelly Pro Series
public static final String THING_TYPE_SHELLYPRO1_STR = "shellypro1";
public static final String THING_TYPE_SHELLYPRO1PM_STR = "shellypro1pm";
public static final String THING_TYPE_SHELLYPRO2_RELAY_STR = "shellypro2-relay";
public static final String THING_TYPE_SHELLYPRO2_ROLLER_STR = "shellypro2-roller";
public static final String THING_TYPE_SHELLYPRO2PM_RELAY_STR = "shellypro2pm-relay";
public static final String THING_TYPE_SHELLYPRO2PM_ROLLER_STR = "shellypro2pm-roller";
public static final String THING_TYPE_SHELLYPRO3_STR = "shellypro3";
public static final String THING_TYPE_SHELLYPRO4PM_STR = "shellypro4pm";
public static final String THING_TYPE_SHELLYPROTECTED_STR = "shellydevice";
public static final String THING_TYPE_SHELLYUNKNOWN_STR = "shellyunknown";
// List of all Thing Type UIDs
public static final ThingTypeUID THING_TYPE_SHELLY1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1_STR);
public static final ThingTypeUID THING_TYPE_SHELLY1L = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1L_STR);
public static final ThingTypeUID THING_TYPE_SHELLY1PM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY1PM_STR);
public static final ThingTypeUID THING_TYPE_SHELLYEM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYEM_STR);
public static final ThingTypeUID THING_TYPE_SHELLY3EM = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY3EM_STR);
public static final ThingTypeUID THING_TYPE_SHELLY2_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY2_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLY2_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY2_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLY25_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY25_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLY25_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLY25_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLY4PRO = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLY4PRO_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUG = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUG_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUGS = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUGS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUGU1 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUGU1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYUNI = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYUNI_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDIMMER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDIMMER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDIMMER2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDIMMER2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYIX3 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYIX3_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBULB = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYBULB_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDUO = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYDUO_STR);
public static final ThingTypeUID THING_TYPE_SHELLYVINTAGE = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYVINTAGE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDUORGBW = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDUORGBW_STR);
public static final ThingTypeUID THING_TYPE_SHELLYHT = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYHT_STR);
public static final ThingTypeUID THING_TYPE_SHELLYSENSE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYSENSE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYSMOKE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYSMOKE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYGAS = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYGAS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYFLOOD = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYFLOOD_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDOORWIN = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDOORWIN_STR);
public static final ThingTypeUID THING_TYPE_SHELLYDOORWIN2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYDOORWIN2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYTRV = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYTRV_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBUTTON1 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYBUTTON1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYBUTTON2 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYBUTTON2_STR);
public static final ThingTypeUID THING_TYPE_SHELLYEYE = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYEYE_STR);
public static final ThingTypeUID THING_TYPE_SHELLMOTION = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYMOTION_STR);
public static final ThingTypeUID THING_TYPE_SHELLYRGBW2_COLOR = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYRGBW2_COLOR_STR);
public static final ThingTypeUID THING_TYPE_SHELLYRGBW2_WHITE = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYRGBW2_WHITE_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPROTECTED = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPROTECTED_STR);
public static final ThingTypeUID THING_TYPE_SHELLYUNKNOWN = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYUNKNOWN_STR);
// Shelly Plus/Pro
public static final ThingTypeUID THING_TYPE_SHELLYPLUS1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPLUS1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUS1PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUS1PM_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUS2PM_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUS2PM_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUS2PM_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSI4 = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSI4_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSI4DC = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSI4DC_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSHT = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSHT_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPLUSPLUGUS = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPLUSPLUGUS_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO1 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO1_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO1PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO1PM_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO2_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO2_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO2_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO2_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO2PM_RELAY = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO2PM_RELAY_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO2PM_ROLLER = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO3 = new ThingTypeUID(BINDING_ID, THING_TYPE_SHELLYPRO3_STR);
public static final ThingTypeUID THING_TYPE_SHELLYPRO4PM = new ThingTypeUID(BINDING_ID,
THING_TYPE_SHELLYPRO4PM_STR);
private static final Map<String, String> THING_TYPE_MAPPING = new LinkedHashMap<>();
static {
// mapping by device type id
@ -57,6 +270,35 @@ public class ShellyThingCreator {
THING_TYPE_MAPPING.put(SHELLYDT_TRV, THING_TYPE_SHELLYTRV_STR);
THING_TYPE_MAPPING.put(SHELLYDT_MOTION, THING_TYPE_SHELLYMOTION_STR);
// Plus Series
THING_TYPE_MAPPING.put(SHELLYDT_PLUS1, THING_TYPE_SHELLYPLUS1_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS1PM, THING_TYPE_SHELLYPLUS1PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS1UL, THING_TYPE_SHELLYPLUS1_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS1PMUL, THING_TYPE_SHELLYPLUS1PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS2PM_RELAY, THING_TYPE_SHELLYPLUS2PM_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUS2PM_ROLLER, THING_TYPE_SHELLYPLUS2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSPLUGUS, THING_TYPE_SHELLYPLUSPLUGUS_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSI4DC, THING_TYPE_SHELLYPLUSI4DC_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSI4, THING_TYPE_SHELLYPLUSI4_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PLUSHT, THING_TYPE_SHELLYPLUSHT_STR);
// Pro Series
THING_TYPE_MAPPING.put(SHELLYDT_PRO1, THING_TYPE_SHELLYPRO1_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO1_2, THING_TYPE_SHELLYPRO1_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO1PM, THING_TYPE_SHELLYPRO1PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO1PM_2, THING_TYPE_SHELLYPRO1PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2_RELAY, THING_TYPE_SHELLYPRO2_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2_RELAY_2, THING_TYPE_SHELLYPRO2_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2_ROLLER, THING_TYPE_SHELLYPRO2_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2_ROLLER_2, THING_TYPE_SHELLYPRO2_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_RELAY, THING_TYPE_SHELLYPRO2PM_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_RELAY_2, THING_TYPE_SHELLYPRO2PM_RELAY_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_ROLLER, THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO2PM_ROLLER_2, THING_TYPE_SHELLYPRO2PM_ROLLER_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO3, THING_TYPE_SHELLYPRO3_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO4PM, THING_TYPE_SHELLYPRO4PM_STR);
THING_TYPE_MAPPING.put(SHELLYDT_PRO4PM_2, THING_TYPE_SHELLYPRO4PM_STR);
// mapping by thing type
THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1_STR, THING_TYPE_SHELLY1_STR);
THING_TYPE_MAPPING.put(THING_TYPE_SHELLY1PM_STR, THING_TYPE_SHELLY1PM_STR);

View File

@ -13,7 +13,8 @@
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import static org.openhab.binding.shelly.internal.handler.ShellyComponents.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import static org.openhab.core.thing.Thing.*;
@ -31,17 +32,17 @@ import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyInputState;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpApi;
import org.openhab.binding.shelly.internal.coap.ShellyCoapHandler;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO;
import org.openhab.binding.shelly.internal.coap.ShellyCoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputState;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDevice;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapHandler;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.discovery.ShellyThingCreator;
@ -84,11 +85,13 @@ public class ShellyBaseHandler extends BaseThingHandler
public String thingType = "";
protected final ShellyApiInterface api;
private final HttpClient httpClient;
protected ShellyBindingConfiguration bindingConfig;
protected ShellyThingConfiguration config = new ShellyThingConfiguration();
protected ShellyDeviceProfile profile = new ShellyDeviceProfile(); // init empty profile to avoid NPE
protected ShellyDeviceStats stats = new ShellyDeviceStats();
private final ShellyCoapHandler coap;
private final Shelly1CoapHandler coap;
public boolean autoCoIoT = false;
public final ShellyTranslationProvider messages;
@ -124,7 +127,7 @@ public class ShellyBaseHandler extends BaseThingHandler
* @param httpPort from httpService
*/
public ShellyBaseHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
final ShellyBindingConfiguration bindingConfig, final ShellyCoapServer coapServer, final String localIP,
final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
int httpPort, final HttpClient httpClient) {
super(thing);
@ -135,11 +138,12 @@ public class ShellyBaseHandler extends BaseThingHandler
this.bindingConfig = bindingConfig;
this.config = getConfigAs(ShellyThingConfiguration.class);
this.httpClient = httpClient;
this.localIP = localIP;
this.localPort = String.valueOf(httpPort);
this.api = new ShellyHttpApi(thingName, config, httpClient);
this.api = new Shelly1HttpApi(thingName, config, httpClient);
coap = new ShellyCoapHandler(this, coapServer);
coap = new Shelly1CoapHandler(this, coapServer);
}
@Override
@ -196,6 +200,11 @@ public class ShellyBaseHandler extends BaseThingHandler
return config;
}
@Override
public HttpClient getHttpClient() {
return httpClient;
}
/**
* This routine is called every time the Thing configuration has been changed
*/
@ -274,7 +283,7 @@ public class ShellyBaseHandler extends BaseThingHandler
if (config.eventsCoIoT && (tmpPrf.settings.coiot != null) && (tmpPrf.settings.coiot.enabled != null)) {
String devpeer = getString(tmpPrf.settings.coiot.peer);
String ourpeer = config.localIp + ":" + ShellyCoapJSonDTO.COIOT_PORT;
String ourpeer = config.localIp + ":" + Shelly1CoapJSonDTO.COIOT_PORT;
if (!tmpPrf.settings.coiot.enabled || (profile.isMotion && devpeer.isEmpty())) {
try {
api.setCoIoTPeer(ourpeer);
@ -749,7 +758,7 @@ public class ShellyBaseHandler extends BaseThingHandler
if (isButton) {
triggerButton(group, idx, mapButtonEvent(event));
channel = CHANNEL_BUTTON_TRIGGER + profile.getInputSuffix(idx);
payload = ShellyApiJsonDTO.mapButtonEvent(event);
payload = Shelly1ApiJsonDTO.mapButtonEvent(event);
} else {
logger.debug("{}: Relay button is not in memontary or detached mode, ignore SHORT/LONGPUSH",
thingName);

View File

@ -12,7 +12,7 @@
*/
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import java.math.BigDecimal;

View File

@ -13,19 +13,19 @@
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsMeter;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor.ShellyADC;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyThermnostat;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor.ShellyADC;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyThermnostat;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.OpenClosedType;

View File

@ -13,7 +13,7 @@
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.Map;
@ -22,13 +22,13 @@ import java.util.TreeMap;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLightChannel;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.coap.ShellyCoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusLightChannel;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
@ -66,7 +66,7 @@ public class ShellyLightHandler extends ShellyBaseHandler {
* @param httpPort port of the openHAB HTTP API
*/
public ShellyLightHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
final ShellyBindingConfiguration bindingConfig, final ShellyCoapServer coapServer, final String localIP,
final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
int httpPort, final HttpClient httpClient) {
super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
channelColors = new TreeMap<>();

View File

@ -14,7 +14,7 @@ package org.openhab.binding.shelly.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.coap.ShellyCoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
import org.openhab.core.thing.Thing;
@ -36,7 +36,7 @@ public class ShellyProtectedHandler extends ShellyBaseHandler {
* @param httpPort port of the openHAB HTTP API
*/
public ShellyProtectedHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
final ShellyBindingConfiguration bindingConfig, final ShellyCoapServer coapServer, final String localIP,
final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
int httpPort, final HttpClient httpClient) {
super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
}

View File

@ -13,22 +13,22 @@
package org.openhab.binding.shelly.internal.handler;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRoller;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortStatusRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.coap.ShellyCoapServer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRoller;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapServer;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.provider.ShellyChannelDefinitions;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
@ -69,7 +69,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
* @param httpPort port of the openHAB HTTP API
*/
public ShellyRelayHandler(final Thing thing, final ShellyTranslationProvider translationProvider,
final ShellyBindingConfiguration bindingConfig, final ShellyCoapServer coapServer, final String localIP,
final ShellyBindingConfiguration bindingConfig, final Shelly1CoapServer coapServer, final String localIP,
int httpPort, final HttpClient httpClient) {
super(thing, translationProvider, bindingConfig, coapServer, localIP, httpPort, httpClient);
}
@ -222,7 +222,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
int position = -1;
if ((command instanceof UpDownType) || (command instanceof OnOffType)) {
ShellyControlRoller rstatus = api.getRollerStatus(index);
ShellyRollerStatus rstatus = api.getRollerStatus(index);
if (!getString(rstatus.state).isEmpty() && !getString(rstatus.state).equals(SHELLY_ALWD_ROLLER_TURN_STOP)) {
if ((command == UpDownType.UP && getString(rstatus.state).equals(SHELLY_ALWD_ROLLER_TURN_OPEN))
@ -317,7 +317,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
}
}
private void createRollerChannels(ShellyControlRoller roller) {
private void createRollerChannels(ShellyRollerStatus roller) {
if (!areChannelsCreated()) {
updateChannelDefinitions(ShellyChannelDefinitions.createRollerChannels(getThing(), roller));
}
@ -406,7 +406,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
for (ShellySettingsRoller roller : status.rollers) {
if (roller.isValid) {
ShellyControlRoller control = api.getRollerStatus(i);
ShellyRollerStatus control = api.getRollerStatus(i);
Integer relayIndex = i + 1;
String groupName = profile.numRollers > 1 ? CHANNEL_GROUP_ROL_CONTROL + relayIndex.toString()
: CHANNEL_GROUP_ROL_CONTROL;
@ -456,7 +456,7 @@ public class ShellyRelayHandler extends ShellyBaseHandler {
// the same structure as lights[] from Bulb,RGBW2 and Duo. The tag gets replaced by dimmers[] so that Gson
// maps to a different structure (ShellyShortLight).
Gson gson = new Gson();
ShellySettingsStatus dstatus = fromJson(gson, ShellyApiJsonDTO.fixDimmerJson(orgStatus.json),
ShellySettingsStatus dstatus = fromJson(gson, Shelly1ApiJsonDTO.fixDimmerJson(orgStatus.json),
ShellySettingsStatus.class);
logger.trace("{}: Updating {} dimmers(s)", thingName, dstatus.dimmers.size());

View File

@ -17,10 +17,11 @@ import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.Thing;
@ -81,6 +82,8 @@ public interface ShellyThingInterface {
public ShellyThingConfiguration getThingConfig();
public HttpClient getHttpClient();
public String getProperty(String key);
public void updateProperties(String key, String value);

View File

@ -13,7 +13,7 @@
package org.openhab.binding.shelly.internal.manager;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.PROPERTY_SERVICE_NAME;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.SHELLY_COIOT_MCAST;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.SHELLY_COIOT_MCAST;
import static org.openhab.binding.shelly.internal.manager.ShellyManagerConstants.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
@ -27,11 +27,11 @@ import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.shelly.internal.ShellyHandlerFactory;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiInterface;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpApi;
import org.openhab.binding.shelly.internal.coap.ShellyCoapJSonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyOtaCheckResult;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsLogin;
import org.openhab.binding.shelly.internal.api1.Shelly1CoapJSonDTO;
import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyManagerInterface;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
@ -83,7 +83,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
ShellyThingConfiguration config = getThingConfig(th, properties);
ShellyDeviceProfile profile = th.getProfile();
ShellyApiInterface api = th.getApi();
new ShellyHttpApi(uid, config, httpClient);
new Shelly1HttpApi(uid, config, httpClient);
int refreshTimer = 0;
switch (action) {
@ -139,7 +139,7 @@ public class ShellyManagerActionPage extends ShellyManagerPage {
String peer = getString(profile.settings.coiot.peer);
boolean mcast = peer.isEmpty() || SHELLY_COIOT_MCAST.equalsIgnoreCase(peer);
String newPeer = mcast ? localIp + ":" + ShellyCoapJSonDTO.COIOT_PORT : SHELLY_COIOT_MCAST;
String newPeer = mcast ? localIp + ":" + Shelly1CoapJSonDTO.COIOT_PORT : SHELLY_COIOT_MCAST;
String displayPeer = mcast ? newPeer : "Multicast";
if (profile.isMotion && action.equalsIgnoreCase(ACTION_SETCOIOT_MCAST)) {

View File

@ -33,9 +33,9 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus;
import org.openhab.binding.shelly.internal.ShellyHandlerFactory;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsUpdate;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpApi;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsUpdate;
import org.openhab.binding.shelly.internal.api1.Shelly1HttpApi;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyManagerInterface;
import org.openhab.binding.shelly.internal.provider.ShellyTranslationProvider;
@ -122,7 +122,7 @@ public class ShellyManagerOtaPage extends ShellyManagerPage {
new Thread(() -> { // schedule asynchronous reboot
try {
ShellyHttpApi api = new ShellyHttpApi(uid, config, httpClient);
Shelly1HttpApi api = new Shelly1HttpApi(uid, config, httpClient);
ShellySettingsUpdate result = api.firmwareUpdate(updateUrl);
String status = getString(result.status);
logger.info("{}: {}", th.getThingName(), getMessage("fwupdate.initiated", status));

View File

@ -13,6 +13,7 @@
package org.openhab.binding.shelly.internal.manager;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.discovery.ShellyThingCreator.*;
import static org.openhab.binding.shelly.internal.manager.ShellyManagerConstants.*;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import static org.openhab.core.thing.Thing.*;
@ -44,7 +45,7 @@ import org.openhab.binding.shelly.internal.ShellyHandlerFactory;
import org.openhab.binding.shelly.internal.api.ShellyApiException;
import org.openhab.binding.shelly.internal.api.ShellyApiResult;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api.ShellyHttpApi;
import org.openhab.binding.shelly.internal.api.ShellyHttpClient;
import org.openhab.binding.shelly.internal.config.ShellyBindingConfiguration;
import org.openhab.binding.shelly.internal.config.ShellyThingConfiguration;
import org.openhab.binding.shelly.internal.handler.ShellyDeviceStats;
@ -491,7 +492,7 @@ public class ShellyManagerPage {
try {
Request request = httpClient.newRequest(url).method(method).timeout(SHELLY_API_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
request.header(HttpHeader.ACCEPT, ShellyHttpApi.CONTENT_TYPE_JSON);
request.header(HttpHeader.ACCEPT, ShellyHttpClient.CONTENT_TYPE_JSON);
logger.trace("{}: HTTP {} {}", LOG_PREFIX, method, url);
ContentResponse contentResponse = request.send();
apiResult = new ShellyApiResult(contentResponse);

View File

@ -72,14 +72,14 @@ public class ShellyManagerServlet extends HttpServlet {
className = substringAfterLast(getClass().toString(), ".");
this.httpService = httpService;
String localIp = getString(networkAddressService.getPrimaryIpv4HostAddress());
int localPort = HttpServiceUtil.getHttpServicePort(componentContext.getBundleContext());
Integer localPort = HttpServiceUtil.getHttpServicePort(componentContext.getBundleContext());
this.manager = new ShellyManager(configurationAdmin, translationProvider,
httpClientFactory.getCommonHttpClient(), localIp, localPort, handlerFactory);
try {
httpService.registerServlet(SERVLET_URI, this, null, httpService.createDefaultHttpContext());
// Promote Shelly Manager usage
logger.info("{}", translationProvider.get("status.managerstarted", localIp, localPort + ""));
logger.info("{}", translationProvider.get("status.managerstarted", localIp, localPort.toString()));
} catch (NamespaceException | ServletException | IllegalArgumentException e) {
logger.warn("{}: Unable to initialize bindingConfig", className, e);
}

View File

@ -13,7 +13,7 @@
package org.openhab.binding.shelly.internal.provider;
import static org.openhab.binding.shelly.internal.ShellyBindingConstants.*;
import static org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.SHELLY_API_INVTEMP;
import static org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.SHELLY_API_INVTEMP;
import static org.openhab.binding.shelly.internal.util.ShellyUtils.*;
import java.util.HashMap;
@ -27,21 +27,21 @@ import javax.measure.Unit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyControlRoller;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyInputState;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsGlobal;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsMeter;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyShortStatusRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusLightChannel;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api.ShellyApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.api.ShellyDeviceProfile;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyInputState;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyRollerStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsDimmer;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsEMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsGlobal;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsMeter;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsRgbwLight;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellySettingsStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortLightStatus;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyShortStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusLightChannel;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusRelay;
import org.openhab.binding.shelly.internal.api1.Shelly1ApiJsonDTO.ShellyStatusSensor;
import org.openhab.binding.shelly.internal.handler.ShellyThingInterface;
import org.openhab.core.thing.Channel;
import org.openhab.core.thing.ChannelUID;
@ -262,7 +262,7 @@ public class ShellyChannelDefinitions {
addChannel(thing, add, profile.settings.name != null, CHGR_DEVST, CHANNEL_DEVST_NAME);
if (!profile.isSensor && !profile.isIX3 && getDouble(status.temperature) != SHELLY_API_INVTEMP) {
if (!profile.isSensor && !profile.isIX && getDouble(status.temperature) != SHELLY_API_INVTEMP) {
// Only some devices report the internal device temp
addChannel(thing, add, status.tmp != null || status.temperature != null, CHGR_DEVST, CHANNEL_DEVST_ITEMP);
}
@ -298,15 +298,18 @@ public class ShellyChannelDefinitions {
Map<String, Channel> add = new LinkedHashMap<>();
String group = profile.getControlGroup(idx);
ShellySettingsRelay rs = profile.settings.relays.get(idx);
ShellyShortStatusRelay rstatus = relay.relays.get(idx);
boolean timer = rs.hasTimer != null || (rstatus != null && rstatus.hasTimer != null); // Dimmer 1/2 have
// has_timer under /status
addChannel(thing, add, rs.ison != null, group, CHANNEL_OUTPUT);
addChannel(thing, add, rs.name != null, group, CHANNEL_OUTPUT_NAME);
addChannel(thing, add, rs.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, rs.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
addChannel(thing, add, timer, group, CHANNEL_TIMER_ACTIVE);
if (profile.settings.relays != null) {
ShellySettingsRelay rs = profile.settings.relays.get(idx);
ShellyShortStatusRelay rstatus = relay.relays.get(idx);
boolean timer = rs.hasTimer != null || (rstatus != null && rstatus.hasTimer != null); // Dimmer 1/2 have
// has_timer under
// /status
addChannel(thing, add, rs.ison != null, group, CHANNEL_OUTPUT);
addChannel(thing, add, rs.name != null, group, CHANNEL_OUTPUT_NAME);
addChannel(thing, add, rs.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, rs.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
addChannel(thing, add, timer, group, CHANNEL_TIMER_ACTIVE);
}
// Shelly 1/1PM Addon
if (relay.extTemperature != null) {
@ -329,12 +332,14 @@ public class ShellyChannelDefinitions {
// Shelly Dimmer has an additional brightness channel
addChannel(thing, add, profile.isDimmer, group, CHANNEL_BRIGHTNESS);
ShellySettingsDimmer ds = profile.settings.dimmers.get(idx);
addChannel(thing, add, ds.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
if (profile.settings.dimmers != null) {
ShellySettingsDimmer ds = profile.settings.dimmers.get(idx);
addChannel(thing, add, ds.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, ds.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
ShellyShortLightStatus dss = dstatus.dimmers.get(idx);
addChannel(thing, add, dss != null && dss.hasTimer != null, group, CHANNEL_TIMER_ACTIVE);
ShellyShortLightStatus dss = dstatus.dimmers.get(idx);
addChannel(thing, add, dss != null && dss.hasTimer != null, group, CHANNEL_TIMER_ACTIVE);
}
return add;
}
@ -343,13 +348,16 @@ public class ShellyChannelDefinitions {
Map<String, Channel> add = new LinkedHashMap<>();
String group = profile.getControlGroup(idx);
ShellySettingsRgbwLight light = profile.settings.lights.get(idx);
// The is no brightness channel in color mode, so we need a power channel
addChannel(thing, add, profile.inColor, group, CHANNEL_LIGHT_POWER);
addChannel(thing, add, light.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, light.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
addChannel(thing, add, status.hasTimer != null, group, CHANNEL_TIMER_ACTIVE);
if (profile.settings.lights != null) {
ShellySettingsRgbwLight light = profile.settings.lights.get(idx);
// Create power channel in color mode and brightness channel in white mode
addChannel(thing, add, profile.inColor, group, CHANNEL_LIGHT_POWER);
addChannel(thing, add, !profile.inColor, group, CHANNEL_BRIGHTNESS);
addChannel(thing, add, light.temp != null, CHANNEL_GROUP_WHITE_CONTROL, CHANNEL_COLOR_TEMP);
addChannel(thing, add, light.autoOn != null, group, CHANNEL_TIMER_AUTOON);
addChannel(thing, add, light.autoOff != null, group, CHANNEL_TIMER_AUTOOFF);
addChannel(thing, add, status.hasTimer != null, group, CHANNEL_TIMER_ACTIVE);
}
return add;
}
@ -379,7 +387,7 @@ public class ShellyChannelDefinitions {
return add;
}
public static Map<String, Channel> createRollerChannels(Thing thing, final ShellyControlRoller roller) {
public static Map<String, Channel> createRollerChannels(Thing thing, final ShellyRollerStatus roller) {
Map<String, Channel> add = new LinkedHashMap<>();
addChannel(thing, add, true, CHGR_ROLLER, CHANNEL_ROL_CONTROL_CONTROL);
addChannel(thing, add, true, CHGR_ROLLER, CHANNEL_ROL_CONTROL_STATE);

View File

@ -19,6 +19,8 @@ import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.DateTimeException;
import java.time.Instant;
import java.time.LocalDateTime;
@ -351,4 +353,26 @@ public class ShellyUtils {
public static char lastChar(String s) {
return s.length() > 1 ? s.charAt(s.length() - 1) : '*';
}
public static String sha256(String string) throws ShellyApiException {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
final byte[] hashbytes = digest.digest(string.getBytes(StandardCharsets.UTF_8));
return bytesToHex(hashbytes);
} catch (NoSuchAlgorithmException e) {
throw new ShellyApiException("SHA256 can't be initialzed", e);
}
}
public static String bytesToHex(byte[] bytes) {
StringBuilder hexString = new StringBuilder(2 * bytes.length);
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xff & bytes[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}

View File

@ -17,6 +17,7 @@
<default>admin</default>
<label>@text/binding.shelly.config.defaultPassword.label</label>
<description>@text/binding.shelly.config.defaultPassword.description</description>
<context>password</context>
</parameter>
<parameter name="localIP" type="text">
<label>@text/binding.shelly.config.localIP.label</label>

View File

@ -86,6 +86,23 @@ thing-type.shelly.shellygas.description = Shelly Gas (Gas Sensor - Gas Leak Dete
thing-type.shelly.shellytrv.description = Shelly TRV (Radiator value, battery powered)
thing-type.shelly.shellyix3.description = Shelly ix3 (Activation Device with 3 inputs)
# Plus/Pro devices
thing-type.shelly.shellyplus1.description = Shelly Plus 1 (Single Relay Switch)
thing-type.shelly.shellyplus1pm.description = Shelly Plus 1PM - Single Relay Switch with Power Meter
thing-type.shelly.shellyplus2-relay.description = Shelly Plus 2PM - Dual Relay Switch with Power Meter
thing-type.shelly.shellyplus2pm-roller.description = Shelly Plus 2PM - Roller Control with Power Meter
thing-type.shelly.shellyplusht.description = Shelly Plus HT - Humidity and Temperature sensor with display
thing-type.shelly.shellyplusi4.description = Shelly Plus i4 - 4xInput Device
thing-type.shelly.shellyplusi4dc.description = Shelly Plus i4DC - 4xDC Input Device
thing-type.shelly.shellypro1.description = Shelly Pro 1 - Single Relay Switch
thing-type.shelly.shellypro1pm.description = Shelly Pro 1PM - Single Relay Switch with Power Meter
thing-type.shelly.shellypro2-relay.description = Shelly Pro 2 - Dual Relay Switch
thing-type.shelly.shellypro2-roller.description = Shelly Pro 2 - Roller Control
thing-type.shelly.shellypro2pm-relay.description= Shelly Pro 2PM - Dual Relay Switch with Power Meter
thing-type.shelly.shellypro2pm-roller.description = Shelly Pro 2PM - Roller Control with Power Meter
thing-type.shelly.shellypro3.description = Shelly Pro 3 - 3xRelay Switch
thing-type.shelly.shellypro4pm.description = Shelly Pro 4PM - 4xRelay Switch with Power Meter
# thing config - shellydevice
thing-type.config.shelly.deviceIp.label = IP Address
thing-type.config.shelly.deviceIp.description = IP Address of the Shelly device
@ -247,7 +264,7 @@ channel-type.shelly.meterAccuReturned.description = Accumulated Returned Power i
channel-type.shelly.meterReactive.label = Reactive Energy
channel-type.shelly.meterReactive.description = Instantaneous reactive power in Watts (W)
channel-type.shelly.lastPower1.label = Last Power
channel-type.shelly.lastPower1.description = Rounded power consumption during last minute
channel-type.shelly.lastPower1.description = Last power consumption #1 - one rounded minute
channel-type.shelly.meterTotal.label = Total Energy Consumption
channel-type.shelly.meterTotal.description = Total energy consumption in kW/h since the device powered up (resets on restart)
channel-type.shelly.meterReturned.label = Total Returned Energy