Add additional hub properties (#13174)

Signed-off-by: Jacob Laursen <jacob-github@vindvejr.dk>
This commit is contained in:
Jacob Laursen 2022-07-28 08:43:17 +02:00 committed by GitHub
parent 6028533e8e
commit 5ec86ec614
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 188 additions and 22 deletions

View File

@ -65,6 +65,7 @@ public class HDPowerViewBindingConstants {
// Hub properties // Hub properties
public static final String PROPERTY_FIRMWARE_NAME = "firmwareName"; public static final String PROPERTY_FIRMWARE_NAME = "firmwareName";
public static final String PROPERTY_RADIO_FIRMWARE_VERSION = "radioFirmwareVersion"; public static final String PROPERTY_RADIO_FIRMWARE_VERSION = "radioFirmwareVersion";
public static final String PROPERTY_HUB_NAME = "hubName";
// Shade properties // Shade properties
public static final String PROPERTY_SHADE_TYPE = "type"; public static final String PROPERTY_SHADE_TYPE = "type";

View File

@ -28,8 +28,10 @@ import org.eclipse.jetty.http.HttpHeader;
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.openhab.binding.hdpowerview.internal.api.Color; import org.openhab.binding.hdpowerview.internal.api.Color;
import org.openhab.binding.hdpowerview.internal.api.HubFirmware;
import org.openhab.binding.hdpowerview.internal.api.ShadePosition; import org.openhab.binding.hdpowerview.internal.api.ShadePosition;
import org.openhab.binding.hdpowerview.internal.api.SurveyData; import org.openhab.binding.hdpowerview.internal.api.SurveyData;
import org.openhab.binding.hdpowerview.internal.api.UserData;
import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterBlinking; import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterBlinking;
import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterColor; import org.openhab.binding.hdpowerview.internal.api.requests.RepeaterColor;
import org.openhab.binding.hdpowerview.internal.api.requests.ShadeCalibrate; import org.openhab.binding.hdpowerview.internal.api.requests.ShadeCalibrate;
@ -37,7 +39,6 @@ import org.openhab.binding.hdpowerview.internal.api.requests.ShadeJog;
import org.openhab.binding.hdpowerview.internal.api.requests.ShadeMove; import org.openhab.binding.hdpowerview.internal.api.requests.ShadeMove;
import org.openhab.binding.hdpowerview.internal.api.requests.ShadeStop; import org.openhab.binding.hdpowerview.internal.api.requests.ShadeStop;
import org.openhab.binding.hdpowerview.internal.api.responses.FirmwareVersion; import org.openhab.binding.hdpowerview.internal.api.responses.FirmwareVersion;
import org.openhab.binding.hdpowerview.internal.api.responses.FirmwareVersions;
import org.openhab.binding.hdpowerview.internal.api.responses.Repeater; import org.openhab.binding.hdpowerview.internal.api.responses.Repeater;
import org.openhab.binding.hdpowerview.internal.api.responses.RepeaterData; import org.openhab.binding.hdpowerview.internal.api.responses.RepeaterData;
import org.openhab.binding.hdpowerview.internal.api.responses.Repeaters; import org.openhab.binding.hdpowerview.internal.api.responses.Repeaters;
@ -51,6 +52,7 @@ import org.openhab.binding.hdpowerview.internal.api.responses.Shade;
import org.openhab.binding.hdpowerview.internal.api.responses.Shades; import org.openhab.binding.hdpowerview.internal.api.responses.Shades;
import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData; import org.openhab.binding.hdpowerview.internal.api.responses.Shades.ShadeData;
import org.openhab.binding.hdpowerview.internal.api.responses.Survey; import org.openhab.binding.hdpowerview.internal.api.responses.Survey;
import org.openhab.binding.hdpowerview.internal.api.responses.UserDataResponse;
import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException; import org.openhab.binding.hdpowerview.internal.exceptions.HubInvalidResponseException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException; import org.openhab.binding.hdpowerview.internal.exceptions.HubMaintenanceException;
import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException; import org.openhab.binding.hdpowerview.internal.exceptions.HubProcessingException;
@ -94,6 +96,7 @@ public class HDPowerViewWebTargets {
private final String sceneCollections; private final String sceneCollections;
private final String scheduledEvents; private final String scheduledEvents;
private final String repeaters; private final String repeaters;
private final String userData;
private final Gson gson = new Gson(); private final Gson gson = new Gson();
private final HttpClient httpClient; private final HttpClient httpClient;
@ -137,7 +140,7 @@ public class HDPowerViewWebTargets {
public HDPowerViewWebTargets(HttpClient httpClient, String ipAddress) { public HDPowerViewWebTargets(HttpClient httpClient, String ipAddress) {
base = "http://" + ipAddress + "/api/"; base = "http://" + ipAddress + "/api/";
shades = base + "shades/"; shades = base + "shades/";
firmwareVersion = base + "fwversion/"; firmwareVersion = base + "fwversion";
sceneActivate = base + "scenes"; sceneActivate = base + "scenes";
scenes = base + "scenes/"; scenes = base + "scenes/";
@ -146,8 +149,8 @@ public class HDPowerViewWebTargets {
sceneCollections = base + "scenecollections/"; sceneCollections = base + "scenecollections/";
scheduledEvents = base + "scheduledevents"; scheduledEvents = base + "scheduledevents";
repeaters = base + "repeaters/"; repeaters = base + "repeaters/";
userData = base + "userdata";
this.httpClient = httpClient; this.httpClient = httpClient;
} }
@ -160,7 +163,7 @@ public class HDPowerViewWebTargets {
* @throws HubProcessingException if there is any processing error * @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance * @throws HubMaintenanceException if the hub is down for maintenance
*/ */
public FirmwareVersions getFirmwareVersions() public HubFirmware getFirmwareVersions()
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException {
String json = invoke(HttpMethod.GET, firmwareVersion, null, null); String json = invoke(HttpMethod.GET, firmwareVersion, null, null);
try { try {
@ -168,7 +171,7 @@ public class HDPowerViewWebTargets {
if (firmwareVersion == null) { if (firmwareVersion == null) {
throw new HubInvalidResponseException("Missing firmware response"); throw new HubInvalidResponseException("Missing firmware response");
} }
FirmwareVersions firmwareVersions = firmwareVersion.firmware; HubFirmware firmwareVersions = firmwareVersion.firmware;
if (firmwareVersions == null) { if (firmwareVersions == null) {
throw new HubInvalidResponseException("Missing 'firmware' element"); throw new HubInvalidResponseException("Missing 'firmware' element");
} }
@ -178,6 +181,31 @@ public class HDPowerViewWebTargets {
} }
} }
/**
* Fetches a JSON package with user data information for the hub.
*
* @return {@link UserData} class instance
* @throws HubInvalidResponseException if response is invalid
* @throws HubProcessingException if there is any processing error
* @throws HubMaintenanceException if the hub is down for maintenance
*/
public UserData getUserData() throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException {
String json = invoke(HttpMethod.GET, userData, null, null);
try {
UserDataResponse userDataResponse = gson.fromJson(json, UserDataResponse.class);
if (userDataResponse == null) {
throw new HubInvalidResponseException("Missing userData response");
}
UserData userData = userDataResponse.userData;
if (userData == null) {
throw new HubInvalidResponseException("Missing 'userData' element");
}
return userData;
} catch (JsonParseException e) {
throw new HubInvalidResponseException("Error parsing userData response", e);
}
}
/** /**
* Fetches a JSON package that describes all shades in the hub, and wraps it in * Fetches a JSON package that describes all shades in the hub, and wraps it in
* a Shades class instance * a Shades class instance

View File

@ -10,11 +10,10 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.openhab.binding.hdpowerview.internal.api.responses; package org.openhab.binding.hdpowerview.internal.api;
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.hdpowerview.internal.api.Firmware;
/** /**
* Firmware information for an HD PowerView hub * Firmware information for an HD PowerView hub
@ -22,7 +21,7 @@ import org.openhab.binding.hdpowerview.internal.api.Firmware;
* @author Jacob Laursen - Initial contribution * @author Jacob Laursen - Initial contribution
*/ */
@NonNullByDefault @NonNullByDefault
public class FirmwareVersions { public class HubFirmware {
@Nullable @Nullable
public Firmware mainProcessor; public Firmware mainProcessor;
@Nullable @Nullable

View File

@ -0,0 +1,31 @@
/**
* 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.hdpowerview.internal.api;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* Times as part of {@link UserData} for an HD PowerView hub
*
* @author Jacob Laursen - Initial contribution
*/
@NonNullByDefault
public class Times {
public @Nullable String timezone;
public int localSunriseTimeInMinutes;
public int localSunsetTimeInMinutes;
public int currentOffset;
public double longitude;
public double latitude;
}

View File

@ -0,0 +1,58 @@
/**
* 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.hdpowerview.internal.api;
import java.util.Base64;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import com.google.gson.annotations.SerializedName;
/**
* User data for an HD PowerView hub
*
* @author Jacob Laursen - Initial contribution
*/
@NonNullByDefault
public class UserData {
public @Nullable String hubName;
public boolean localTimeDataSet;
public boolean enableScheduledEvents;
public boolean editingEnabled;
public boolean setupCompleted;
public @Nullable String gateway;
public @Nullable String dns;
public boolean staticIp;
@SerializedName("_id")
public @Nullable String id;
public @Nullable Color color;
public boolean autoBackup;
public @Nullable String ip;
public @Nullable String macAddress;
public @Nullable String mask;
public boolean wireless;
public @Nullable HubFirmware firmware;
public @Nullable String serialNumber;
public @Nullable String rfIDInt;
public @Nullable String rfID;
public int rfStatus;
public @Nullable Times times;
public @Nullable String brand;
public boolean rcUp;
public boolean remoteConnectEnabled;
public String getHubName() {
return hubName != null ? new String(Base64.getDecoder().decode(hubName)) : "";
}
}

View File

@ -14,6 +14,7 @@ package org.openhab.binding.hdpowerview.internal.api.responses;
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.hdpowerview.internal.api.HubFirmware;
/** /**
* Firmware information for an HD PowerView hub * Firmware information for an HD PowerView hub
@ -23,5 +24,5 @@ import org.eclipse.jdt.annotation.Nullable;
@NonNullByDefault @NonNullByDefault
public class FirmwareVersion { public class FirmwareVersion {
@Nullable @Nullable
public FirmwareVersions firmware; public HubFirmware firmware;
} }

View File

@ -0,0 +1,27 @@
/**
* 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.hdpowerview.internal.api.responses;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.binding.hdpowerview.internal.api.UserData;
/**
* Response with {@link UserData} for an HD PowerView hub
*
* @author Jacob Laursen - Initial contribution
*/
@NonNullByDefault
public class UserDataResponse {
public @Nullable UserData userData;
}

View File

@ -31,7 +31,8 @@ import org.openhab.binding.hdpowerview.internal.HDPowerViewBindingConstants;
import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider; import org.openhab.binding.hdpowerview.internal.HDPowerViewTranslationProvider;
import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets; import org.openhab.binding.hdpowerview.internal.HDPowerViewWebTargets;
import org.openhab.binding.hdpowerview.internal.api.Firmware; import org.openhab.binding.hdpowerview.internal.api.Firmware;
import org.openhab.binding.hdpowerview.internal.api.responses.FirmwareVersions; import org.openhab.binding.hdpowerview.internal.api.HubFirmware;
import org.openhab.binding.hdpowerview.internal.api.UserData;
import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections; import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections;
import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection; import org.openhab.binding.hdpowerview.internal.api.responses.SceneCollections.SceneCollection;
import org.openhab.binding.hdpowerview.internal.api.responses.Scenes; import org.openhab.binding.hdpowerview.internal.api.responses.Scenes;
@ -98,7 +99,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
private List<Scene> sceneCache = new CopyOnWriteArrayList<>(); private List<Scene> sceneCache = new CopyOnWriteArrayList<>();
private List<SceneCollection> sceneCollectionCache = new CopyOnWriteArrayList<>(); private List<SceneCollection> sceneCollectionCache = new CopyOnWriteArrayList<>();
private List<ScheduledEvent> scheduledEventCache = new CopyOnWriteArrayList<>(); private List<ScheduledEvent> scheduledEventCache = new CopyOnWriteArrayList<>();
private Instant firmwareVersionsUpdated = Instant.MIN; private Instant UserDataUpdated = Instant.MIN;
private Boolean deprecatedChannelsCreated = false; private Boolean deprecatedChannelsCreated = false;
private final ChannelTypeUID sceneChannelTypeUID = new ChannelTypeUID(HDPowerViewBindingConstants.BINDING_ID, private final ChannelTypeUID sceneChannelTypeUID = new ChannelTypeUID(HDPowerViewBindingConstants.BINDING_ID,
@ -144,7 +145,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
} }
} catch (HubMaintenanceException e) { } catch (HubMaintenanceException e) {
// exceptions are logged in HDPowerViewWebTargets // exceptions are logged in HDPowerViewWebTargets
firmwareVersionsUpdated = Instant.MIN; UserDataUpdated = Instant.MIN;
} catch (NumberFormatException | HubException e) { } catch (NumberFormatException | HubException e) {
logger.debug("Unexpected error {}", e.getMessage()); logger.debug("Unexpected error {}", e.getMessage());
} }
@ -168,7 +169,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
hardRefreshPositionInterval = config.hardRefresh; hardRefreshPositionInterval = config.hardRefresh;
hardRefreshBatteryLevelInterval = config.hardRefreshBatteryLevel; hardRefreshBatteryLevelInterval = config.hardRefreshBatteryLevel;
initializeChannels(); initializeChannels();
firmwareVersionsUpdated = Instant.MIN; UserDataUpdated = Instant.MIN;
updateStatus(ThingStatus.UNKNOWN); updateStatus(ThingStatus.UNKNOWN);
schedulePoll(); schedulePoll();
@ -283,7 +284,7 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
private synchronized void poll() { private synchronized void poll() {
try { try {
updateFirmwareProperties(); updateUserDataProperties();
} catch (HubException e) { } catch (HubException e) {
logger.warn("Failed to update firmware properties: {}", e.getMessage()); logger.warn("Failed to update firmware properties: {}", e.getMessage());
} }
@ -308,27 +309,49 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
} }
} catch (HubMaintenanceException e) { } catch (HubMaintenanceException e) {
// exceptions are logged in HDPowerViewWebTargets // exceptions are logged in HDPowerViewWebTargets
firmwareVersionsUpdated = Instant.MIN; UserDataUpdated = Instant.MIN;
} catch (HubException e) { } catch (HubException e) {
logger.warn("Error connecting to bridge: {}", e.getMessage()); logger.warn("Error connecting to bridge: {}", e.getMessage());
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
firmwareVersionsUpdated = Instant.MIN; UserDataUpdated = Instant.MIN;
} }
} }
private void updateFirmwareProperties() private void updateUserDataProperties()
throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException {
if (firmwareVersionsUpdated.isAfter(Instant.now().minus(firmwareVersionValidityPeriod))) { if (UserDataUpdated.isAfter(Instant.now().minus(firmwareVersionValidityPeriod))) {
return; return;
} }
FirmwareVersions firmwareVersions = webTargets.getFirmwareVersions();
UserData userData = webTargets.getUserData();
Map<String, String> properties = editProperties();
HubFirmware firmwareVersions = userData.firmware;
if (firmwareVersions != null) {
updateFirmwareProperties(properties, firmwareVersions);
}
String serialNumber = userData.serialNumber;
if (serialNumber != null) {
properties.put(Thing.PROPERTY_SERIAL_NUMBER, serialNumber);
}
String macAddress = userData.macAddress;
if (macAddress != null) {
properties.put(Thing.PROPERTY_MAC_ADDRESS, macAddress);
}
String hubName = userData.getHubName();
if (!hubName.isEmpty()) {
properties.put(HDPowerViewBindingConstants.PROPERTY_HUB_NAME, hubName);
}
updateProperties(properties);
UserDataUpdated = Instant.now();
}
private void updateFirmwareProperties(Map<String, String> properties, HubFirmware firmwareVersions) {
Firmware mainProcessor = firmwareVersions.mainProcessor; Firmware mainProcessor = firmwareVersions.mainProcessor;
if (mainProcessor == null) { if (mainProcessor == null) {
logger.warn("Main processor firmware version missing in response."); logger.warn("Main processor firmware version missing in response.");
return; return;
} }
logger.debug("Main processor firmware version received: {}, {}", mainProcessor.name, mainProcessor.toString()); logger.debug("Main processor firmware version received: {}, {}", mainProcessor.name, mainProcessor.toString());
Map<String, String> properties = editProperties();
String mainProcessorName = mainProcessor.name; String mainProcessorName = mainProcessor.name;
if (mainProcessorName != null) { if (mainProcessorName != null) {
properties.put(HDPowerViewBindingConstants.PROPERTY_FIRMWARE_NAME, mainProcessorName); properties.put(HDPowerViewBindingConstants.PROPERTY_FIRMWARE_NAME, mainProcessorName);
@ -339,8 +362,6 @@ public class HDPowerViewHubHandler extends BaseBridgeHandler {
logger.debug("Radio firmware version received: {}", radio.toString()); logger.debug("Radio firmware version received: {}", radio.toString());
properties.put(HDPowerViewBindingConstants.PROPERTY_RADIO_FIRMWARE_VERSION, radio.toString()); properties.put(HDPowerViewBindingConstants.PROPERTY_RADIO_FIRMWARE_VERSION, radio.toString());
} }
updateProperties(properties);
firmwareVersionsUpdated = Instant.now();
} }
private void pollShades() throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException { private void pollShades() throws HubInvalidResponseException, HubProcessingException, HubMaintenanceException {