From 07c48463cbc7e708d2d40de95055376034995189 Mon Sep 17 00:00:00 2001 From: Holger Eisold Date: Wed, 23 Oct 2019 14:56:06 +0200 Subject: [PATCH] Added houshold users, locationChangedThrough channel, updated Readme (#8) * Added household users and locationChangedThrough channel * Updated Readme * openHAB/ESH code formatting * fixed NPE for gender, breed, species * minor translation fixes * Fixed pet status polling job, Removed PetLocation - using PetStatusActivity instead, Updated Readme.md to use tabs in PaperUI control, Updated API call for PetStatus (now using only one call for all pets), some other renaming changes Co-authored-by: Holger Eisold Co-authored-by: Rene Scherer Signed-off-by: Holger Eisold --- .../org.openhab.binding.surepetcare/README.md | 187 +++++++++++------- .../internal/SurePetcareAPIHelper.java | 54 ++--- .../internal/SurePetcareConstants.java | 6 +- .../internal/data/SurePetcareHousehold.java | 58 ++++-- .../internal/data/SurePetcarePet.java | 10 - ...ation.java => SurePetcarePetActivity.java} | 80 ++------ .../internal/data/SurePetcarePetFeeding.java | 80 ++++++++ .../internal/data/SurePetcarePetStatus.java | 133 +------------ .../SurePetcareDiscoveryService.java | 6 +- .../handler/SurePetcareBaseObjectHandler.java | 2 +- .../handler/SurePetcareBridgeHandler.java | 26 +-- .../handler/SurePetcareHouseholdHandler.java | 6 + .../handler/SurePetcarePetHandler.java | 61 +++--- .../resources/ESH-INF/binding/binding.xml | 9 +- .../ESH-INF/i18n/surepetcare.properties | 8 +- .../ESH-INF/i18n/surepetcare_de.properties | 8 +- .../main/resources/ESH-INF/thing/bridge.xml | 15 +- .../main/resources/ESH-INF/thing/things.xml | 41 ++-- .../config/things/surepetcare.things | 13 +- .../data/SurePetcarePetLocationTest.java | 12 +- .../internal/data/SurePetcarePetTest.java | 5 +- 21 files changed, 409 insertions(+), 411 deletions(-) rename bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/{SurePetcarePetLocation.java => SurePetcarePetActivity.java} (53%) create mode 100644 bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetFeeding.java diff --git a/bundles/org.openhab.binding.surepetcare/README.md b/bundles/org.openhab.binding.surepetcare/README.md index 346ff8fffef19..474bda60cbb89 100644 --- a/bundles/org.openhab.binding.surepetcare/README.md +++ b/bundles/org.openhab.binding.surepetcare/README.md @@ -32,6 +32,7 @@ This binding supports the following thing types | Household | Thing | Automatic | The Sure Petcare Household | | Hub Device | Thing | Automatic | The hub device which connects the cat flaps and feeders to the internet | | Flap Device | Thing | Automatic | A cat or pet flap | +| Feeder Device | Thing | Automatic | A pet feeder | | Pet | Thing | Automatic | A pet (dog or cat) | @@ -49,76 +50,130 @@ Channel names in **bold** are read/write, everything else is read-only ### Bridge Thing -| Channel | Type | Description | -|-------------------|----------|--------------------------------------------------------------------------------------------| -| online | Switch | Parameter indicating if the bridge has a valid connection to the Sure Petcare API | -| **refresh** | Switch | Trigger switch to force a full cache update | +| Channel | Type | Description | +|-------------|--------|-----------------------------------------------------------------------------------| +| online | Switch | Parameter indicating if the bridge has a valid connection to the Sure Petcare API | +| **refresh** | Switch | Trigger switch to force a full cache update | + ### Household Thing -| Channel | Type | Description | -|-------------------|----------|--------------------------------------------------------------------------------------------| -| id | Number | A unique id assigned by the Sure Petcare API | -| name | Text | The name of the household | -| timezoneId | Number | The id of the household's timezone | +| Channel | Type | Description | +|------------|----------|----------------------------------------------| +| id | Number | A unique id assigned by the Sure Petcare API | +| name | Text | The name of the household | +| timezoneId | Number | The id of the household's timezone | +| createdAt | DateTime | The date when the household was created | +| updatedAt | DateTime | The date when the household was last updated | +| userName1 | Text | The name of the first household user | +| userName2 | Text | The name of the second household user | +| userName3 | Text | The name of the third household user | +| userName4 | Text | The name of the fourth household user | +| userName5 | Text | The name of the fifth household user | ### Hub Device Thing -| Channel | Type | Description | -|-------------------|----------|--------------------------------------------------------------------------------------------| -| id | Number | A unique id assigned by the Sure Petcare API | -| name | Text | The name of the hub | -| product | Text | The type of product (1=hub) | -| **ledMode** | Text | The mode of the hub's LED ears | -| pairingMode | Text | The state of pairing | -| hardwareVersion | Number | The hub's hardware version number | -| firmwareVersion | Number | The hub's firmware number | -| online | Switch | Indicator if the hub is connected to the internet | +| Channel | Type | Description | +|-----------------|----------|-----------------------------------------------------------------------| +| id | Number | A unique id assigned by the Sure Petcare API | +| name | Text | The name of the hub | +| product | Text | The type of product (1=hub) | +| **ledMode** | Text | The mode of the hub's LED ears | +| pairingMode | Text | The state of pairing | +| hardwareVersion | Number | The hub's hardware version number | +| firmwareVersion | Number | The hub's firmware number | +| online | Switch | Indicator if the hub is connected to the internet | +| serialNumber | Text | The serial number of the device | +| macAddress | Text | The mac address of the device | +| createdAt | DateTime | The date when the device was created (could be the manufactured date) | +| updatedAt | DateTime | The date when the device was last updated (device settings changed) | ### Flap Device Thing (Cat or Pet Flap) -| Channel | Type | Description | -|-----------------------|----------|--------------------------------------------------------------------------------------------| -| id | Number | A unique id assigned by the Sure Petcare API | -| name | Text | The name of the flap | -| product | Text | The type of product (3=pet flap, 6=cat flap) | -| **curfewEnabled1** | Switch | Indicator if curfew #1 configuration is enabled | -| **curfewLockTime1** | Text | The curfew #1 locking time (HH:MM) | -| **curfewUnlockTime1** | Text | The curfew #1 unlocking time (HH:MM) | -| **curfewEnabled2** | Switch | Indicator if curfew #2 configuration is enabled | -| **curfewLockTime2** | Text | The curfew #2 locking time (HH:MM) | -| **curfewUnlockTime2** | Text | The curfew #2 unlocking time (HH:MM) | -| **curfewEnabled3** | Switch | Indicator if curfew #3 configuration is enabled | -| **curfewLockTime3** | Text | The curfew #3 locking time (HH:MM) | -| **curfewUnlockTime3** | Text | The curfew #3 unlocking time (HH:MM) | -| **curfewEnabled4** | Switch | Indicator if curfew #4 configuration is enabled | -| **curfewLockTime4** | Text | The curfew #4 locking time (HH:MM) | -| **curfewUnlockTime4** | Text | The curfew #4 unlocking time (HH:MM) | -| hardwareVersion | Text | The flap's hardware version number | -| **lockingMode** | Text | The locking mode (e.g. in/out, in-only, out-only etc.) | -| hardwareVersion | Number | The flap's hardware version number | -| firmwareVersion | Number | The flap's firmware number | -| online | Switch | Indicator if the flap is connected to the hub | -| lowBattery | Switch | Indicator if the battery voltage is low | -| batteryLevel | Number | The battery voltage percentage | -| batteryVoltage | Number | The absolute battery voltage measurement | -| deviceRSSI | Number | The received device signal strength in dB | -| hubRSSI | Number | The received hub signal strength in dB | +| Channel | Type | Description | +|-----------------------|----------|-----------------------------------------------------------------------| +| id | Number | A unique id assigned by the Sure Petcare API | +| name | Text | The name of the flap | +| product | Text | The type of product (3=pet flap, 6=cat flap) | +| **curfewEnabled1** | Switch | Indicator if curfew #1 configuration is enabled | +| **curfewLockTime1** | Text | The curfew #1 locking time (HH:MM) | +| **curfewUnlockTime1** | Text | The curfew #1 unlocking time (HH:MM) | +| **curfewEnabled2** | Switch | Indicator if curfew #2 configuration is enabled | +| **curfewLockTime2** | Text | The curfew #2 locking time (HH:MM) | +| **curfewUnlockTime2** | Text | The curfew #2 unlocking time (HH:MM) | +| **curfewEnabled3** | Switch | Indicator if curfew #3 configuration is enabled | +| **curfewLockTime3** | Text | The curfew #3 locking time (HH:MM) | +| **curfewUnlockTime3** | Text | The curfew #3 unlocking time (HH:MM) | +| **curfewEnabled4** | Switch | Indicator if curfew #4 configuration is enabled | +| **curfewLockTime4** | Text | The curfew #4 locking time (HH:MM) | +| **curfewUnlockTime4** | Text | The curfew #4 unlocking time (HH:MM) | +| **lockingMode** | Text | The locking mode (e.g. in/out, in-only, out-only etc.) | +| hardwareVersion | Number | The flap's hardware version number | +| firmwareVersion | Number | The flap's firmware number | +| online | Switch | Indicator if the flap is connected to the hub | +| lowBattery | Switch | Indicator if the battery voltage is low | +| batteryLevel | Number | The battery voltage percentage | +| batteryVoltage | Number | The absolute battery voltage measurement | +| deviceRSSI | Number | The received device signal strength in dB | +| hubRSSI | Number | The received hub signal strength in dB | +| serialNumber | Text | The serial number of the device | +| macAddress | Text | The mac address of the device | +| createdAt | DateTime | The date when the device was created (could be the manufactured date) | +| updatedAt | DateTime | The date when the device was last updated (device settings changed) | +| pairingAt | Datetime | The date when the device was included in the hub device | + +### Feeder Device Thing + +| Channel | Type | Description | +|-------------------|-------------|-------------------------------------------------------------------------------------------------| +| id | Number | A unique id assigned by the Sure Petcare API | +| name | Text | The name of the feeder | +| product | Text | The type of product | +| hardwareVersion | Number | The feeder's hardware version number | +| firmwareVersion | Number | The feeder's firmware number | +| online | Switch | Indicator if the feeder is connected to the hub | +| lowBattery | Switch | Indicator if the battery voltage is low | +| batteryLevel | Number | The battery voltage percentage | +| batteryVoltage | Number | The absolute battery voltage measurement | +| deviceRSSI | Number | The received device signal strength in dB | +| hubRSSI | Number | The received hub signal strength in dB | +| serialNumber | Text | The serial number of the device | +| macAddress | Text | The mac address of the device | +| createdAt | DateTime | The date when the device was created (could be the manufactured date) | +| updatedAt | DateTime | The date when the device was last updated (device settings changed) | +| pairingAt | Datetime | The date when the device was included in the hub device | +| bowls | Text | The feeder bowls type (1 big bowl or 2 half bowls) | +| bowlsFood | Text | The feeder big bowl food type (wet food, dry food or both) | +| bowlsTarget | Number:Mass | The feeder big bowl target weight in gram (even if user setting is oz, API stores this in gram) | +| bowlsFoodLeft | Text | The feeder left half bowl food type (wet food, dry food or both) | +| bowlsTargetLeft | Number:Mass | The feeder left half bowl target weight | +| bowlsFoodRight | Text | The feeder right half bowl food type (wet food, dry food or both) | +| bowlsTargetRight | Number:Mass | The feeder right half bowl target weight | +| bowlsCloseDelay | Text | The feeder lid close delay (fast, normal, slow) | +| bowlsTrainingMode | Text | The feeder training mode (off, full open, almost full open, half closed, almost closed) | ### Pet Thing -| Channel | Type | Description | -|-------------------|----------|--------------------------------------------------------------------------------------------| -| id | Number | A unique id assigned by the Sure Petcare API | -| name | Text | The name of the pet | -| comment | Text | A user provided comment/description | -| gender | Text | The pet's gender | -| breed | Text | The pet's breed | -| species | Text | The pet's species | -| photoURL | Text | The URL of the pet's photo | -| tagIdentifier | Text | The unique identifier of the pet's micro chip or collar tag | -| **location** | Text | The current location of the pet (0=unknown, 1=inside, 2=outside) | -| locationChanged | DateTime | The time when the location was last changed | +| Channel | Type | Description | +|------------------------|-------------|------------------------------------------------------------------| +| id | Number | A unique id assigned by the Sure Petcare API | +| name | Text | The name of the pet | +| comment | Text | A user provided comment/description | +| gender | Text | The pet's gender | +| breed | Text | The pet's breed | +| species | Text | The pet's species | +| photoURL | Text | The URL of the pet's photo | +| tagIdentifier | Text | The unique identifier of the pet's micro chip or collar tag | +| **location** | Text | The current location of the pet (0=unknown, 1=inside, 2=outside) | +| locationChanged | DateTime | The time when the location was last changed | +| locationChangedThrough | Text | The device name or username where the pet left/entered the house | +| weight | Number | The pet's weight | +| dateOfBirth | DateTime | The pet's date of birth | +| feederDevice | Text | The device from which the pet last ate | +| feederLastChange | Number:Mass | The last eaten change in gram (big bowl) | +| feederLastChangeLeft | Number:Mass | The last eaten change in gram (half bowl left) | +| feederLastChangeRight | Number:Mass | The last eaten change in gram (half bowl right) | +| feederLastFeeding | DateTime | The pet's last eaten date | ## Manual configuration @@ -126,12 +181,13 @@ Channel names in **bold** are read/write, everything else is read-only ### Things configuration ``` -Bridge surepetcare:bridge:bridge1 "Demo API Bridge" [ username="", password="", refresh_interval_topology=36000, refresh_interval_location=300 ] +Bridge surepetcare:bridge:bridge1 "Demo API Bridge" @ "SurePetcare" [ username="", password="", refresh_interval_topology=36000, refresh_interval_status=300 ] { - Thing household 45237 "My Household" - Thing hubDevice 439862 "My SurePetcare Hub" - Thing flapDevice 316524 "My Backdoor Cat Flap" - Thing pet 60487 "My Cat" + Thing household 45237 "My Household" @ "SurePetcare" + Thing hubDevice 439862 "My SurePetcare Hub" @ "SurePetcare Devices" + Thing flapDevice 316524 "My Backdoor Cat Flap" @ "SurePetcare Devices" + Thing feederDevice 123456 "My Pet Feeder" @ "SurePetcare Devices" + Thing pet 60487 "My Cat" @ "SurePetcare Pets" } ``` @@ -218,11 +274,6 @@ sitemap surepetcare label="Sure Petcare Sitemap" TODO ``` - -### Transform Maps - -Several of the channels are of "code"-type, i.e. they map back to a human readable value such as Locking Mode, Pet Location etc. -To allow language independent values in either items or sitemap, the MAP transformation bundle should be installed and a number of maps. The maps are currently available in the code base (src/main/resources/transform) and in the bundle jar. ## Troubleshooting diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java index 5bfe3354bf462..1b5de40a6707e 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareAPIHelper.java @@ -22,6 +22,7 @@ import java.net.SocketException; import java.net.URL; import java.net.UnknownHostException; +import java.util.Arrays; import java.util.Date; import org.eclipse.jdt.annotation.NonNull; @@ -35,7 +36,6 @@ import org.openhab.binding.surepetcare.internal.data.SurePetcareLoginCredentials; import org.openhab.binding.surepetcare.internal.data.SurePetcareLoginResponse; import org.openhab.binding.surepetcare.internal.data.SurePetcarePet; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetLocation; import org.openhab.binding.surepetcare.internal.data.SurePetcarePetStatus; import org.openhab.binding.surepetcare.internal.data.SurePetcareTag; import org.openhab.binding.surepetcare.internal.data.SurePetcareTopology; @@ -70,6 +70,7 @@ public class SurePetcareAPIHelper { private static final String API_URL = "https://app.api.surehub.io/api"; private static final String TOPOLOGY_URL = API_URL + "/me/start"; private static final String PET_BASE_URL = API_URL + "/pet"; + private static final String PET_STATUS_URL = API_URL + "/pet/?with[]=status"; private static final String DEVICE_BASE_URL = API_URL + "/device"; private static final String LOGIN_URL = API_URL + "/auth/login"; @@ -147,17 +148,16 @@ public synchronized void updateTopologyCache() { } /** - * Refreshes only the pet status (location activity and feeding information). This API call can be used more - * frequently. + * Refreshes the pet information. This API call can be used more frequently. + * Unlike for the "position" API endpoint, there is none for the "status" (activity/feeding). + * We also dont need to specify a "petId" in the call, so we just need to call the API once. */ public synchronized void updatePetStatus() { try { - for (SurePetcarePet pet : topologyCache.getPets()) { - String url = PET_BASE_URL + "/" + pet.getId().toString() + "?with[]=status"; - pet.setPetStatus(gson.fromJson(getDataFromApi(url), SurePetcarePetStatus.class)); - } + String url = PET_STATUS_URL; + topologyCache.setPets(Arrays.asList(gson.fromJson(getDataFromApi(url), SurePetcarePet[].class))); } catch (JsonSyntaxException | SurePetcareApiException e) { - logger.warn("Exception caught during topology cache update: {}", e.getMessage()); + logger.warn("Exception caught during pet status update: {}", e.getMessage()); } } @@ -210,21 +210,6 @@ public final SurePetcareTopology getTopology() { return topologyCache.getTagById(id); } - /** - * Returns the location object if a pet exists with the given id, otherwise null. - * - * @param id the pet id - * @return the location of the pet with the given id - */ - public final @Nullable SurePetcarePetLocation getPetLocation(String id) { - SurePetcarePet pet = topologyCache.getPetById(id); - if (pet != null) { - return pet.getLocation(); - } else { - return null; - } - } - /** * Returns the status object if a pet exists with the given id, otherwise null. * @@ -243,22 +228,21 @@ public final SurePetcareTopology getTopology() { /** * Updates the pet location through an API call to the Sure Petcare API. * - * @param pet the pet + * @param pet the pet * @param newLocationId the id of the new location * @throws SurePetcareApiException */ public synchronized void setPetLocation(SurePetcarePet pet, Integer newLocationId) throws SurePetcareApiException { - pet.getLocation().setPetId(pet.getId()); - pet.getLocation().setWhere(newLocationId); - pet.getLocation().setSince(new Date()); + pet.getPetStatus().getActivity().setWhere(newLocationId); + pet.getPetStatus().getActivity().setSince(new Date()); String url = PET_BASE_URL + "/" + pet.getId().toString() + "/position"; - setDataThroughApi(url, HTTP_REQUEST_METHOD_POST, pet.getLocation()); + setDataThroughApi(url, HTTP_REQUEST_METHOD_POST, pet.getPetStatus().getActivity()); } /** * Updates the device locking mode through an API call to the Sure Petcare API. * - * @param device the device + * @param device the device * @param newLockingModeId the id of the new locking mode * @throws SurePetcareApiException */ @@ -279,7 +263,7 @@ public synchronized void setDeviceLockingMode(SurePetcareDevice device, Integer /** * Updates the device led mode through an API call to the Sure Petcare API. * - * @param device the device + * @param device the device * @param newLedModeId the id of the new led mode * @throws SurePetcareApiException */ @@ -300,7 +284,7 @@ public synchronized void setDeviceLedMode(SurePetcareDevice device, Integer newL /** * Updates all curfews through an API call to the Sure Petcare API. * - * @param device the device + * @param device the device * @param curfewList the list of curfews * @throws SurePetcareApiException */ @@ -402,9 +386,9 @@ private JsonElement getDataFromApi(String url) throws SurePetcareApiException { /** * Sends a given object as a JSON payload to the API. * - * @param url the URL + * @param url the URL * @param requestMethod the request method (POST, PUT etc.) - * @param payload an object used for the payload + * @param payload an object used for the payload * @throws SurePetcareApiException */ private void setDataThroughApi(String url, String requestMethod, Object payload) throws SurePetcareApiException { @@ -464,9 +448,9 @@ private String getResultFromApi(String url) throws SurePetcareApiException { /** * Uses the given request method to send a JSON string to an API. * - * @param url the URL + * @param url the URL * @param requestMethod the required request method (POST, PUT etc.) - * @param jsonPayload the JSON string + * @param jsonPayload the JSON string * @throws SurePetcareApiException */ private void postDataThroughAPI(String url, String requestMethod, String jsonPayload) diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareConstants.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareConstants.java index 1a2db1fc17284..3a865302264a1 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareConstants.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/SurePetcareConstants.java @@ -48,7 +48,7 @@ public class SurePetcareConstants { public static final String USERNAME = "username"; public static final String PASSWORD = "password"; public static final String REFRESH_INTERVAL_TOPOLOGY = "refresh_interval_topology"; - public static final String REFRESH_INTERVAL_LOCATION = "refresh_interval_location"; + public static final String REFRESH_INTERVAL_STATUS = "refresh_interval_status"; // Bridge Channel Names public static final String BRIDGE_CHANNEL_ONLINE = "online"; @@ -58,10 +58,9 @@ public class SurePetcareConstants { public static final String HOUSEHOLD_CHANNEL_ID = "id"; public static final String HOUSEHOLD_CHANNEL_NAME = "name"; public static final String HOUSEHOLD_CHANNEL_TIMEZONE_ID = "timezoneId"; - // public static final String HOUSEHOLD_CHANNEL_TIMEZONE = "timezone"; - // public static final String HOUSEHOLD_CHANNEL_TIMEZONE_UTC_OFFSET = "timezoneUTCOffset"; public static final String HOUSEHOLD_CHANNEL_CREATED_AT = "createdAt"; public static final String HOUSEHOLD_CHANNEL_UPDATED_AT = "updatedAt"; + public static final String HOUSEHOLD_CHANNEL_USER_NAME = "userName"; // Device Channel Names public static final String DEVICE_CHANNEL_ID = "id"; @@ -107,6 +106,7 @@ public class SurePetcareConstants { public static final String PET_CHANNEL_PHOTO_URL = "photoURL"; public static final String PET_CHANNEL_LOCATION = "location"; public static final String PET_CHANNEL_LOCATION_CHANGED = "locationChanged"; + public static final String PET_CHANNEL_LOCATION_CHANGED_THROUGH = "locationChangedThrough"; public static final String PET_CHANNEL_DATE_OF_BIRTH = "dateOfBirth"; public static final String PET_CHANNEL_WEIGHT = "weight"; public static final String PET_CHANNEL_TAG_IDENTIFIER = "tagIdentifier"; diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcareHousehold.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcareHousehold.java index c2afcd7b6e1d3..a05247ab6f1f6 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcareHousehold.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcareHousehold.java @@ -12,7 +12,9 @@ */ package org.openhab.binding.surepetcare.internal.data; -import java.util.Date; +import java.util.List; + +import com.google.gson.annotations.SerializedName; /** * The {@link SurePetcareHousehold} is the Java class used as a DTO to represent a Sure Petcare Household. @@ -21,23 +23,47 @@ */ public class SurePetcareHousehold extends SurePetcareBaseObject { - // Commented members indicate properties returned by the API not used by the binding + public class HouseholdUsers { + public class User { + @SerializedName("id") + private Integer userId; + @SerializedName("name") + private String userName; + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + } + + @SerializedName("user") + private User user; - public class Timezone { - public Integer id; - public String name; - public String timezone; - public Integer utcOffset; - public Date createdAt; - public Date updatedAt; + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } } private String name; private String shareCode; private Integer timezoneId; - - // Timezone does seem to be included anymore - // private Timezone timezone = new Timezone(); + @SerializedName("users") + private List householdUsers = null; public String getName() { return name; @@ -63,6 +89,14 @@ public void setTimezoneId(Integer timezoneId) { this.timezoneId = timezoneId; } + public List getHouseholdUsers() { + return householdUsers; + } + + public void setHouseholdUsers(List householdUsers) { + this.householdUsers = householdUsers; + } + @Override public String toString() { return "SurePetcareHousehold [id=" + id + ", name=" + name + "]"; diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePet.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePet.java index cb67c49f04298..40a424eb57351 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePet.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePet.java @@ -99,8 +99,6 @@ public static PetSpecies findByTypeId(final int id) { private Integer tagId; private SurePetcarePhoto photo; - @SerializedName("position") - private SurePetcarePetLocation location = new SurePetcarePetLocation(); @SerializedName("status") private SurePetcarePetStatus status = new SurePetcarePetStatus(); @@ -192,14 +190,6 @@ public void setPhoto(SurePetcarePhoto photo) { this.photo = photo; } - public SurePetcarePetLocation getLocation() { - return location; - } - - public void setLocation(SurePetcarePetLocation position) { - this.location = position; - } - public SurePetcarePetStatus getPetStatus() { return status; } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocation.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetActivity.java similarity index 53% rename from bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocation.java rename to bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetActivity.java index 42bbe3588816c..ed4234d740fd1 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocation.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetActivity.java @@ -14,71 +14,38 @@ import java.time.ZoneId; import java.time.ZonedDateTime; -import java.util.Arrays; import java.util.Date; -import org.eclipse.jdt.annotation.NonNull; +import com.google.gson.annotations.SerializedName; /** - * The {@link SurePetcarePetLocation} is the Java class used to represent the location of a pet. It's used to - * deserialize JSON API results. + * The {@link SurePetcarePetActivity} is the Java class used to represent the + * status of a pet. It's used to deserialize JSON API results. * * @author Rene Scherer - Initial contribution + * @author Holger Eisold - Added pet feeder status */ -public class SurePetcarePetLocation { +public class SurePetcarePetActivity { - // {"pet_id":70237,"tag_id":60126,"device_id":376236,"where":2,"since":"2019-09-11T13:09:07+00:00"} - - public enum PetLocation { - - UNKNONWN(-1, "Unknown"), - INSIDE(1, "Inside"), - OUTSIDE(2, "Outside"); - - private final Integer id; - private final String name; - - private PetLocation(int id, String name) { - this.id = id; - this.name = name; - } - - public Integer getId() { - return id; - } - - public String getName() { - return name; - } - - public static @NonNull PetLocation findByTypeId(final int id) { - return Arrays.stream(values()).filter(value -> value.id.equals(id)).findFirst().orElse(UNKNONWN); - } - } - - private Integer petId; + @SerializedName("tag_id") private Integer tagId; + @SerializedName("device_id") private Integer deviceId; + @SerializedName("user_id") private Integer userId; + @SerializedName("where") private Integer where; + @SerializedName("since") private Date since; - public SurePetcarePetLocation() { + public SurePetcarePetActivity() { } - public SurePetcarePetLocation(PetLocation location, Date since) { - this.where = location.getId(); + public SurePetcarePetActivity(Integer location, Date since) { + this.where = location; this.since = since; } - public Integer getPetId() { - return petId; - } - - public void setPetId(Integer petId) { - this.petId = petId; - } - public Integer getTagId() { return tagId; } @@ -87,14 +54,6 @@ public void setTagId(Integer tagId) { this.tagId = tagId; } - public Integer getDeviceId() { - return deviceId; - } - - public void setDeviceId(Integer deviceId) { - this.deviceId = deviceId; - } - public Integer getUserId() { return userId; } @@ -103,6 +62,14 @@ public void setUserId(Integer userId) { this.userId = userId; } + public Integer getDeviceId() { + return deviceId; + } + + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + public Integer getWhere() { return where; } @@ -119,11 +86,6 @@ public void setSince(Date since) { this.since = since; } - @Override - public String toString() { - return "Pet [id=" + petId + ", location=" + PetLocation.findByTypeId(where).getName() + "]"; - } - public ZonedDateTime getLocationChanged() { if (since != null) { return since.toInstant().atZone(ZoneId.systemDefault()).withNano(0); diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetFeeding.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetFeeding.java new file mode 100644 index 0000000000000..7379c8ad14d69 --- /dev/null +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetFeeding.java @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2010-2019 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.surepetcare.internal.data; + +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link SurePetcarePetFeeding} is the Java class used to represent the + * status of a pet. It's used to deserialize JSON API results. + * + * @author Rene Scherer - Initial contribution + * @author Holger Eisold - Added pet feeder status + */ +public class SurePetcarePetFeeding { + + @SerializedName("tag_id") + private Integer tagId; + @SerializedName("device_id") + private Integer deviceId; + @SerializedName("change") + private List feedChange = new ArrayList(); + @SerializedName("at") + private Date feedChangeAt; + + public Integer getTagId() { + return tagId; + } + + public void setTagId(Integer tagId) { + this.tagId = tagId; + } + + public Integer getDeviceId() { + return deviceId; + } + + public void setDeviceId(Integer deviceId) { + this.deviceId = deviceId; + } + + public List getFeedChange() { + return feedChange; + } + + public void setFeedChange(List feedChange) { + this.feedChange = feedChange; + } + + public Date getAt() { + return feedChangeAt; + } + + public void setAt(Date feedChangeAt) { + this.feedChangeAt = feedChangeAt; + } + + public ZonedDateTime getZonedFeedChangeAt() { + if (feedChangeAt != null) { + return feedChangeAt.toInstant().atZone(ZoneId.systemDefault()); + } else { + return null; + } + } +} diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetStatus.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetStatus.java index 9ef90b5b129ed..4b9ece8efbf85 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetStatus.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetStatus.java @@ -12,12 +12,6 @@ */ package org.openhab.binding.surepetcare.internal.data; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - import com.google.gson.annotations.SerializedName; /** @@ -29,139 +23,24 @@ */ public class SurePetcarePetStatus { - public class Activity { - - @SerializedName("tag_id") - private Integer tagId; - @SerializedName("device_id") - private Integer deviceId; - @SerializedName("user_id") - private Integer userId; - @SerializedName("where") - private Integer where; - @SerializedName("since") - private Date since; - - public Integer getTagId() { - return tagId; - } - - public void setTagId(Integer tagId) { - this.tagId = tagId; - } - - public Integer getUserId() { - return userId; - } - - public void setUserId(Integer userId) { - this.userId = userId; - } - - public Integer getDeviceId() { - return deviceId; - } - - public void setDeviceId(Integer deviceId) { - this.deviceId = deviceId; - } - - public Integer getWhere() { - return where; - } - - public void setWhere(Integer where) { - this.where = where; - } - - public Date getSince() { - return since; - } - - public void setSince(Date since) { - this.since = since; - } - - public ZonedDateTime getLocationChanged() { - if (since != null) { - return since.toInstant().atZone(ZoneId.systemDefault()).withNano(0); - } else { - return null; - } - } - - } - - public class Feeding { - - @SerializedName("tag_id") - private Integer tagId; - @SerializedName("device_id") - private Integer deviceId; - @SerializedName("change") - private List feedChange = new ArrayList(); - @SerializedName("at") - private Date feedChangeAt; - - public Integer getTagId() { - return tagId; - } - - public void setTagId(Integer tagId) { - this.tagId = tagId; - } - - public Integer getDeviceId() { - return deviceId; - } - - public void setDeviceId(Integer deviceId) { - this.deviceId = deviceId; - } - - public List getFeedChange() { - return feedChange; - } - - public void setFeedChange(List feedChange) { - this.feedChange = feedChange; - } - - public Date getAt() { - return feedChangeAt; - } - - public void setAt(Date feedChangeAt) { - this.feedChangeAt = feedChangeAt; - } - - public ZonedDateTime getZonedFeedChangeAt() { - if (feedChangeAt != null) { - return feedChangeAt.toInstant().atZone(ZoneId.systemDefault()); - } else { - return null; - } - } - } - @SerializedName("activity") - private Activity activity; + private SurePetcarePetActivity activity; @SerializedName("feeding") - private Feeding feeding; + private SurePetcarePetFeeding feeding; - public Activity getActivity() { + public SurePetcarePetActivity getActivity() { return activity; } - public void setActivity(Activity activity) { + public void setActivity(SurePetcarePetActivity activity) { this.activity = activity; } - public Feeding getFeeding() { + public SurePetcarePetFeeding getFeeding() { return feeding; } - public void setFeeding(Feeding feeding) { + public void setFeeding(SurePetcarePetFeeding feeding) { this.feeding = feeding; } } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/discovery/SurePetcareDiscoveryService.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/discovery/SurePetcareDiscoveryService.java index 4f9611b30fa45..27e5b1180a714 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/discovery/SurePetcareDiscoveryService.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/discovery/SurePetcareDiscoveryService.java @@ -47,8 +47,7 @@ public class SurePetcareDiscoveryService extends AbstractDiscoveryService { private final Logger logger = LoggerFactory.getLogger(SurePetcareDiscoveryService.class); - private static final Set SUPPORTED_THING_TYPES = Collections - .singleton(THING_TYPE_BRIDGE); + private static final Set SUPPORTED_THING_TYPES = Collections.singleton(THING_TYPE_BRIDGE); private static final int DISCOVER_TIMEOUT_SECONDS = 2; private static final int DISCOVERY_REFRESH_INTERVAL = 12 * 3600; // 12 hours @@ -145,8 +144,7 @@ private void retrieveTopologyFromSurePetcare() { } private void createHouseholdThing(SurePetcareHousehold household) { - ThingUID thingsUID = new ThingUID(THING_TYPE_HOUSEHOLD, bridgeUID, - household.getId().toString()); + ThingUID thingsUID = new ThingUID(THING_TYPE_HOUSEHOLD, bridgeUID, household.getId().toString()); Map properties = household.getThingProperties(); thingDiscovered(DiscoveryResultBuilder.create(thingsUID).withLabel(household.getName()) .withProperties(properties).withBridge(bridgeUID).build()); diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBaseObjectHandler.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBaseObjectHandler.java index 4dd77dd2d74da..cf4d53b220c56 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBaseObjectHandler.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBaseObjectHandler.java @@ -49,7 +49,7 @@ public void initialize() { @Override public void handleCommand(ChannelUID channelUID, Command command) { - logger.debug("DeviceHandler handleCommand called with command: {}", command.toString()); + logger.debug("BaseObjectHandler handleCommand called with command: {}", command.toString()); if (command instanceof RefreshType) { updateThing(); } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBridgeHandler.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBridgeHandler.java index 16aab1c3ed89a..23692c367f1eb 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBridgeHandler.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareBridgeHandler.java @@ -53,7 +53,7 @@ public class SurePetcareBridgeHandler extends BaseBridgeHandler { private SurePetcareAPIHelper petcareAPI; private @Nullable ScheduledFuture topologyPollingJob = null; - private @Nullable ScheduledFuture petLocationPollingJob = null; + private @Nullable ScheduledFuture petStatusPollingJob = null; public SurePetcareBridgeHandler(Bridge bridge, SurePetcareAPIHelper petcareAPI) { super(bridge); @@ -72,7 +72,7 @@ public void initialize() { logger.warn("Setting thing '{}' to OFFLINE: Parameter 'password' and 'username' must be configured.", getThing().getUID()); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, - "@text/offline.conf-error-missing-password"); + "@text/offline.conf-error-missing-username-or-password"); } else { String username = (String) config.get(USERNAME); String password = (String) config.get(PASSWORD); @@ -93,7 +93,7 @@ public void initialize() { try { long refreshIntervalTopology = ((BigDecimal) config.get(REFRESH_INTERVAL_TOPOLOGY)).longValueExact(); - long refreshIntervalLocation = ((BigDecimal) config.get(REFRESH_INTERVAL_LOCATION)).longValueExact(); + long refreshIntervalStatus = ((BigDecimal) config.get(REFRESH_INTERVAL_STATUS)).longValueExact(); if (topologyPollingJob == null || topologyPollingJob.isCancelled()) { topologyPollingJob = scheduler.scheduleWithFixedDelay(() -> { @@ -102,15 +102,15 @@ public void initialize() { }, refreshIntervalTopology, refreshIntervalTopology, TimeUnit.SECONDS); logger.debug("Bridge topology polling job every {} seconds", refreshIntervalTopology); } - if (petLocationPollingJob == null || petLocationPollingJob.isCancelled()) { - petLocationPollingJob = scheduler.scheduleWithFixedDelay(() -> { + if (petStatusPollingJob == null || petStatusPollingJob.isCancelled()) { + petStatusPollingJob = scheduler.scheduleWithFixedDelay(() -> { pollAndUpdatePetStatus(); - }, refreshIntervalLocation, refreshIntervalLocation, TimeUnit.SECONDS); - logger.debug("Bridge location polling job every {} seconds", refreshIntervalLocation); + }, refreshIntervalStatus, refreshIntervalStatus, TimeUnit.SECONDS); + logger.debug("Pet status polling job every {} seconds", refreshIntervalStatus); } } catch (ArithmeticException e) { logger.warn("Invalid settings for refresh intervals [{},{}]", config.get(REFRESH_INTERVAL_TOPOLOGY), - config.get(REFRESH_INTERVAL_LOCATION)); + config.get(REFRESH_INTERVAL_STATUS)); updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/offline.conf-error-invalid-refresh-intervals"); } @@ -126,9 +126,9 @@ public void dispose() { topologyPollingJob = null; logger.debug("Stopped pet background polling process"); } - if (petLocationPollingJob != null && !petLocationPollingJob.isCancelled()) { - petLocationPollingJob.cancel(true); - petLocationPollingJob = null; + if (petStatusPollingJob != null && !petStatusPollingJob.isCancelled()) { + petStatusPollingJob.cancel(true); + petStatusPollingJob = null; logger.debug("Stopped pet location background polling process"); } } @@ -176,10 +176,10 @@ private synchronized void pollAndUpdatePetStatus() { petcareAPI.updatePetStatus(); for (Thing th : ((Bridge) thing).getThings()) { if (th.getThingTypeUID().equals(THING_TYPE_PET)) { - logger.debug("updating pet location for: {}", th.getUID().getId()); + logger.debug("Updating pet status for: {}", th.getUID().getId()); ThingHandler handler = th.getHandler(); if (handler != null) { - ((SurePetcarePetHandler) handler).updatePetLocation(); + ((SurePetcarePetHandler) handler).updateThing(); } } } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareHouseholdHandler.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareHouseholdHandler.java index 68262d1e1493d..bb9e92aef0a82 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareHouseholdHandler.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcareHouseholdHandler.java @@ -21,6 +21,7 @@ import org.eclipse.smarthome.core.thing.Thing; import org.openhab.binding.surepetcare.internal.SurePetcareAPIHelper; import org.openhab.binding.surepetcare.internal.data.SurePetcareHousehold; +import org.openhab.binding.surepetcare.internal.data.SurePetcareHousehold.HouseholdUsers; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,6 +50,11 @@ protected void updateThing() { updateState(HOUSEHOLD_CHANNEL_TIMEZONE_ID, new DecimalType(household.getTimezoneId())); updateState(HOUSEHOLD_CHANNEL_CREATED_AT, new DateTimeType(household.getCreatedAtAsZonedDateTime())); updateState(HOUSEHOLD_CHANNEL_UPDATED_AT, new DateTimeType(household.getUpdatedAtAsZonedDateTime())); + int numUsers = household.getHouseholdUsers().size(); + for (int i = 0; (i < numUsers); i++) { + HouseholdUsers user = household.getHouseholdUsers().get(i); + updateState(HOUSEHOLD_CHANNEL_USER_NAME + (i + 1), new StringType(user.getUser().getUserName())); + } } else { logger.debug("Trying to update unknown household: {}", thing.getUID().getId()); } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcarePetHandler.java b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcarePetHandler.java index d62eaa991a84e..ce60080c67190 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcarePetHandler.java +++ b/bundles/org.openhab.binding.surepetcare/src/main/java/org/openhab/binding/surepetcare/internal/handler/SurePetcarePetHandler.java @@ -31,10 +31,10 @@ import org.openhab.binding.surepetcare.internal.SurePetcareAPIHelper; import org.openhab.binding.surepetcare.internal.SurePetcareApiException; import org.openhab.binding.surepetcare.internal.data.SurePetcareDevice; +import org.openhab.binding.surepetcare.internal.data.SurePetcareHousehold; import org.openhab.binding.surepetcare.internal.data.SurePetcarePet; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetLocation; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetStatus.Activity; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetStatus.Feeding; +import org.openhab.binding.surepetcare.internal.data.SurePetcarePetActivity; +import org.openhab.binding.surepetcare.internal.data.SurePetcarePetFeeding; import org.openhab.binding.surepetcare.internal.data.SurePetcareTag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,14 +56,14 @@ public SurePetcarePetHandler(Thing thing, SurePetcareAPIHelper petcareAPI) { @Override public void handleCommand(ChannelUID channelUID, Command command) { - logger.debug("DeviceHandler handleCommand called with command: {}", command.toString()); + logger.debug("PetHandler handleCommand called with command: {}", command.toString()); if (command instanceof RefreshType) { updateThing(); } else { switch (channelUID.getId()) { case PET_CHANNEL_LOCATION: - logger.debug("received location update command: {}", command.toFullString()); + logger.debug("Received location update command: {}", command.toFullString()); if (command instanceof StringType) { synchronized (petcareAPI) { SurePetcarePet pet = petcareAPI.getPet(thing.getUID().getId()); @@ -71,12 +71,12 @@ public void handleCommand(ChannelUID channelUID, Command command) { String newLocationIdStr = ((StringType) command).toString(); try { Integer newLocationId = Integer.valueOf(newLocationIdStr); - logger.debug("received new location: {}", newLocationId); + logger.debug("Received new location: {}", newLocationId); petcareAPI.setPetLocation(pet, newLocationId); updateState(PET_CHANNEL_LOCATION, - new StringType(pet.getLocation().getWhere().toString())); + new StringType(pet.getPetStatus().getActivity().getWhere().toString())); updateState(PET_CHANNEL_LOCATION_CHANGED, - new DateTimeType(pet.getLocation().getLocationChanged())); + new DateTimeType(pet.getPetStatus().getActivity().getLocationChanged())); } catch (NumberFormatException e) { logger.warn("Invalid location id: {}, ignoring command", newLocationIdStr); } catch (SurePetcareApiException e) { @@ -106,13 +106,19 @@ protected void updateThing() { if (pet.getComments() != null) { updateState(PET_CHANNEL_COMMENT, new StringType(pet.getComments())); } - updateState(PET_CHANNEL_GENDER, new StringType(pet.getGenderId().toString())); - updateState(PET_CHANNEL_BREED, new StringType(pet.getBreedId().toString())); - updateState(PET_CHANNEL_SPECIES, new StringType(pet.getSpeciesId().toString())); + if (pet.getGenderId() != null) { + updateState(PET_CHANNEL_GENDER, new StringType(pet.getGenderId().toString())); + } + if (pet.getBreedId() != null) { + updateState(PET_CHANNEL_BREED, new StringType(pet.getBreedId().toString())); + } + if (pet.getSpeciesId() != null) { + updateState(PET_CHANNEL_SPECIES, new StringType(pet.getSpeciesId().toString())); + } if (pet.getPhoto() != null) { updateState(PET_CHANNEL_PHOTO_URL, new StringType(pet.getPhoto().getLocation())); } - Activity loc = pet.getPetStatus().getActivity(); + SurePetcarePetActivity loc = pet.getPetStatus().getActivity(); if (loc != null) { updateState(PET_CHANNEL_LOCATION, new StringType(loc.getWhere().toString())); if (loc.getLocationChanged() != null) { @@ -132,7 +138,22 @@ protected void updateThing() { updateState(PET_CHANNEL_TAG_IDENTIFIER, new StringType(tag.getTag())); } } - Feeding feeding = pet.getPetStatus().getFeeding(); + if (pet.getPetStatus().getActivity().getDeviceId() != null) { + SurePetcareDevice device = petcareAPI + .getDevice(pet.getPetStatus().getActivity().getDeviceId().toString()); + updateState(PET_CHANNEL_LOCATION_CHANGED_THROUGH, new StringType(device.getName())); + } else if (pet.getPetStatus().getActivity().getUserId() != null) { + SurePetcareHousehold user = petcareAPI.getHousehold(pet.getHouseholdId().toString()); + int numUsers = user.getHouseholdUsers().size(); + for (int i = 0; (i < numUsers); i++) { + if (pet.getPetStatus().getActivity().getUserId() + .equals(user.getHouseholdUsers().get(i).getUser().getUserId())) { + updateState(PET_CHANNEL_LOCATION_CHANGED_THROUGH, + new StringType(user.getHouseholdUsers().get(i).getUser().getUserName().toString())); + } + } + } + SurePetcarePetFeeding feeding = pet.getPetStatus().getFeeding(); if (feeding != null) { SurePetcareDevice device = petcareAPI.getDevice(feeding.getDeviceId().toString()); if (device != null) { @@ -162,18 +183,4 @@ protected void updateThing() { } } - protected void updatePetLocation() { - synchronized (petcareAPI) { - SurePetcarePet pet = petcareAPI.getPet(thing.getUID().getId()); - if (pet != null) { - SurePetcarePetLocation loc = pet.getLocation(); - if (loc != null) { - updateState(PET_CHANNEL_LOCATION, new StringType(loc.getWhere().toString())); - if (loc.getLocationChanged() != null) { - updateState(PET_CHANNEL_LOCATION_CHANGED, new DateTimeType(loc.getLocationChanged())); - } - } - } - } - } } diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/binding/binding.xml b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/binding/binding.xml index d7b32fc714df5..501bd7b6b8d97 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/binding/binding.xml +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/binding/binding.xml @@ -1,11 +1,8 @@ - - + + Sure PetCare Binding This binding interacts with the Sure Petcare Connect range of cat flaps and feeders Rene Scherer - + \ No newline at end of file diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare.properties b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare.properties index 9e00e53908b06..aeeaad1b8703f 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare.properties +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare.properties @@ -12,8 +12,8 @@ thing-type.config.surepetcare.bridge.username.description = The username to acce thing-type.config.surepetcare.bridge.password.label = Sure Petcare Password thing-type.config.surepetcare.bridge.password.description = The password to access the Sure Petcare API. -thing-type.config.surepetcare.bridge.refresh_interval_location.label = Refresh Interval Location -thing-type.config.surepetcare.bridge.refresh_interval_location.description = Query interval (in secs) for pet locations. (min. 300 / default 36000). +thing-type.config.surepetcare.bridge.refresh_interval_status.label = Refresh Interval Pet Status +thing-type.config.surepetcare.bridge.refresh_interval_status.description = Query interval (in secs) for pet status. (min. 300 / default 36000). thing-type.config.surepetcare.bridge.refresh_interval_topology.label = Refresh Interval Topology thing-type.config.surepetcare.bridge.refresh_interval_topology.description = Query interval (in secs) for device topology. (min 300 / default 300). @@ -272,6 +272,6 @@ channel-type.surepetcare.bowlsTrainingModeType.state.option.3 = Half closed channel-type.surepetcare.bowlsTrainingModeType.state.option.4 = Almost closed # Thing status description -offline.comm-error-invalid-username-or-password = Invalid username or password. -offline.comm-error-missing-username-or-password = Missing username or password. +offline.conf-error-invalid-refresh-intervals = Invalid refresh interval. +offline.conf-error-missing-username-or-password = Missing username or password. diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare_de.properties b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare_de.properties index 8199ac286594f..436f92b326807 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare_de.properties +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/i18n/surepetcare_de.properties @@ -12,8 +12,8 @@ thing-type.config.surepetcare.bridge.username.description = Sure Petcare Benutze thing-type.config.surepetcare.bridge.password.label = Sure Petcare Passwort thing-type.config.surepetcare.bridge.password.description = Sure Petcare Passwort. -thing-type.config.surepetcare.bridge.refresh_interval_location.label = Abfrageintervall Standort -thing-type.config.surepetcare.bridge.refresh_interval_location.description = Intervall zur Abfrage des Haustier Standorts (in Sekunden) (mind. 300 / standard 36000). +thing-type.config.surepetcare.bridge.refresh_interval_status.label = Abfrageintervall Haustier Status +thing-type.config.surepetcare.bridge.refresh_interval_status.description = Intervall zur Abfrage des Haustier Status (in Sekunden) (mind. 300 / standard 36000). thing-type.config.surepetcare.bridge.refresh_interval_topology.label = Abfrageintervall Topology thing-type.config.surepetcare.bridge.refresh_interval_topology.description = Intervall zur Abfrage der Geräte und Haustier Daten (in Sekunden) (mind. 300 / standard 300). @@ -272,6 +272,6 @@ channel-type.surepetcare.bowlsTrainingModeType.state.option.3 = Halb geschlossen channel-type.surepetcare.bowlsTrainingModeType.state.option.4 = Fast geschlossen # Thing status description -offline.comm-error-invalid-username-or-password = Invalid username or password. -offline.comm-error-missing-username-or-password = Missing username or password. +offline.conf-error-invalid-refresh-intervals = Ungültiger Aktualisierungs-Intervall. +offline.conf-error-missing-username-or-password = Benutzername oder Passowrt fehlt. diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/bridge.xml b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/bridge.xml index 14506db39c44e..8b9ba48086e40 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/bridge.xml +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/bridge.xml @@ -1,9 +1,6 @@ - + - + @@ -31,9 +28,9 @@ Query interval (in secs) for device topology 36000 - - - Query interval (in secs) for pet locations + + + Query interval (in secs) for pet status 300 @@ -48,4 +45,4 @@ - + \ No newline at end of file diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/things.xml b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/things.xml index dd54758f43deb..e4bfeffe2961b 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/things.xml +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/ESH-INF/thing/things.xml @@ -1,9 +1,6 @@ - + - + @@ -21,6 +18,11 @@ + + + + + @@ -145,6 +147,7 @@ + @@ -170,12 +173,19 @@ - - String - - Comments about the thing - - + + String + + The username of the thing + + + + + String + + Comments about the thing + + Number @@ -326,6 +336,13 @@ + + String + + Shows the device name or username of the last location change. + + + String @@ -618,4 +635,4 @@ - + \ No newline at end of file diff --git a/bundles/org.openhab.binding.surepetcare/src/main/resources/config/things/surepetcare.things b/bundles/org.openhab.binding.surepetcare/src/main/resources/config/things/surepetcare.things index 7b1714af94e7e..5003c79445ece 100644 --- a/bundles/org.openhab.binding.surepetcare/src/main/resources/config/things/surepetcare.things +++ b/bundles/org.openhab.binding.surepetcare/src/main/resources/config/things/surepetcare.things @@ -1,9 +1,8 @@ -Bridge surepetcare:bridge:bridge1 "Demo API Bridge" [ username="", password="", refresh_interval_topology=36000, refresh_interval_location=300 ] +Bridge surepetcare:bridge:bridge1 "Demo API Bridge" @ "SurePetcare" [ username="", password="", refresh_interval_topology=36000, refresh_interval_status=300 ] { - Thing household 45237 "My Household" - Thing hubDevice 439862 "My SurePetcare Hub" - Thing flapDevice 316524 "My Backdoor Cat Flap" - Thing pet 60487 "My Cat" + Thing household 45237 "My Household" @ "SurePetcare" + Thing hubDevice 439862 "My SurePetcare Hub" @ "SurePetcare Devices" + Thing flapDevice 316524 "My Backdoor Cat Flap" @ "SurePetcare Devices" + Thing feederDevice 123456 "My Pet Feeder" @ "SurePetcare Devices" + Thing pet 60487 "My Cat" @ "SurePetcare Pets" } - - diff --git a/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocationTest.java b/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocationTest.java index 3c0a0a37c1c51..d87a195175658 100644 --- a/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocationTest.java +++ b/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetLocationTest.java @@ -8,7 +8,6 @@ import org.junit.Test; import org.openhab.binding.surepetcare.internal.GsonColonDateTypeAdapter; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetLocation.PetLocation; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; @@ -24,13 +23,12 @@ public class SurePetcarePetLocationTest { @Test public void testJsonDeserialize() throws ParseException { - String testReponse = "{\"pet_id\":70237,\"tag_id\":60126,\"device_id\":376236,\"where\":2,\"since\":\"2019-09-11T13:09:07+00:00\"}"; - SurePetcarePetLocation response = gson.fromJson(testReponse, SurePetcarePetLocation.class); + String testReponse = "{\"tag_id\":60126,\"device_id\":376236,\"where\":2,\"since\":\"2019-09-11T13:09:07+00:00\"}"; + SurePetcarePetActivity response = gson.fromJson(testReponse, SurePetcarePetActivity.class); - assertEquals(new Integer(70237), response.getPetId()); assertEquals(new Integer(60126), response.getTagId()); assertEquals(new Integer(376236), response.getDeviceId()); - assertEquals(PetLocation.OUTSIDE.getId(), response.getWhere()); + assertEquals(new Integer(2), response.getWhere()); Date sinceDate = simpleDateFormat.parse("2019-09-11T13:09:07+0000"); assertEquals(sinceDate, response.getSince()); } @@ -40,9 +38,9 @@ public void testJsonFullSerialize() throws ParseException { Date since = simpleDateFormat.parse("2019-09-11T13:09:07+0000"); - SurePetcarePetLocation location = new SurePetcarePetLocation(PetLocation.OUTSIDE, since); + SurePetcarePetActivity location = new SurePetcarePetActivity(2, since); - String json = gson.toJson(location, SurePetcarePetLocation.class); + String json = gson.toJson(location, SurePetcarePetActivity.class); assertEquals("{\"where\":2,\"since\":\"2019-09-11T13:09:07+00:00\"}", json); } diff --git a/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetTest.java b/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetTest.java index 42eedfd84069d..628961197827e 100644 --- a/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetTest.java +++ b/bundles/org.openhab.binding.surepetcare/src/test/java/org/openhab/binding/surepetcare/internal/data/SurePetcarePetTest.java @@ -9,7 +9,6 @@ import org.junit.Test; import org.openhab.binding.surepetcare.internal.GsonColonDateTypeAdapter; -import org.openhab.binding.surepetcare.internal.data.SurePetcarePetLocation.PetLocation; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; @@ -96,9 +95,9 @@ public void testJsonDeserialize() throws ParseException { assertEquals(SurePetcarePet.PetSpecies.CAT.getId(), response.getSpeciesId()); assertEquals(new Integer(382), response.getBreedId()); - assertEquals(PetLocation.INSIDE.getId(), response.getLocation().getWhere()); + assertEquals(new Integer(1), response.getPetStatus().getActivity().getWhere()); Date sinceDate = simpleDateFormat.parse("2019-10-03T10:23:37+0000"); - assertEquals(sinceDate, response.getLocation().getSince()); + assertEquals(sinceDate, response.getPetStatus().getActivity().getSince()); } }