[myq] Fixes breaking API changes to the MyQ binding (#11601)

Signed-off-by: Dan Cunningham <dan@digitaldan.com>
This commit is contained in:
Dan Cunningham 2021-11-19 15:17:27 -08:00 committed by GitHub
parent 163a34fca4
commit d0837ae8a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 113 additions and 247 deletions

View File

@ -14,11 +14,12 @@ package org.openhab.binding.myq.internal;
import static org.openhab.binding.myq.internal.MyQBindingConstants.BINDING_ID; import static org.openhab.binding.myq.internal.MyQBindingConstants.BINDING_ID;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.myq.internal.dto.DevicesDTO; import org.openhab.binding.myq.internal.dto.DeviceDTO;
import org.openhab.binding.myq.internal.handler.MyQAccountHandler; import org.openhab.binding.myq.internal.handler.MyQAccountHandler;
import org.openhab.core.config.discovery.AbstractDiscoveryService; import org.openhab.core.config.discovery.AbstractDiscoveryService;
import org.openhab.core.config.discovery.DiscoveryResult; import org.openhab.core.config.discovery.DiscoveryResult;
@ -55,9 +56,9 @@ public class MyQDiscoveryService extends AbstractDiscoveryService implements Dis
public void startScan() { public void startScan() {
MyQAccountHandler accountHandler = this.accountHandler; MyQAccountHandler accountHandler = this.accountHandler;
if (accountHandler != null) { if (accountHandler != null) {
DevicesDTO devices = accountHandler.devicesCache(); List<DeviceDTO> devices = accountHandler.devicesCache();
if (devices != null) { if (devices != null) {
devices.items.forEach(device -> { devices.forEach(device -> {
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily); ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily);
if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) { if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) {
ThingUID thingUID = new ThingUID(thingTypeUID, accountHandler.getThing().getUID(), ThingUID thingUID = new ThingUID(thingTypeUID, accountHandler.getThing().getUID(),
@ -73,6 +74,11 @@ public class MyQDiscoveryService extends AbstractDiscoveryService implements Dis
} }
} }
@Override
public void startBackgroundDiscovery() {
startScan();
}
@Override @Override
public void setThingHandler(ThingHandler handler) { public void setThingHandler(ThingHandler handler) {
if (handler instanceof MyQAccountHandler) { if (handler instanceof MyQAccountHandler) {

View File

@ -18,21 +18,7 @@ package org.openhab.binding.myq.internal.dto;
* @author Dan Cunningham - Initial contribution * @author Dan Cunningham - Initial contribution
*/ */
public class AccountDTO { public class AccountDTO {
public String id;
public UsersDTO users; public String name;
public Boolean admin; public String createdBy;
public AccountInfoDTO account;
public String analyticsId;
public String userId;
public String userName;
public String email;
public String firstName;
public String lastName;
public String cultureCode;
public AddressDTO address;
public TimeZoneDTO timeZone;
public Boolean mailingListOptIn;
public Boolean requestAccountLinkInfo;
public String phone;
public Boolean diagnosticDataOptIn;
} }

View File

@ -12,13 +12,13 @@
*/ */
package org.openhab.binding.myq.internal.dto; package org.openhab.binding.myq.internal.dto;
import java.util.List;
/** /**
* The {@link AccountInfoDTO} entity from the MyQ API * The {@link AccountsDTO} entity from the MyQ API
* *
* @author Dan Cunningham - Initial contribution * @author Dan Cunningham - Initial contribution
*/ */
public class AccountInfoDTO { public class AccountsDTO {
public List<AccountDTO> accounts;
public String href;
public String id;
} }

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.dto;
/**
* The {@link ActionDTO} entity from the MyQ API
*
* @author Dan Cunningham - Initial contribution
*/
public class ActionDTO {
public ActionDTO(String actionType) {
super();
this.actionType = actionType;
}
public String actionType;
}

View File

@ -1,26 +0,0 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.dto;
/**
* The {@link AddressDTO} entity from the MyQ API
*
* @author Dan Cunningham - Initial contribution
*/
public class AddressDTO {
public String addressLine1;
public String city;
public String postalCode;
public CountryDTO country;
}

View File

@ -1,25 +0,0 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.dto;
/**
* The {@link CountryDTO} entity from the MyQ API
*
* @author Dan Cunningham - Initial contribution
*/
public class CountryDTO {
public String code;
public Boolean isEEACountry;
public String href;
}

View File

@ -25,6 +25,7 @@ public class DeviceDTO {
public String deviceType; public String deviceType;
public String name; public String name;
public String createdDate; public String createdDate;
public String accountId;
public DeviceStateDTO state; public DeviceStateDTO state;
public String parentDevice; public String parentDevice;
public String parentDeviceId; public String parentDeviceId;

View File

@ -12,8 +12,6 @@
*/ */
package org.openhab.binding.myq.internal.dto; package org.openhab.binding.myq.internal.dto;
import java.util.List;
/** /**
* The {@link DeviceStateDTO} entity from the MyQ API * The {@link DeviceStateDTO} entity from the MyQ API
* *
@ -23,34 +21,16 @@ public class DeviceStateDTO {
public Boolean gdoLockConnected; public Boolean gdoLockConnected;
public Boolean attachedWorkLightErrorPresent; public Boolean attachedWorkLightErrorPresent;
public String doorState; public String learnStatus;
public Boolean hasCamera;
public String lampState; public String lampState;
public String open; public String batteryBackupState;
public String close; public String doorState;
public String lastUpdate; public String lastUpdate;
public String passthroughInterval;
public String doorAjarInterval;
public String invalidCredentialWindow;
public String invalidShutoutPeriod;
public Boolean isUnattendedOpenAllowed; public Boolean isUnattendedOpenAllowed;
public Boolean isUnattendedCloseAllowed; public Boolean isUnattendedCloseAllowed;
public String auxRelayDelay; public Integer serviceCycleCount;
public Boolean useAuxRelay; public Integer absoluteCycleCount;
public String auxRelayBehavior;
public Boolean rexFiresDoor;
public Boolean commandChannelReportStatus;
public Boolean controlFromBrowser;
public Boolean reportForced;
public Boolean reportAjar;
public Integer maxInvalidAttempts;
public Boolean online; public Boolean online;
public String lastStatus; public String lastStatus;
public String firmwareVersion;
public Boolean homekitCapable;
public Boolean homekitEnabled;
public String learn;
public Boolean learnMode;
public String updatedDate;
public List<String> physicalDevices = null;
public Boolean pendingBootloadAbandoned;
} }

View File

@ -1,24 +0,0 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.dto;
/**
* The {@link TimeZoneDTO} entity from the MyQ API
*
* @author Dan Cunningham - Initial contribution
*/
public class TimeZoneDTO {
public String id;
public String name;
}

View File

@ -1,23 +0,0 @@
/**
* Copyright (c) 2010-2021 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.myq.internal.dto;
/**
* The {@link UsersDTO} entity from the MyQ API
*
* @author Dan Cunningham - Initial contribution
*/
public class UsersDTO {
public String href;
}

View File

@ -23,10 +23,12 @@ import java.net.URISyntaxException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Base64; import java.util.Base64;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -47,7 +49,6 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.client.util.FormContentProvider; import org.eclipse.jetty.client.util.FormContentProvider;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.Fields; import org.eclipse.jetty.util.Fields;
@ -57,7 +58,8 @@ import org.jsoup.nodes.Element;
import org.openhab.binding.myq.internal.MyQDiscoveryService; import org.openhab.binding.myq.internal.MyQDiscoveryService;
import org.openhab.binding.myq.internal.config.MyQAccountConfiguration; import org.openhab.binding.myq.internal.config.MyQAccountConfiguration;
import org.openhab.binding.myq.internal.dto.AccountDTO; import org.openhab.binding.myq.internal.dto.AccountDTO;
import org.openhab.binding.myq.internal.dto.ActionDTO; import org.openhab.binding.myq.internal.dto.AccountsDTO;
import org.openhab.binding.myq.internal.dto.DeviceDTO;
import org.openhab.binding.myq.internal.dto.DevicesDTO; import org.openhab.binding.myq.internal.dto.DevicesDTO;
import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener; import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
import org.openhab.core.auth.client.oauth2.AccessTokenResponse; import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
@ -106,20 +108,23 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
// this should never happen, but lets be safe and give up after so many redirects // this should never happen, but lets be safe and give up after so many redirects
private static final int LOGIN_MAX_REDIRECTS = 30; private static final int LOGIN_MAX_REDIRECTS = 30;
/* /*
* MyQ device and account API endpoint * MyQ device and account API endpoints
*/ */
private static final String BASE_URL = "https://api.myqdevice.com/api"; private static final String ACCOUNTS_URL = "https://accounts.myq-cloud.com/api/v6.0/accounts";
private static final String DEVICES_URL = "https://devices.myq-cloud.com/api/v5.2/Accounts/%s/Devices";
private static final String CMD_LAMP_URL = "https://account-devices-lamp.myq-cloud.com/api/v5.2/Accounts/%s/lamps/%s/%s";
private static final String CMD_DOOR_URL = "https://account-devices-gdo.myq-cloud.com/api/v5.2/Accounts/%s/door_openers/%s/%s";
private static final Integer RAPID_REFRESH_SECONDS = 5; private static final Integer RAPID_REFRESH_SECONDS = 5;
private final Logger logger = LoggerFactory.getLogger(MyQAccountHandler.class); private final Logger logger = LoggerFactory.getLogger(MyQAccountHandler.class);
private final Gson gsonUpperCase = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
private final Gson gsonLowerCase = new GsonBuilder() private final Gson gsonLowerCase = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
private final OAuthFactory oAuthFactory; private final OAuthFactory oAuthFactory;
private @Nullable Future<?> normalPollFuture; private @Nullable Future<?> normalPollFuture;
private @Nullable Future<?> rapidPollFuture; private @Nullable Future<?> rapidPollFuture;
private @Nullable AccountDTO account; private @Nullable AccountsDTO accounts;
private @Nullable DevicesDTO devicesCache;
private List<DeviceDTO> devicesCache = new ArrayList<DeviceDTO>();
private @Nullable OAuthClientService oAuthService; private @Nullable OAuthClientService oAuthService;
private Integer normalRefreshSeconds = 60; private Integer normalRefreshSeconds = 60;
private HttpClient httpClient; private HttpClient httpClient;
@ -155,6 +160,7 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
@Override @Override
public void dispose() { public void dispose() {
stopPolls(); stopPolls();
OAuthClientService oAuthService = this.oAuthService;
if (oAuthService != null) { if (oAuthService != null) {
oAuthService.close(); oAuthService.close();
} }
@ -167,10 +173,10 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
@Override @Override
public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) { public void childHandlerInitialized(ThingHandler childHandler, Thing childThing) {
DevicesDTO localDeviceCaches = devicesCache; List<DeviceDTO> localDeviceCaches = devicesCache;
if (localDeviceCaches != null && childHandler instanceof MyQDeviceHandler) { if (childHandler instanceof MyQDeviceHandler) {
MyQDeviceHandler handler = (MyQDeviceHandler) childHandler; MyQDeviceHandler handler = (MyQDeviceHandler) childHandler;
localDeviceCaches.items.stream() localDeviceCaches.stream()
.filter(d -> ((MyQDeviceHandler) childHandler).getSerialNumber().equalsIgnoreCase(d.serialNumber)) .filter(d -> ((MyQDeviceHandler) childHandler).getSerialNumber().equalsIgnoreCase(d.serialNumber))
.findFirst().ifPresent(handler::handleDeviceUpdate); .findFirst().ifPresent(handler::handleDeviceUpdate);
} }
@ -182,33 +188,42 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
} }
/** /**
* Sends an action to the MyQ API * Sends a door action to the MyQ API
* *
* @param serialNumber * @param device
* @param action * @param action
*/ */
public void sendAction(String serialNumber, String action) { public void sendDoorAction(DeviceDTO device, String action) {
sendAction(device, action, CMD_DOOR_URL);
}
/**
* Sends a lamp action to the MyQ API
*
* @param device
* @param action
*/
public void sendLampAction(DeviceDTO device, String action) {
sendAction(device, action, CMD_LAMP_URL);
}
private void sendAction(DeviceDTO device, String action, String urlFormat) {
if (getThing().getStatus() != ThingStatus.ONLINE) { if (getThing().getStatus() != ThingStatus.ONLINE) {
logger.debug("Account offline, ignoring action {}", action); logger.debug("Account offline, ignoring action {}", action);
return; return;
} }
AccountDTO localAccount = account; try {
if (localAccount != null) { ContentResponse response = sendRequest(
try { String.format(urlFormat, device.accountId, device.serialNumber, action), HttpMethod.PUT, null,
ContentResponse response = sendRequest( null);
String.format("%s/v5.1/Accounts/%s/Devices/%s/actions", BASE_URL, localAccount.account.id, if (HttpStatus.isSuccess(response.getStatus())) {
serialNumber), restartPolls(true);
HttpMethod.PUT, new StringContentProvider(gsonLowerCase.toJson(new ActionDTO(action))), } else {
"application/json"); logger.debug("Failed to send action {} : {}", action, response.getContentAsString());
if (HttpStatus.isSuccess(response.getStatus())) {
restartPolls(true);
} else {
logger.debug("Failed to send action {} : {}", action, response.getContentAsString());
}
} catch (InterruptedException | MyQCommunicationException | MyQAuthenticationException e) {
logger.debug("Could not send action", e);
} }
} catch (InterruptedException | MyQCommunicationException | MyQAuthenticationException e) {
logger.debug("Could not send action", e);
} }
} }
@ -217,7 +232,7 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
* *
* @return cached MyQ devices * @return cached MyQ devices
*/ */
public @Nullable DevicesDTO devicesCache() { public @Nullable List<DeviceDTO> devicesCache() {
return devicesCache; return devicesCache;
} }
@ -266,8 +281,8 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
private synchronized void fetchData() { private synchronized void fetchData() {
try { try {
if (account == null) { if (accounts == null) {
getAccount(); getAccounts();
} }
getDevices(); getDevices();
} catch (MyQCommunicationException e) { } catch (MyQCommunicationException e) {
@ -338,33 +353,37 @@ public class MyQAccountHandler extends BaseBridgeHandler implements AccessTokenR
} }
} }
private void getAccount() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException { private void getAccounts() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
ContentResponse response = sendRequest(BASE_URL + "/v5/My?expand=account", HttpMethod.GET, null, null); ContentResponse response = sendRequest(ACCOUNTS_URL, HttpMethod.GET, null, null);
account = parseResultAndUpdateStatus(response, gsonUpperCase, AccountDTO.class); accounts = parseResultAndUpdateStatus(response, gsonLowerCase, AccountsDTO.class);
} }
private void getDevices() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException { private void getDevices() throws InterruptedException, MyQCommunicationException, MyQAuthenticationException {
AccountDTO localAccount = account; AccountsDTO localAccounts = accounts;
if (localAccount == null) { if (localAccounts == null) {
return; return;
} }
ContentResponse response = sendRequest(
String.format("%s/v5.1/Accounts/%s/Devices", BASE_URL, localAccount.account.id), HttpMethod.GET, null, List<DeviceDTO> currentDevices = new ArrayList<DeviceDTO>();
null);
DevicesDTO devices = parseResultAndUpdateStatus(response, gsonLowerCase, DevicesDTO.class); for (AccountDTO account : localAccounts.accounts) {
devicesCache = devices; ContentResponse response = sendRequest(String.format(DEVICES_URL, account.id), HttpMethod.GET, null, null);
devices.items.forEach(device -> { DevicesDTO devices = parseResultAndUpdateStatus(response, gsonLowerCase, DevicesDTO.class);
ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily); currentDevices.addAll(devices.items);
if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) { devices.items.forEach(device -> {
for (Thing thing : getThing().getThings()) { ThingTypeUID thingTypeUID = new ThingTypeUID(BINDING_ID, device.deviceFamily);
ThingHandler handler = thing.getHandler(); if (SUPPORTED_DISCOVERY_THING_TYPES_UIDS.contains(thingTypeUID)) {
if (handler != null for (Thing thing : getThing().getThings()) {
&& ((MyQDeviceHandler) handler).getSerialNumber().equalsIgnoreCase(device.serialNumber)) { ThingHandler handler = thing.getHandler();
((MyQDeviceHandler) handler).handleDeviceUpdate(device); if (handler != null && ((MyQDeviceHandler) handler).getSerialNumber()
.equalsIgnoreCase(device.serialNumber)) {
((MyQDeviceHandler) handler).handleDeviceUpdate(device);
}
} }
} }
} });
}); }
devicesCache = currentDevices;
} }
private synchronized ContentResponse sendRequest(String url, HttpMethod method, @Nullable ContentProvider content, private synchronized ContentResponse sendRequest(String url, HttpMethod method, @Nullable ContentProvider content,

View File

@ -40,7 +40,7 @@ import org.openhab.core.types.UnDefType;
*/ */
@NonNullByDefault @NonNullByDefault
public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceHandler { public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceHandler {
private @Nullable DeviceDTO deviceState; private @Nullable DeviceDTO device;
private String serialNumber; private String serialNumber;
public MyQGarageDoorHandler(Thing thing) { public MyQGarageDoorHandler(Thing thing) {
@ -60,8 +60,8 @@ public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceH
return; return;
} }
Bridge bridge = getBridge(); Bridge bridge = getBridge();
final DeviceDTO localState = deviceState; final DeviceDTO localDevice = device;
if (bridge != null && localState != null) { if (bridge != null && localDevice != null) {
BridgeHandler handler = bridge.getHandler(); BridgeHandler handler = bridge.getHandler();
if (handler != null) { if (handler != null) {
String cmd = null; String cmd = null;
@ -78,7 +78,7 @@ public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceH
cmd = command.toString(); cmd = command.toString();
} }
if (cmd != null) { if (cmd != null) {
((MyQAccountHandler) handler).sendAction(localState.serialNumber, cmd); ((MyQAccountHandler) handler).sendDoorAction(localDevice, cmd);
} }
} }
} }
@ -90,9 +90,9 @@ public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceH
} }
protected void updateState() { protected void updateState() {
final DeviceDTO localState = deviceState; final DeviceDTO localDevice = device;
if (localState != null) { if (localDevice != null) {
String doorState = localState.state.doorState; String doorState = localDevice.state.doorState;
updateState("status", new StringType(doorState)); updateState("status", new StringType(doorState));
switch (doorState) { switch (doorState) {
case "open": case "open":
@ -112,8 +112,8 @@ public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceH
updateState("rollershutter", UnDefType.UNDEF); updateState("rollershutter", UnDefType.UNDEF);
break; break;
} }
updateState("closeerror", localState.state.isUnattendedCloseAllowed ? OnOffType.OFF : OnOffType.ON); updateState("closeerror", localDevice.state.isUnattendedCloseAllowed ? OnOffType.OFF : OnOffType.ON);
updateState("openerror", localState.state.isUnattendedOpenAllowed ? OnOffType.OFF : OnOffType.ON); updateState("openerror", localDevice.state.isUnattendedOpenAllowed ? OnOffType.OFF : OnOffType.ON);
} }
} }
@ -122,7 +122,7 @@ public class MyQGarageDoorHandler extends BaseThingHandler implements MyQDeviceH
if (!MyQBindingConstants.THING_TYPE_GARAGEDOOR.getId().equals(device.deviceFamily)) { if (!MyQBindingConstants.THING_TYPE_GARAGEDOOR.getId().equals(device.deviceFamily)) {
return; return;
} }
deviceState = device; this.device = device;
if (device.state.online) { if (device.state.online) {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
updateState(); updateState();

View File

@ -36,7 +36,7 @@ import org.openhab.core.types.RefreshType;
*/ */
@NonNullByDefault @NonNullByDefault
public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler { public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler {
private @Nullable DeviceDTO deviceState; private @Nullable DeviceDTO device;
private String serialNumber; private String serialNumber;
public MyQLampHandler(Thing thing) { public MyQLampHandler(Thing thing) {
@ -58,11 +58,11 @@ public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler
if (command instanceof OnOffType) { if (command instanceof OnOffType) {
Bridge bridge = getBridge(); Bridge bridge = getBridge();
final DeviceDTO localState = deviceState; final DeviceDTO localDevice = device;
if (bridge != null && localState != null) { if (bridge != null && localDevice != null) {
BridgeHandler handler = bridge.getHandler(); BridgeHandler handler = bridge.getHandler();
if (handler != null) { if (handler != null) {
((MyQAccountHandler) handler).sendAction(localState.serialNumber, ((MyQAccountHandler) handler).sendLampAction(localDevice,
command == OnOffType.ON ? "turnon" : "turnoff"); command == OnOffType.ON ? "turnon" : "turnoff");
} }
} }
@ -75,9 +75,9 @@ public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler
} }
protected void updateState() { protected void updateState() {
final DeviceDTO localState = deviceState; final DeviceDTO localDevice = device;
if (localState != null) { if (localDevice != null) {
String lampState = localState.state.lampState; String lampState = localDevice.state.lampState;
updateState("switch", "on".equals(lampState) ? OnOffType.ON : OnOffType.OFF); updateState("switch", "on".equals(lampState) ? OnOffType.ON : OnOffType.OFF);
} }
} }
@ -87,7 +87,7 @@ public class MyQLampHandler extends BaseThingHandler implements MyQDeviceHandler
if (!MyQBindingConstants.THING_TYPE_LAMP.getId().equals(device.deviceFamily)) { if (!MyQBindingConstants.THING_TYPE_LAMP.getId().equals(device.deviceFamily)) {
return; return;
} }
deviceState = device; this.device = device;
if (device.state.online) { if (device.state.online) {
updateStatus(ThingStatus.ONLINE); updateStatus(ThingStatus.ONLINE);
updateState(); updateState();