From: Mark Hilbush Date: Sat, 18 Feb 2023 15:26:57 +0000 (-0500) Subject: [sleepiq] Rework cloud API and other enhancements (#14180) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=253b25631f65e41154d1f635596439acfa0ef119;p=openhab-addons.git [sleepiq] Rework cloud API and other enhancements (#14180) Signed-off-by: Mark Hilbush --- diff --git a/CODEOWNERS b/CODEOWNERS index 0a9c9c64ba..34ff5b5d4b 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -301,7 +301,7 @@ /bundles/org.openhab.binding.siemensrds/ @andrewfg /bundles/org.openhab.binding.silvercrestwifisocket/ @jmvaz /bundles/org.openhab.binding.sinope/ @chaton78 -/bundles/org.openhab.binding.sleepiq/ @syphr42 +/bundles/org.openhab.binding.sleepiq/ @syphr42 @mhilbush /bundles/org.openhab.binding.smaenergymeter/ @monnimeter /bundles/org.openhab.binding.smartmeter/ @msteigenberger /bundles/org.openhab.binding.smartthings/ @BobRak diff --git a/bundles/org.openhab.binding.sleepiq/README.md b/bundles/org.openhab.binding.sleepiq/README.md index 4e47a9f47a..d56c2a618a 100644 --- a/bundles/org.openhab.binding.sleepiq/README.md +++ b/bundles/org.openhab.binding.sleepiq/README.md @@ -31,13 +31,11 @@ The binding requires no special configuration. The bridge requires a username and a password. Optionally, you can also specify a polling interval. -To enable verbose logging of HTTP requests and responses regarding the cloud service, enable DEBUG level logging on ```SleepIQCloudHandler```. - | Configuration Parameter | Type | Description | Default | |-------------------------|---------|--------------------------------------------------------|---------| | username | text | Username of a registered SleepIQ account owner | | | password | text | Password of a registered SleepIQ account owner | | -| pollingInterval | integer | Seconds between fetching values from the cloud service | 60 | +| pollingInterval | integer | Seconds between fetching values from the cloud service | 120 | ### Dual-Chamber Bed (Thing ID: "dualBed") @@ -50,7 +48,7 @@ Each bed requires a bed ID as defined by the SleepIQ service. ### Sample Thing Configuration ```java -Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", pollingInterval=60, logging=false ] +Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", pollingInterval=120 ] { Thing dualBed master [ bedId="-9999999999999999999" ] Thing dualBed guest [ bedId="-8888888888888888888" ] @@ -68,33 +66,65 @@ Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", polli ### Chamber Channel Group -All channels within this group are read-only. - -| Channel ID | Item Type | Description | -|----------------------|-----------|---------------------------------------------------------------------------------------------------------------------| -| inBed | Switch | The presence of a person or object on the chamber | -| sleepNumber | Number | The Sleep Number setting of the chamber | -| pressure | Number | The current pressure inside the chamber | -| lastLink | String | The amount of time that has passed since a connection was made from the chamber to the cloud service (D d HH:MM:SS) | -| alertId | Number | Identifier for an alert condition with the chamber | -| alertDetailedMessage | String | A detailed message describing an alert condition with the chamber | +All channels within this group are read-only, except for the sleepNumber and privacyMode channels. + +| Channel ID | Item Type | Description | +|-----------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------| +| inBed | Switch | The presence of a person or object on the chamber | +| sleepNumber | Number | The Sleep Number setting of the chamber. Set the sleep number of the chamber by sending a command to the sleepNumber channel with a value between 5 and 100. The value must be a multiple of 5 | + +| sleepGoalMinutes | Number:Time | The person's sleep goal in minutes | +| pressure | Number | The current pressure inside the chamber | +| privacyMode | Switch | Enable or disable privacy mode | +| lastLink | String | The amount of time that has passed since a connection was made from the chamber to the cloud service (D d HH:MM:SS) | +| alertId | Number | Identifier for an alert condition with the chamber | +| alertDetailedMessage | String | A detailed message describing an alert condition with the chamber | +| todaySleepIQ | Number | The Sleep IQ score for the current day | +| todayAverageHeartRate | Number | The average heart rate for the current day | +| todayAverageRespirationRate | Number | The average respiration rate for the current day | +| todayMessage | String | A description of the sleep quality for the current day | +| todaySleepDurationSeconds | Number:Time | The duration of sleep for the current day | +| monthlySleepIQ | Number | The average Sleep IQ score for the current month | +| monthlyAverageHeartRate | Number | The average heart rate for the current month | +| monthlyAverageRespirationRate | Number | The average respiration rate for the current month | ## Items Here is a sample item configuration: ```java -Switch MasterBedroom_SleepIQ_InBed_Alice "In Bed [%s]" { channel="sleepiq:dualBed:1:master:left#inBed" } -Number MasterBedroom_SleepIQ_SleepNumber_Alice "Sleep Number [%s]" { channel="sleepiq:dualBed:1:master:left#sleepNumber" } -Number MasterBedroom_SleepIQ_Pressure_Alice "Pressure [%s]" { channel="sleepiq:dualBed:1:master:left#pressure" } -String MasterBedroom_SleepIQ_LastLink_Alice "Last Update [%s]" { channel="sleepiq:dualBed:1:master:left#lastLink" } -Number MasterBedroom_SleepIQ_AlertId_Alice "Alert ID [%s]" { channel="sleepiq:dualBed:1:master:left#alertId" } -String MasterBedroom_SleepIQ_AlertMessage_Alice "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:left#alertDetailedMessage" } - -Switch MasterBedroom_SleepIQ_InBed_Bob "In Bed [%s]" { channel="sleepiq:dualBed:1:master:right#inBed" } -Number MasterBedroom_SleepIQ_SleepNumber_Bob "Sleep Number [%s]" { channel="sleepiq:dualBed:1:master:right#sleepNumber" } -Number MasterBedroom_SleepIQ_Pressure_Bob "Pressure [%s]" { channel="sleepiq:dualBed:1:master:right#pressure" } -String MasterBedroom_SleepIQ_LastLink_Bob "Last Update [%s]" { channel="sleepiq:dualBed:1:master:right#lastLink" } -Number MasterBedroom_SleepIQ_AlertId_Bob "Alert ID [%s]" { channel="sleepiq:dualBed:1:master:right#alertId" } -String MasterBedroom_SleepIQ_AlertMessage_Bob "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:right#alertDetailedMessage" } +Switch MasterBR_SleepIQ_InBed_Alice "In Bed [%s]" { channel="sleepiq:dualBed:1:master:left#inBed" } +Number MasterBR_SleepIQ_SleepNumber_Alice "Sleep Number [%s]" { channel="sleepiq:dualBed:1:master:left#sleepNumber" } +Number:Time MasterBR_SleepIQ_SleepGoal_Alice "Sleep Goal [%d min]" { channel="sleepiq:dualBed:1:master:left#sleepGoalMinutes" +Number MasterBR_SleepIQ_Pressure_Alice "Pressure [%s]" { channel="sleepiq:dualBed:1:master:left#pressure" } +Switch MasterBR_SleepIQ_PrivacyMode_Alice "Privacy Mode [%s]" { channel="sleepiq:dualBed:1:master:left#privacyMode" } +String MasterBR_SleepIQ_LastLink_Alice "Last Update [%s]" { channel="sleepiq:dualBed:1:master:left#lastLink" } +Number MasterBR_SleepIQ_AlertId_Alice "Alert ID [%s]" { channel="sleepiq:dualBed:1:master:left#alertId" } +String MasterBR_SleepIQ_AlertMessage_Alice "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:left#alertDetailedMessage" } +Number MasterBR_SleepIQ_DailySleepIQ_Alice "Daily Sleep IQ [%.0f]" { channel="sleepiq:dualBed:1:master:left#todaySleepIQ" } +Number MasterBR_SleepIQ_DailyHeartRate_Alice "Daily Heart Rate [%.0f]" { channel="sleepiq:dualBed:1:master:left#todayAverageHeartRate" } +Number MasterBR_SleepIQ_DailyRespRate_Alice "Daily Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:left#todayAverageRespirationRate"} +String MasterBR_SleepIQ_DailyMessage_Alice "Daily Message [%s]" { channel="sleepiq:dualBed:1:master:left#todayMessage"} +Number MasterBR_SleepIQ_DailyDuration_Alice "Daily Sleep Duration [%.0f]" { channel="sleepiq:dualBed:1:master:left#todaySleepDurationSeconds"} +Number:Time MasterBR_SleepIQ_MonthlySleepIQ_Alice "Monthly Sleep IQ [%d s]" { channel="sleepiq:dualBed:1:master:left#monthlySleepIQ"} +Number MasterBR_SleepIQ_MonthlyHeartRate_Alice "Monthly Heart Rate [%.0f]" { channel="sleepiq:dualBed:1:master:left#monthlyAverageHeartRate"} +Number MasterBR_SleepIQ_MonthlyRespRate_Alice "Monthly Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:left#monthlyAverageRespirationRate"} + + +Switch MasterBR_SleepIQ_InBed_Bob "In Bed [%s]" { channel="sleepiq:dualBed:1:master:right#inBed" } +Number MasterBR_SleepIQ_SleepNumber_Bob "Sleep Number [%s]" { channel="sleepiq:dualBed:1:master:right#sleepNumber" } +Number MasterBR_SleepIQ_SleepGoal_Alice "Sleep Goal [%d min]" { channel="sleepiq:dualBed:1:master:left#sleepGoalMinutes" +Number:Time MasterBR_SleepIQ_Pressure_Bob "Pressure [%s]" { channel="sleepiq:dualBed:1:master:right#pressure" } +Switch MasterBR_SleepIQ_PrivacyMode_Bob "Privacy Mode [%s]" { channel="sleepiq:dualBed:1:master:right#privacyMode" } +String MasterBR_SleepIQ_LastLink_Bob "Last Update [%s]" { channel="sleepiq:dualBed:1:master:right#lastLink" } +Number MasterBR_SleepIQ_AlertId_Bob "Alert ID [%s]" { channel="sleepiq:dualBed:1:master:right#alertId" } +String MasterBR_SleepIQ_AlertMessage_Bob "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:right#alertDetailedMessage" } +Number MasterBR_SleepIQ_DailySleepIQ_Bob "Daily Sleep IQ [%.0f]" { channel="sleepiq:dualBed:1:master:right#todaySleepIQ" } +Number MasterBR_SleepIQ_DailyHeartRate_Bob "Daily Heart Rate [%.0f]" { channel="sleepiq:dualBed:1:master:right#todayAverageHeartRate" } +Number MasterBR_SleepIQ_DailyRespRate_Bob "Daily Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:right#todayAverageRespirationRate"} +String MasterBR_SleepIQ_DailyMessage_Bob "Daily Message [%s]" { channel="sleepiq:dualBed:1:master:right#todayMessage"} +Number:Time MasterBR_SleepIQ_DailyDuration_Bob "Daily Sleep Duration [%d s]" { channel="sleepiq:dualBed:1:master:right#todaySleepDurationSeconds"} +Number MasterBR_SleepIQ_MonthlySleepIQ_Bob "Monthly Sleep IQ [%.0f]" { channel="sleepiq:dualBed:1:master:right#monthlySleepIQ"} +Number MasterBR_SleepIQ_MonthlyHeartRate_Bob "Monthly Heart Rate [%.0f]" { channel="sleepiq:dualBed:1:master:right#monthlyAverageHeartRate"} +Number MasterBR_SleepIQ_MonthlyRespRate_Bob "Monthly Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:right#monthlyAverageRespirationRate"} ``` diff --git a/bundles/org.openhab.binding.sleepiq/pom.xml b/bundles/org.openhab.binding.sleepiq/pom.xml index 754bf4078a..842ada6428 100644 --- a/bundles/org.openhab.binding.sleepiq/pom.xml +++ b/bundles/org.openhab.binding.sleepiq/pom.xml @@ -14,51 +14,4 @@ openHAB Add-ons :: Bundles :: SleepIQ Binding - - provider-gson - - - - - junit - junit - 4.12 - test - - - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - - add-source - - generate-sources - - - src/3rdparty/java - - - - - add-test-source - generate-sources - - add-test-source - - - - src/3rdparty/test - - - - - - - - diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java deleted file mode 100644 index 3eba856849..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import org.openhab.binding.sleepiq.api.model.Failure; - -public class BedNotFoundException extends SleepIQException -{ - private static final long serialVersionUID = 1L; - - public BedNotFoundException(Failure failure) - { - super(failure); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java deleted file mode 100644 index cb0fd28ba4..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import java.net.URI; -import java.util.logging.Level; - -/** - * This class represents configuration parameters for using {@link SleepIQ}. - * - * @author Gregory Moyer - */ -public class Configuration -{ - private String username; - private String password; - - private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com/rest"); - - private boolean logging = false; - - /** - * Get the username on the account. - * - * @return the username - */ - public String getUsername() - { - return username; - } - - /** - * Set the username on the account. This should be the username used to - * register with SleepIQ. - * - * @param username - * the value to set - */ - public void setUsername(String username) - { - this.username = username; - } - - /** - * Set the username on the account. This should be the username used to - * register with SleepIQ. - * - * @param username - * the value to set - * @return this configuration instance - */ - public Configuration withUsername(String username) - { - setUsername(username); - return this; - } - - /** - * Get the password on the account. - * - * @return the password - */ - public String getPassword() - { - return password; - } - - /** - * Set the password on the account. This should be the password used to - * register with SleepIQ. - * - * @param password - * the value to set - */ - public void setPassword(String password) - { - this.password = password; - } - - /** - * Set the password on the account. This should be the password used to - * register with SleepIQ. - * - * @param password - * the value to set - * @return this configuration instance - */ - public Configuration withPassword(String password) - { - setPassword(password); - return this; - } - - /** - * Get the base URI of the SleepIQ cloud service. - * - * @return the base URI - */ - public URI getBaseUri() - { - return baseUri; - } - - /** - * Set the base URI of the SleepIQ cloud service. It is unlikely that this - * will need to be changed from its default value. - * - * @param baseUri - * the value to set - */ - public void setBaseUri(URI baseUri) - { - this.baseUri = baseUri; - } - - /** - * Set the base URI of the SleepIQ cloud service. It is unlikely that this - * will need to be changed from its default value. - * - * @param baseUri - * the value to set - * @return this configuration instance - */ - public Configuration withBaseUri(URI baseUri) - { - setBaseUri(baseUri); - return this; - } - - /** - * Get the logging flag. - * - * @return the logging flag - */ - public boolean isLogging() - { - return logging; - } - - /** - * Set the logging flag. When this is set to true, all requests - * and responses will be logged at the {@link Level#INFO} level. This - * includes usernames and passwords! - * - * @param logging - * the value to set - */ - public void setLogging(boolean logging) - { - this.logging = logging; - } - - /** - * Set the logging flag. When this is set to true, all requests - * and responses will be logged at the {@link Level#INFO} level. This - * includes usernames and passwords! - * - * @param logging - * the value to set - * @return this configuration instance - */ - public Configuration withLogging(boolean logging) - { - setLogging(logging); - return this; - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java deleted file mode 100644 index 6480ae4ffd..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import org.openhab.binding.sleepiq.api.model.Failure; - -public class LoginException extends SleepIQException -{ - private static final long serialVersionUID = 1L; - - public LoginException(Failure failure) - { - super(failure); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java deleted file mode 100644 index 5785b24f79..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import java.util.List; - -import javax.ws.rs.client.ClientBuilder; - -import org.openhab.binding.sleepiq.api.impl.SleepIQImpl; -import org.openhab.binding.sleepiq.api.model.Bed; -import org.openhab.binding.sleepiq.api.model.FamilyStatus; -import org.openhab.binding.sleepiq.api.model.LoginInfo; -import org.openhab.binding.sleepiq.api.model.PauseMode; -import org.openhab.binding.sleepiq.api.model.Sleeper; - -/** - * This interface is the main API to access the SleepIQ system. - * - * @author Gregory Moyer - */ -public interface SleepIQ { - /** - * Login to the {@link Configuration configured} account. This method is not - * required to be called before other methods because all methods must - * ensure login before acting. However, when the only desired action is to - * login and not retrieve other data, this method is the most efficient - * option. - * - * @return basic information about the logged in user - * @throws UnauthorizedException - * if the credentials provided are not valid - * @throws LoginException - * if the login request fails for any reason other than bad - * credentials (including missing credentials) - */ - public LoginInfo login() throws LoginException; - - /** - * Get a list of beds connected to the account. - * - * @return the list of beds - */ - public List getBeds(); - - /** - * Get a list of people registered to this account for beds or bed positions - * (left or right side). - * - * @return the list of sleepers - */ - public List getSleepers(); - - /** - * Get the status of all beds and all air chambers registered to this - * account. - * - * @return the complete status of beds on the account - */ - public FamilyStatus getFamilyStatus(); - - /** - * Get the status of "pause mode" (disabling SleepIQ data upload) for a - * specific bed. A bed in pause mode will send no information to the SleepIQ - * cloud services. For example, if a sleeper is in bed and disables SleepIQ - * (enables pause mode), the service will continue to report that the bed is - * occupied even after the sleeper exits the bed until pause mode is - * disabled. - * - * @param bedId - * the unique identifier of the bed to query - * @return the status of pause mode for the specified bed - * @throws BedNotFoundException - * if the bed identifier was not found on the account - */ - public PauseMode getPauseMode(String bedId) throws BedNotFoundException; - - /** - * Create a default implementation instance of this interface. Each call to - * this method will create a new object. - * - * @param config - * the configuration to use for the new instance - * @return a concrete implementation of this interface - */ - public static SleepIQ create(Configuration config, ClientBuilder clientBuilder) { - return new SleepIQImpl(config, clientBuilder); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java deleted file mode 100644 index 55935c1f7d..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import org.openhab.binding.sleepiq.api.model.Failure; - -public class SleepIQException extends Exception -{ - private static final long serialVersionUID = 1L; - - private final Failure failure; - - public SleepIQException(Failure failure) - { - super(failure.getError().getMessage()); - this.failure = failure; - } - - public Failure getFailure() - { - return failure; - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java deleted file mode 100644 index 5a809005fa..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api; - -import org.openhab.binding.sleepiq.api.model.Failure; - -public class UnauthorizedException extends LoginException -{ - private static final long serialVersionUID = 1L; - - public UnauthorizedException(Failure failure) - { - super(failure); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java deleted file mode 100644 index 5ce38e5ef3..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright (c) 2011-2015 Oracle and/or its affiliates. All rights reserved. - * - * The contents of this file are subject to the terms of either the GNU - * General Public License Version 2 only ("GPL") or the Common Development - * and Distribution License("CDDL") (collectively, the "License"). You - * may not use this file except in compliance with the License. You can - * obtain a copy of the License at - * http://glassfish.java.net/public/CDDL+GPL_1_1.html - * or packager/legal/LICENSE.txt. See the License for the specific - * language governing permissions and limitations under the License. - * - * When distributing the software, include this License Header Notice in each - * file and include the License file at packager/legal/LICENSE.txt. - * - * GPL Classpath Exception: - * Oracle designates this particular file as subject to the "Classpath" - * exception as provided by Oracle in the GPL Version 2 section of the License - * file that accompanied this code. - * - * Modifications: - * If applicable, add the following below the License Header, with the fields - * enclosed by brackets [] replaced by your own identifying information: - * "Portions Copyright [year] [name of copyright owner]" - * - * Contributor(s): - * If you wish your version of this file to be governed by only the CDDL or - * only the GPL Version 2, indicate your decision by adding "[Contributor] - * elects to include this software in this distribution under the [CDDL or GPL - * Version 2] license." If you don't indicate a single choice of license, a - * recipient has the option to distribute your version of this file under - * either the CDDL, the GPL Version 2 or to extend the choice of license to - * its licensees as provided above. However, if you add GPL Version 2 code - * and therefore, elected the GPL Version 2 license, then the option applies - * only if the new code is made subject to such option by the copyright - * holder. - */ -package org.openhab.binding.sleepiq.api.filter; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.nio.charset.Charset; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Logger; - -import javax.annotation.Priority; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.ClientResponseContext; -import javax.ws.rs.client.ClientResponseFilter; -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.container.PreMatching; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.WriterInterceptor; -import javax.ws.rs.ext.WriterInterceptorContext; - -/** - * Universal logging filter. - *

- * Can be used on client or server side. Has the highest priority. - * - * @author Pavel Bucek (pavel.bucek at oracle.com) - * @author Martin Matula - */ -@PreMatching -@Priority(Integer.MIN_VALUE) -public final class LoggingFilter implements ContainerRequestFilter, ClientRequestFilter, ContainerResponseFilter, - ClientResponseFilter, WriterInterceptor { - - public static final Charset UTF8 = Charset.forName("UTF-8"); - - private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName()); - private static final String NOTIFICATION_PREFIX = "* "; - private static final String REQUEST_PREFIX = "> "; - private static final String RESPONSE_PREFIX = "< "; - private static final String ENTITY_LOGGER_PROPERTY = LoggingFilter.class.getName() + ".entityLogger"; - private static final String LOGGING_ID_PROPERTY = LoggingFilter.class.getName() + ".id"; - - private static final Comparator>> COMPARATOR = new Comparator>>() { - - @Override - public int compare(final Map.Entry> o1, final Map.Entry> o2) { - return o1.getKey().compareToIgnoreCase(o2.getKey()); - } - }; - - private static final int DEFAULT_MAX_ENTITY_SIZE = 8 * 1024; - - // - private final Logger logger; - private final AtomicLong _id = new AtomicLong(0); - private final boolean printEntity; - private final int maxEntitySize; - - /** - * Create a logging filter logging the request and response to a default JDK - * logger, named as the fully qualified class name of this class. Entity - * logging is turned off by default. - */ - public LoggingFilter() { - this(LOGGER, false); - } - - /** - * Create a logging filter with custom logger and custom settings of entity - * logging. - * - * @param logger the logger to log requests and responses. - * @param printEntity if true, entity will be logged as well up to the default maxEntitySize, which is 8KB - */ - public LoggingFilter(final Logger logger, final boolean printEntity) { - this.logger = logger; - this.printEntity = printEntity; - this.maxEntitySize = DEFAULT_MAX_ENTITY_SIZE; - } - - /** - * Creates a logging filter with custom logger and entity logging turned on, but potentially limiting the size - * of entity to be buffered and logged. - * - * @param logger the logger to log requests and responses. - * @param maxEntitySize maximum number of entity bytes to be logged (and buffered) - if the entity is larger, - * logging filter will print (and buffer in memory) only the specified number of bytes - * and print "...more..." string at the end. Negative values are interpreted as zero. - */ - public LoggingFilter(final Logger logger, final int maxEntitySize) { - this.logger = logger; - this.printEntity = true; - this.maxEntitySize = Math.max(0, maxEntitySize); - } - - private void log(final StringBuilder b) { - if (logger != null) { - logger.info(b.toString()); - } - } - - private StringBuilder prefixId(final StringBuilder b, final long id) { - b.append(Long.toString(id)).append(" "); - return b; - } - - private void printRequestLine(final StringBuilder b, final String note, final long id, final String method, - final URI uri) { - prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") - .append(Thread.currentThread().getName()).append("\n"); - prefixId(b, id).append(REQUEST_PREFIX).append(method).append(" ").append(uri.toASCIIString()).append("\n"); - } - - private void printResponseLine(final StringBuilder b, final String note, final long id, final int status) { - prefixId(b, id).append(NOTIFICATION_PREFIX).append(note).append(" on thread ") - .append(Thread.currentThread().getName()).append("\n"); - prefixId(b, id).append(RESPONSE_PREFIX).append(Integer.toString(status)).append("\n"); - } - - private void printPrefixedHeaders(final StringBuilder b, final long id, final String prefix, - final MultivaluedMap headers) { - for (final Map.Entry> headerEntry : getSortedHeaders(headers.entrySet())) { - final List val = headerEntry.getValue(); - final String header = headerEntry.getKey(); - - if (val.size() == 1) { - prefixId(b, id).append(prefix).append(header).append(": ").append(val.get(0)).append("\n"); - } else { - final StringBuilder sb = new StringBuilder(); - boolean add = false; - for (final Object s : val) { - if (add) { - sb.append(','); - } - add = true; - sb.append(s); - } - prefixId(b, id).append(prefix).append(header).append(": ").append(sb.toString()).append("\n"); - } - } - } - - private Set>> getSortedHeaders(final Set>> headers) { - final TreeSet>> sortedHeaders = new TreeSet>>( - COMPARATOR); - sortedHeaders.addAll(headers); - return sortedHeaders; - } - - private InputStream logInboundEntity(final StringBuilder b, InputStream stream, final Charset charset) - throws IOException { - if (!stream.markSupported()) { - stream = new BufferedInputStream(stream); - } - stream.mark(maxEntitySize + 1); - final byte[] entity = new byte[maxEntitySize + 1]; - final int entitySize = stream.read(entity); - b.append(new String(entity, 0, Math.min(entitySize, maxEntitySize), charset)); - if (entitySize > maxEntitySize) { - b.append("...more..."); - } - b.append('\n'); - stream.reset(); - return stream; - } - - @Override - public void filter(final ClientRequestContext context) throws IOException { - final long id = _id.incrementAndGet(); - context.setProperty(LOGGING_ID_PROPERTY, id); - - final StringBuilder b = new StringBuilder(); - - printRequestLine(b, "Sending client request", id, context.getMethod(), context.getUri()); - printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getStringHeaders()); - - if (printEntity && context.hasEntity()) { - final OutputStream stream = new LoggingStream(b, context.getEntityStream()); - context.setEntityStream(stream); - context.setProperty(ENTITY_LOGGER_PROPERTY, stream); - // not calling log(b) here - it will be called by the interceptor - } else { - log(b); - } - } - - @Override - public void filter(final ClientRequestContext requestContext, final ClientResponseContext responseContext) - throws IOException { - final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); - final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); - - final StringBuilder b = new StringBuilder(); - - printResponseLine(b, "Client response received", id, responseContext.getStatus()); - printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getHeaders()); - - if (printEntity && responseContext.hasEntity()) { - responseContext.setEntityStream( - logInboundEntity(b, responseContext.getEntityStream(), getCharset(responseContext.getMediaType()))); - } - - log(b); - } - - @Override - public void filter(final ContainerRequestContext context) throws IOException { - final long id = _id.incrementAndGet(); - context.setProperty(LOGGING_ID_PROPERTY, id); - - final StringBuilder b = new StringBuilder(); - - printRequestLine(b, "Server has received a request", id, context.getMethod(), - context.getUriInfo().getRequestUri()); - printPrefixedHeaders(b, id, REQUEST_PREFIX, context.getHeaders()); - - if (printEntity && context.hasEntity()) { - context.setEntityStream(logInboundEntity(b, context.getEntityStream(), getCharset(context.getMediaType()))); - } - - log(b); - } - - @Override - public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) - throws IOException { - final Object requestId = requestContext.getProperty(LOGGING_ID_PROPERTY); - final long id = requestId != null ? (Long) requestId : _id.incrementAndGet(); - - final StringBuilder b = new StringBuilder(); - - printResponseLine(b, "Server responded with a response", id, responseContext.getStatus()); - printPrefixedHeaders(b, id, RESPONSE_PREFIX, responseContext.getStringHeaders()); - - if (printEntity && responseContext.hasEntity()) { - final OutputStream stream = new LoggingStream(b, responseContext.getEntityStream()); - responseContext.setEntityStream(stream); - requestContext.setProperty(ENTITY_LOGGER_PROPERTY, stream); - // not calling log(b) here - it will be called by the interceptor - } else { - log(b); - } - } - - @Override - public void aroundWriteTo(final WriterInterceptorContext writerInterceptorContext) - throws IOException, WebApplicationException { - final LoggingStream stream = (LoggingStream) writerInterceptorContext.getProperty(ENTITY_LOGGER_PROPERTY); - writerInterceptorContext.proceed(); - if (stream != null) { - log(stream.getStringBuilder(getCharset(writerInterceptorContext.getMediaType()))); - } - } - - private class LoggingStream extends FilterOutputStream { - - private final StringBuilder b; - private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - LoggingStream(final StringBuilder b, final OutputStream inner) { - super(inner); - - this.b = b; - } - - StringBuilder getStringBuilder(final Charset charset) { - // write entity to the builder - final byte[] entity = baos.toByteArray(); - - b.append(new String(entity, 0, Math.min(entity.length, maxEntitySize), charset)); - if (entity.length > maxEntitySize) { - b.append("...more..."); - } - b.append('\n'); - - return b; - } - - @Override - public void write(final int i) throws IOException { - if (baos.size() <= maxEntitySize) { - baos.write(i); - } - out.write(i); - } - } - - /** - * Get the character set from a media type. - *

- * The character set is obtained from the media type parameter "charset". - * If the parameter is not present the {@link #UTF8} charset is utilized. - * - * @param m the media type. - * @return the character set. - */ - public static Charset getCharset(MediaType m) { - String name = (m == null) ? null : m.getParameters().get(MediaType.CHARSET_PARAMETER); - return (name == null) ? UTF8 : Charset.forName(name); - } - -} \ No newline at end of file diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java deleted file mode 100644 index 7f5e3cbce9..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.impl; - -import javax.ws.rs.client.Client; - -import com.google.gson.Gson; - -public abstract class AbstractClient -{ - private volatile Client client; - private volatile Gson gson; - - protected Client getClient() - { - if (client == null) - { - synchronized (this) - { - if (client == null) - { - client = createClient(); - } - } - } - - return client; - } - - protected Gson getGson() - { - if (gson == null) - { - synchronized (this) - { - if (gson == null) - { - gson = createGson(); - } - } - } - - return gson; - } - - protected abstract Client createClient(); - - protected Gson createGson() - { - return GsonGenerator.create(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java deleted file mode 100644 index a1e8f348e4..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.impl; - -public class Endpoints -{ - private static final String LOGIN = "login"; - private static final String BED = "bed"; - private static final String SLEEPER = "sleeper"; - private static final String FAMILY_STATUS = "familyStatus"; - private static final String PAUSE_MODE = "pauseMode"; - - public static String login() - { - return LOGIN; - } - - public static String bed() - { - return BED; - } - - public static String sleeper() - { - return SLEEPER; - } - - public static String familyStatus() - { - return FAMILY_STATUS; - } - - public static String pauseMode() - { - return PAUSE_MODE; - } - - // @formatter:off - private Endpoints() {} - // @formatter:on -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java deleted file mode 100644 index fb67e9b0ac..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.impl; - -import org.openhab.binding.sleepiq.api.impl.typeadapters.JSR310TypeAdapters; -import org.openhab.binding.sleepiq.api.impl.typeadapters.TimeSinceTypeAdapter; -import org.openhab.binding.sleepiq.api.model.TimeSince; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -public class GsonGenerator -{ - public static Gson create() - { - return create(false); - } - - public static Gson create(boolean prettyPrint) - { - GsonBuilder builder = new GsonBuilder(); - - // add Java 8 Time API support - JSR310TypeAdapters.registerJSR310TypeAdapters(builder); - - builder.registerTypeAdapter(TimeSince.class, new TimeSinceTypeAdapter()); - - if (prettyPrint) - { - builder.setPrettyPrinting(); - } - - return builder.create(); - } - - // @formatter:off - private GsonGenerator() {} - // @formatter:on -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java deleted file mode 100644 index df1b85a387..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.impl; - -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; -import java.util.stream.Collectors; - -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.ClientRequestContext; -import javax.ws.rs.client.ClientRequestFilter; -import javax.ws.rs.client.Entity; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; - -import org.openhab.binding.sleepiq.api.BedNotFoundException; -import org.openhab.binding.sleepiq.api.Configuration; -import org.openhab.binding.sleepiq.api.LoginException; -import org.openhab.binding.sleepiq.api.SleepIQ; -import org.openhab.binding.sleepiq.api.UnauthorizedException; -import org.openhab.binding.sleepiq.api.filter.LoggingFilter; -import org.openhab.binding.sleepiq.api.model.Bed; -import org.openhab.binding.sleepiq.api.model.BedsResponse; -import org.openhab.binding.sleepiq.api.model.Failure; -import org.openhab.binding.sleepiq.api.model.FamilyStatus; -import org.openhab.binding.sleepiq.api.model.LoginInfo; -import org.openhab.binding.sleepiq.api.model.LoginRequest; -import org.openhab.binding.sleepiq.api.model.PauseMode; -import org.openhab.binding.sleepiq.api.model.Sleeper; -import org.openhab.binding.sleepiq.api.model.SleepersResponse; -import org.openhab.binding.sleepiq.internal.GsonProvider; - -public class SleepIQImpl extends AbstractClient implements SleepIQ { - protected static final String PARAM_KEY = "_k"; - - protected static final String DATA_BED_ID = "bedId"; - - protected final Configuration config; - - private volatile LoginInfo loginInfo; - - private final ClientBuilder clientBuilder; - - public SleepIQImpl(Configuration config, ClientBuilder clientBuilder) { - this.config = config; - this.clientBuilder = clientBuilder; - } - - @Override - public LoginInfo login() throws LoginException { - if (loginInfo == null) { - synchronized (this) { - if (loginInfo == null) { - Response response = getClient().target(config.getBaseUri()).path(Endpoints.login()) - .request(MediaType.APPLICATION_JSON_TYPE).put(Entity.json(new LoginRequest() - .withLogin(config.getUsername()).withPassword(config.getPassword()))); - - if (isUnauthorized(response)) { - throw new UnauthorizedException(response.readEntity(Failure.class)); - } - - if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { - throw new LoginException(response.readEntity(Failure.class)); - } - - // add the received cookies to all future requests - getClient().register(new ClientRequestFilter() { - @Override - public void filter(ClientRequestContext requestContext) throws IOException { - List cookies = response.getCookies().values().stream() - .map(newCookie -> newCookie.toCookie()).collect(Collectors.toList()); - requestContext.getHeaders().put("Cookie", cookies); - } - }); - - loginInfo = response.readEntity(LoginInfo.class); - } - } - } - - return loginInfo; - } - - @Override - public List getBeds() { - return getSessionResponse(this::getBedsResponse).readEntity(BedsResponse.class).getBeds(); - } - - protected Response getBedsResponse(Map data) throws LoginException { - LoginInfo login = login(); - return getClient().target(config.getBaseUri()).path(Endpoints.bed()).queryParam(PARAM_KEY, login.getKey()) - .request(MediaType.APPLICATION_JSON_TYPE).get(); - } - - @Override - public List getSleepers() { - return getSessionResponse(this::getSleepersResponse).readEntity(SleepersResponse.class).getSleepers(); - } - - protected Response getSleepersResponse(Map data) throws LoginException { - LoginInfo login = login(); - return getClient().target(config.getBaseUri()).path(Endpoints.sleeper()).queryParam(PARAM_KEY, login.getKey()) - .request(MediaType.APPLICATION_JSON_TYPE).get(); - } - - @Override - public FamilyStatus getFamilyStatus() { - return getSessionResponse(this::getFamilyStatusResponse).readEntity(FamilyStatus.class); - } - - protected Response getFamilyStatusResponse(Map data) throws LoginException { - LoginInfo login = login(); - return getClient().target(config.getBaseUri()).path(Endpoints.bed()).path(Endpoints.familyStatus()) - .queryParam(PARAM_KEY, login.getKey()).request(MediaType.APPLICATION_JSON_TYPE).get(); - } - - @Override - public PauseMode getPauseMode(String bedId) throws BedNotFoundException { - Map data = new HashMap<>(); - data.put(DATA_BED_ID, bedId); - - Response response = getSessionResponse(this::getPauseModeResponse, data); - - if (!Status.Family.SUCCESSFUL.equals(response.getStatusInfo().getFamily())) { - throw new BedNotFoundException(response.readEntity(Failure.class)); - } - - return response.readEntity(PauseMode.class); - } - - protected Response getPauseModeResponse(Map data) throws LoginException { - LoginInfo login = login(); - return getClient().target(config.getBaseUri()).path(Endpoints.bed()).path(data.get(DATA_BED_ID).toString()) - .path(Endpoints.pauseMode()).queryParam(PARAM_KEY, login.getKey()) - .request(MediaType.APPLICATION_JSON_TYPE).get(); - } - - protected boolean isUnauthorized(Response response) { - return Status.UNAUTHORIZED.getStatusCode() == response.getStatusInfo().getStatusCode(); - } - - protected synchronized void resetLogin() { - loginInfo = null; - } - - protected Response getSessionResponse(Request request) { - return getSessionResponse(request, Collections.emptyMap()); - } - - protected Response getSessionResponse(Request request, Map data) { - try { - Response response = request.execute(data); - - if (isUnauthorized(response)) { - // session timed out - response.close(); - resetLogin(); - response = request.execute(data); - } - - return response; - } catch (LoginException e) { - throw new RuntimeException(e.getMessage(), e); - } - } - - @Override - protected Client createClient() { - // setup Gson (de)serialization - GsonProvider gsonProvider = new GsonProvider<>(getGson()); - clientBuilder.register(gsonProvider); - - // turn on logging if requested - if (config.isLogging()) { - clientBuilder.register(new LoggingFilter(Logger.getLogger(SleepIQImpl.class.getName()), true)); - } - - return clientBuilder.build(); - } - - @FunctionalInterface - public static interface Request { - public Response execute(Map data) throws LoginException; - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java deleted file mode 100644 index e148736f36..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.util.function.Function; - -/** - * Abstract type adapter for jsr310 date-time types. - * - * @author Christophe Bornet - */ -abstract class DateTimeTypeAdapter extends TemporalTypeAdapter { - - DateTimeTypeAdapter(Function parseFunction) { - super(parseFunction); - } - - @Override - public String preProcess(String in) { - if (in.endsWith("+0000")) { - return in.substring(0, in.length()-5) + "Z"; - } - return in; - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java deleted file mode 100644 index 7651064f6a..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.Duration; - -/** - * Type adapter for jsr310 {@link Duration} class. - * - * @author Christophe Bornet - */ -public class DurationTypeAdapter extends TemporalTypeAdapter { - - public DurationTypeAdapter() { - super(Duration::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java deleted file mode 100644 index 5f4b4f4d0c..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.Instant; - -/** - * Type adapter for jsr310 {@link Instant} class. - * - * @author Christophe Bornet - */ -public class InstantTypeAdapter extends DateTimeTypeAdapter { - - public InstantTypeAdapter() { - super(Instant::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java deleted file mode 100644 index 4de838cf87..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import com.google.gson.GsonBuilder; - -import java.time.*; - -/** - * Helper methods to register JSR310 type adapters. - * - * @author Christophe Bornet - */ -public class JSR310TypeAdapters { - - private JSR310TypeAdapters() { - } - - public static GsonBuilder registerDurationTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(Duration.class, new DurationTypeAdapter()); - } - - public static GsonBuilder registerInstantTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter()); - } - - public static GsonBuilder registerLocalDateTimeTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeTypeAdapter()); - } - - public static GsonBuilder registerLocalDateTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(LocalDate.class, new LocalDateTypeAdapter()); - } - - public static GsonBuilder registerLocalTimeTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(LocalTime.class, new LocalTimeTypeAdapter()); - } - - public static GsonBuilder registerMonthDayTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(MonthDay.class, new MonthDayTypeAdapter()); - } - - public static GsonBuilder registerOffsetDateTimeTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeTypeAdapter()); - } - - public static GsonBuilder registerOffsetTimeTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(OffsetTime.class, new OffsetTimeTypeAdapter()); - } - - public static GsonBuilder registerPeriodTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(Period.class, new PeriodTypeAdapter()); - } - - public static GsonBuilder registerYearMonthTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(YearMonth.class, new YearMonthTypeAdapter()); - } - - public static GsonBuilder registerYearTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(Year.class, new YearTypeAdapter()); - } - - public static GsonBuilder registerZonedDateTimeTypeAdapter(GsonBuilder gsonBuilder) { - return gsonBuilder.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeTypeAdapter()); - } - - - /** - * Helper method to register all the available JSR310 adapters at once. - * @param gsonBuilder the gsonBuilder on which all the JSR310 adapters must be registered. - * @return the gsonBuilder with the JSR310 adapters registered. - */ - public static GsonBuilder registerJSR310TypeAdapters(GsonBuilder gsonBuilder) { - registerDurationTypeAdapter(gsonBuilder); - registerInstantTypeAdapter(gsonBuilder); - registerLocalDateTimeTypeAdapter(gsonBuilder); - registerLocalDateTypeAdapter(gsonBuilder); - registerLocalTimeTypeAdapter(gsonBuilder); - registerMonthDayTypeAdapter(gsonBuilder); - registerOffsetDateTimeTypeAdapter(gsonBuilder); - registerOffsetTimeTypeAdapter(gsonBuilder); - registerPeriodTypeAdapter(gsonBuilder); - registerYearMonthTypeAdapter(gsonBuilder); - registerYearTypeAdapter(gsonBuilder); - registerZonedDateTimeTypeAdapter(gsonBuilder); - - return gsonBuilder; - } - - -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java deleted file mode 100644 index 10360c9ae6..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.LocalDateTime; - -/** - * Type adapter for jsr310 {@link LocalDateTime} class. - * - * @author Christophe Bornet - */ -public class LocalDateTimeTypeAdapter extends DateTimeTypeAdapter { - - public LocalDateTimeTypeAdapter() { - super(LocalDateTime::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java deleted file mode 100644 index 3ac2762dba..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.LocalDate; - -/** - * Type adapter for jsr310 {@link LocalDate} class. - * - * @author Christophe Bornet - */ -public class LocalDateTypeAdapter extends TemporalTypeAdapter { - - public LocalDateTypeAdapter() { - super(LocalDate::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java deleted file mode 100644 index 597301e2f3..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.LocalTime; - -/** - * Type adapter for jsr310 {@link LocalTime} class. - * - * @author Christophe Bornet - */ -public class LocalTimeTypeAdapter extends TemporalTypeAdapter { - - public LocalTimeTypeAdapter() { - super(LocalTime::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java deleted file mode 100644 index 5a1ab7fe71..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.MonthDay; - -/** - * Type adapter for jsr310 {@link MonthDay} class. - * - * @author Christophe Bornet - */ -public class MonthDayTypeAdapter extends TemporalTypeAdapter { - - public MonthDayTypeAdapter() { - super(MonthDay::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java deleted file mode 100644 index ded37fd975..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.OffsetDateTime; - -/** - * Type adapter for jsr310 {@link OffsetDateTime} class. - * - * @author Christophe Bornet - */ -public class OffsetDateTimeTypeAdapter extends DateTimeTypeAdapter { - - public OffsetDateTimeTypeAdapter() { - super(OffsetDateTime::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java deleted file mode 100644 index e6f49e7837..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.OffsetTime; - -/** - * Type adapter for jsr310 {@link OffsetTime} class. - * - * @author Christophe Bornet - */ -public class OffsetTimeTypeAdapter extends TemporalTypeAdapter { - - public OffsetTimeTypeAdapter() { - super(OffsetTime::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java deleted file mode 100644 index 74ade1885a..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.Period; - -/** - * Type adapter for jsr310 {@link Period} class. - * - * @author Christophe Bornet - */ -public class PeriodTypeAdapter extends TemporalTypeAdapter { - - public PeriodTypeAdapter() { - super(Period::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java deleted file mode 100644 index dcbde82e6f..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.io.IOException; -import java.util.Objects; -import java.util.function.Function; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonToken; -import com.google.gson.stream.JsonWriter; - -/** - * Abstract type adapter for jsr310 date-time types. - * - * @author Christophe Bornet - */ -abstract class TemporalTypeAdapter extends TypeAdapter { - - Function parseFunction; - - TemporalTypeAdapter(Function parseFunction) { - Objects.requireNonNull(parseFunction); - this.parseFunction = parseFunction; - } - - @Override - public void write(JsonWriter out, T value) throws IOException { - if (value == null) { - out.nullValue(); - } else { - out.value(value.toString()); - } - } - - @Override - public T read(JsonReader in) throws IOException { - if (in.peek() == JsonToken.NULL) { - in.nextNull(); - return null; - } - String temporalString = preProcess(in.nextString()); - return parseFunction.apply(temporalString); - } - - public String preProcess(String in) { - return in; - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java deleted file mode 100644 index 3504e1bfba..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import org.openhab.binding.sleepiq.api.model.TimeSince; - -public class TimeSinceTypeAdapter extends TemporalTypeAdapter -{ - public TimeSinceTypeAdapter() - { - super(TimeSince::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java deleted file mode 100644 index 5fe0a6e97a..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.YearMonth; - -/** - * Type adapter for jsr310 {@link YearMonth} class. - * - * @author Christophe Bornet - */ -public class YearMonthTypeAdapter extends TemporalTypeAdapter { - - public YearMonthTypeAdapter() { - super(YearMonth::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java deleted file mode 100644 index 37f2153a1e..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.Year; - -/** - * Type adapter for jsr310 {@link Year} class. - * - * @author Christophe Bornet - */ -public class YearTypeAdapter extends TemporalTypeAdapter { - - public YearTypeAdapter() { - super(Year::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java deleted file mode 100644 index 0d31cad1a3..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src - * and repackaged to avoid the default package. - */ -package org.openhab.binding.sleepiq.api.impl.typeadapters; - -import java.time.ZonedDateTime; - -/** - * Type adapter for jsr310 {@link ZonedDateTime} class. - * - * @author Christophe Bornet - */ -public class ZonedDateTimeTypeAdapter extends DateTimeTypeAdapter { - - public ZonedDateTimeTypeAdapter() { - super(ZonedDateTime::parse); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java deleted file mode 100644 index 6bfa86db0e..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import java.time.ZonedDateTime; - -import com.google.gson.annotations.SerializedName; - -public class Bed -{ - private ZonedDateTime registrationDate; - private String sleeperRightId; - private String base; - private Long returnRequestStatus; - private String size; - private String name; - private String serial; - @SerializedName("isKidsBed") - private Boolean kidsBed; - private Boolean dualSleep; - private String bedId; - private Long status; - private String sleeperLeftId; - private String version; - private String accountId; - private String timezone; - private String model; - private ZonedDateTime purchaseDate; - private String macAddress; - private String sku; - @SerializedName("zipcode") - private String zipCode; - private String reference; - - public ZonedDateTime getRegistrationDate() - { - return registrationDate; - } - - public void setRegistrationDate(ZonedDateTime registrationDate) - { - this.registrationDate = registrationDate; - } - - public Bed withRegistrationDate(ZonedDateTime registrationDate) - { - setRegistrationDate(registrationDate); - return this; - } - - public String getSleeperRightId() - { - return sleeperRightId; - } - - public void setSleeperRightId(String sleeperRightId) - { - this.sleeperRightId = sleeperRightId; - } - - public Bed withSleeperRightId(String sleeperRightId) - { - setSleeperRightId(sleeperRightId); - return this; - } - - public String getBase() - { - return base; - } - - public void setBase(String base) - { - this.base = base; - } - - public Bed withBase(String base) - { - setBase(base); - return this; - } - - public Long getReturnRequestStatus() - { - return returnRequestStatus; - } - - public void setReturnRequestStatus(Long returnRequestStatus) - { - this.returnRequestStatus = returnRequestStatus; - } - - public Bed withReturnRequestStatus(Long returnRequestStatus) - { - setReturnRequestStatus(returnRequestStatus); - return this; - } - - public String getSize() - { - return size; - } - - public void setSize(String size) - { - this.size = size; - } - - public Bed withSize(String size) - { - setSize(size); - return this; - } - - public String getName() - { - return name; - } - - public void setName(String name) - { - this.name = name; - } - - public Bed withName(String name) - { - setName(name); - return this; - } - - public String getSerial() - { - return serial; - } - - public void setSerial(String serial) - { - this.serial = serial; - } - - public Bed withSerial(String serial) - { - setSerial(serial); - return this; - } - - public Boolean isKidsBed() - { - return kidsBed; - } - - public void setKidsBed(Boolean kidsBed) - { - this.kidsBed = kidsBed; - } - - public Bed withKidsBed(Boolean kidsBed) - { - setKidsBed(kidsBed); - return this; - } - - public Boolean isDualSleep() - { - return dualSleep; - } - - public void setDualSleep(Boolean dualSleep) - { - this.dualSleep = dualSleep; - } - - public Bed withDualSleep(Boolean dualSleep) - { - setDualSleep(dualSleep); - return this; - } - - public String getBedId() - { - return bedId; - } - - public void setBedId(String bedId) - { - this.bedId = bedId; - } - - public Bed withBedId(String bedId) - { - setBedId(bedId); - return this; - } - - public Long getStatus() - { - return status; - } - - public void setStatus(Long status) - { - this.status = status; - } - - public Bed withStatus(Long status) - { - setStatus(status); - return this; - } - - public String getSleeperLeftId() - { - return sleeperLeftId; - } - - public void setSleeperLeftId(String sleeperLeftId) - { - this.sleeperLeftId = sleeperLeftId; - } - - public Bed withSleeperLeftId(String sleeperLeftId) - { - setSleeperLeftId(sleeperLeftId); - return this; - } - - public String getVersion() - { - return version; - } - - public void setVersion(String version) - { - this.version = version; - } - - public Bed withVersion(String version) - { - setVersion(version); - return this; - } - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public Bed withAccountId(String accountId) - { - setAccountId(accountId); - return this; - } - - public String getTimezone() - { - return timezone; - } - - public void setTimezone(String timezone) - { - this.timezone = timezone; - } - - public Bed withTimezone(String timezone) - { - setTimezone(timezone); - return this; - } - - public String getModel() - { - return model; - } - - public void setModel(String model) - { - this.model = model; - } - - public Bed withModel(String model) - { - setModel(model); - return this; - } - - public ZonedDateTime getPurchaseDate() - { - return purchaseDate; - } - - public void setPurchaseDate(ZonedDateTime purchaseDate) - { - this.purchaseDate = purchaseDate; - } - - public Bed withPurchaseDate(ZonedDateTime purchaseDate) - { - setPurchaseDate(purchaseDate); - return this; - } - - public String getMacAddress() - { - return macAddress; - } - - public void setMacAddress(String macAddress) - { - this.macAddress = macAddress; - } - - public Bed withMacAddress(String macAddress) - { - setMacAddress(macAddress); - return this; - } - - public String getSku() - { - return sku; - } - - public void setSku(String sku) - { - this.sku = sku; - } - - public Bed withSku(String sku) - { - setSku(sku); - return this; - } - - public String getZipCode() - { - return zipCode; - } - - public void setZipCode(String zipCode) - { - this.zipCode = zipCode; - } - - public Bed withZipCode(String zipCode) - { - setZipCode(zipCode); - return this; - } - - public String getReference() - { - return reference; - } - - public void setReference(String reference) - { - this.reference = reference; - } - - public Bed withReference(String reference) - { - setReference(reference); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof Bed)) - { - return false; - } - Bed other = (Bed)obj; - if (bedId == null) - { - if (other.bedId != null) - { - return false; - } - } - else if (!bedId.equals(other.bedId)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("Bed [registrationDate="); - builder.append(registrationDate); - builder.append(", sleeperRightId="); - builder.append(sleeperRightId); - builder.append(", base="); - builder.append(base); - builder.append(", returnRequestStatus="); - builder.append(returnRequestStatus); - builder.append(", size="); - builder.append(size); - builder.append(", name="); - builder.append(name); - builder.append(", serial="); - builder.append(serial); - builder.append(", kidsBed="); - builder.append(kidsBed); - builder.append(", dualSleep="); - builder.append(dualSleep); - builder.append(", bedId="); - builder.append(bedId); - builder.append(", status="); - builder.append(status); - builder.append(", sleeperLeftId="); - builder.append(sleeperLeftId); - builder.append(", version="); - builder.append(version); - builder.append(", accountId="); - builder.append(accountId); - builder.append(", timezone="); - builder.append(timezone); - builder.append(", model="); - builder.append(model); - builder.append(", purchaseDate="); - builder.append(purchaseDate); - builder.append(", macAddress="); - builder.append(macAddress); - builder.append(", sku="); - builder.append(sku); - builder.append(", zipCode="); - builder.append(zipCode); - builder.append(", reference="); - builder.append(reference); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java deleted file mode 100644 index b7e994b2bd..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import com.google.gson.annotations.SerializedName; - -public class BedSideStatus -{ - @SerializedName("isInBed") - private Boolean inBed; - private String alertDetailedMessage; - private Integer sleepNumber; - private Long alertId; - private TimeSince lastLink; - private Integer pressure; // appears to be in kPa - - public Boolean isInBed() - { - return inBed; - } - - public void setInBed(Boolean inBed) - { - this.inBed = inBed; - } - - public BedSideStatus withInBed(Boolean inBed) - { - setInBed(inBed); - return this; - } - - public String getAlertDetailedMessage() - { - return alertDetailedMessage; - } - - public void setAlertDetailedMessage(String alertDetailedMessage) - { - this.alertDetailedMessage = alertDetailedMessage; - } - - public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) - { - setAlertDetailedMessage(alertDetailedMessage); - return this; - } - - public Integer getSleepNumber() - { - return sleepNumber; - } - - public void setSleepNumber(Integer sleepNumber) - { - this.sleepNumber = sleepNumber; - } - - public BedSideStatus withSleepNumber(Integer sleepNumber) - { - setSleepNumber(sleepNumber); - return this; - } - - public Long getAlertId() - { - return alertId; - } - - public void setAlertId(Long alertId) - { - this.alertId = alertId; - } - - public BedSideStatus withAlertId(Long alertId) - { - setAlertId(alertId); - return this; - } - - public TimeSince getLastLink() - { - return lastLink; - } - - public void setLastLink(TimeSince lastLink) - { - this.lastLink = lastLink; - } - - public BedSideStatus withLastLink(TimeSince lastLink) - { - setLastLink(lastLink); - return this; - } - - public Integer getPressure() - { - return pressure; - } - - public void setPressure(Integer pressure) - { - this.pressure = pressure; - } - - public BedSideStatus withPressure(Integer pressure) - { - setPressure(pressure); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result - + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode()); - result = prime * result + ((alertId == null) ? 0 : alertId.hashCode()); - result = prime * result + ((inBed == null) ? 0 : inBed.hashCode()); - result = prime * result + ((lastLink == null) ? 0 : lastLink.hashCode()); - result = prime * result + ((pressure == null) ? 0 : pressure.hashCode()); - result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof BedSideStatus)) - { - return false; - } - BedSideStatus other = (BedSideStatus)obj; - if (alertDetailedMessage == null) - { - if (other.alertDetailedMessage != null) - { - return false; - } - } - else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) - { - return false; - } - if (alertId == null) - { - if (other.alertId != null) - { - return false; - } - } - else if (!alertId.equals(other.alertId)) - { - return false; - } - if (inBed == null) - { - if (other.inBed != null) - { - return false; - } - } - else if (!inBed.equals(other.inBed)) - { - return false; - } - if (lastLink == null) - { - if (other.lastLink != null) - { - return false; - } - } - else if (!lastLink.equals(other.lastLink)) - { - return false; - } - if (pressure == null) - { - if (other.pressure != null) - { - return false; - } - } - else if (!pressure.equals(other.pressure)) - { - return false; - } - if (sleepNumber == null) - { - if (other.sleepNumber != null) - { - return false; - } - } - else if (!sleepNumber.equals(other.sleepNumber)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("BedSideStatus [inBed="); - builder.append(inBed); - builder.append(", alertDetailedMessage="); - builder.append(alertDetailedMessage); - builder.append(", sleepNumber="); - builder.append(sleepNumber); - builder.append(", alertId="); - builder.append(alertId); - builder.append(", lastLink="); - builder.append(lastLink); - builder.append(", pressure="); - builder.append(pressure); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java deleted file mode 100644 index c07fbd8d88..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -public class BedStatus -{ - private Long status; - private String bedId; - private BedSideStatus leftSide; - private BedSideStatus rightSide; - - public Long getStatus() - { - return status; - } - - public void setStatus(Long status) - { - this.status = status; - } - - public BedStatus withStatus(Long status) - { - setStatus(status); - return this; - } - - public String getBedId() - { - return bedId; - } - - public void setBedId(String bedId) - { - this.bedId = bedId; - } - - public BedStatus withBedId(String bedId) - { - setBedId(bedId); - return this; - } - - public BedSideStatus getLeftSide() - { - return leftSide; - } - - public void setLeftSide(BedSideStatus leftSide) - { - this.leftSide = leftSide; - } - - public BedStatus withLeftSide(BedSideStatus leftSide) - { - setLeftSide(leftSide); - return this; - } - - public BedSideStatus getRightSide() - { - return rightSide; - } - - public void setRightSide(BedSideStatus rightSide) - { - this.rightSide = rightSide; - } - - public BedStatus withRightSide(BedSideStatus rightSide) - { - setRightSide(rightSide); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof BedStatus)) - { - return false; - } - BedStatus other = (BedStatus)obj; - if (bedId == null) - { - if (other.bedId != null) - { - return false; - } - } - else if (!bedId.equals(other.bedId)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("BedStatus [status="); - builder.append(status); - builder.append(", bedId="); - builder.append(bedId); - builder.append(", leftSide="); - builder.append(leftSide); - builder.append(", rightSide="); - builder.append(rightSide); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java deleted file mode 100644 index 3b3deeea0c..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import java.util.List; - -public class BedsResponse -{ - private List beds; - - public List getBeds() - { - return beds; - } - - public void setBeds(List beds) - { - this.beds = beds; - } - - public BedsResponse withBeds(List beds) - { - setBeds(beds); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((beds == null) ? 0 : beds.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof BedsResponse)) - { - return false; - } - BedsResponse other = (BedsResponse)obj; - if (beds == null) - { - if (other.beds != null) - { - return false; - } - } - else if (!beds.equals(other.beds)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("BedsResponse [beds="); - builder.append(beds); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java deleted file mode 100644 index 5593b59fe4..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import com.google.gson.annotations.SerializedName; - -public class Error -{ - @SerializedName("Code") - private Long code; - @SerializedName("Message") - private String message; - - public Long getCode() - { - return code; - } - - public void setCode(Long code) - { - this.code = code; - } - - public Error withCode(Long code) - { - setCode(code); - return this; - } - - public String getMessage() - { - return message; - } - - public void setMessage(String message) - { - this.message = message; - } - - public Error withMessage(String message) - { - setMessage(message); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((code == null) ? 0 : code.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof Error)) - { - return false; - } - Error other = (Error)obj; - if (code == null) - { - if (other.code != null) - { - return false; - } - } - else if (!code.equals(other.code)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("Error [code="); - builder.append(code); - builder.append(", message="); - builder.append(message); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java deleted file mode 100644 index 4ab0481e8a..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import com.google.gson.annotations.SerializedName; - -public class Failure -{ - @SerializedName("Error") - private Error error; - - public Error getError() - { - return error; - } - - public void setError(Error error) - { - this.error = error; - } - - public Failure withError(Error error) - { - setError(error); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((error == null) ? 0 : error.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof Failure)) - { - return false; - } - Failure other = (Failure)obj; - if (error == null) - { - if (other.error != null) - { - return false; - } - } - else if (!error.equals(other.error)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("Failure [error="); - builder.append(error); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java deleted file mode 100644 index cddea5a606..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import java.util.List; - -public class FamilyStatus -{ - private List beds; - - public List getBeds() - { - return beds; - } - - public void setBeds(List beds) - { - this.beds = beds; - } - - public FamilyStatus withBeds(List beds) - { - setBeds(beds); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((beds == null) ? 0 : beds.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof FamilyStatus)) - { - return false; - } - FamilyStatus other = (FamilyStatus)obj; - if (beds == null) - { - if (other.beds != null) - { - return false; - } - } - else if (!beds.equals(other.beds)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("FamilyStatus [beds="); - builder.append(beds); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java deleted file mode 100644 index 7cc35096fb..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -public class LoginInfo -{ - private String userId; - private String key; - private Long registrationState; - private Long edpLoginStatus; - private String edpLoginMessage; - - public String getUserId() - { - return userId; - } - - public void setUserId(String userId) - { - this.userId = userId; - } - - public LoginInfo withUserId(String userId) - { - setUserId(userId); - return this; - } - - public String getKey() - { - return key; - } - - public void setKey(String key) - { - this.key = key; - } - - public LoginInfo withKey(String key) - { - setKey(key); - return this; - } - - public Long getRegistrationState() - { - return registrationState; - } - - public void setRegistrationState(Long registrationState) - { - this.registrationState = registrationState; - } - - public LoginInfo withRegistrationState(Long registrationState) - { - setRegistrationState(registrationState); - return this; - } - - public Long getEdpLoginStatus() - { - return edpLoginStatus; - } - - public void setEdpLoginStatus(Long edpLoginStatus) - { - this.edpLoginStatus = edpLoginStatus; - } - - public LoginInfo withEdpLoginStatus(Long edpLoginStatus) - { - setEdpLoginStatus(edpLoginStatus); - return this; - } - - public String getEdpLoginMessage() - { - return edpLoginMessage; - } - - public void setEdpLoginMessage(String edpLoginMessage) - { - this.edpLoginMessage = edpLoginMessage; - } - - public LoginInfo withEdpLoginMessage(String edpLoginMessage) - { - setEdpLoginMessage(edpLoginMessage); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((key == null) ? 0 : key.hashCode()); - result = prime * result + (int)(registrationState ^ (registrationState >>> 32)); - result = prime * result + ((userId == null) ? 0 : userId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof LoginInfo)) - { - return false; - } - LoginInfo other = (LoginInfo)obj; - if (key == null) - { - if (other.key != null) - { - return false; - } - } - else if (!key.equals(other.key)) - { - return false; - } - if (!registrationState.equals(other.registrationState)) - { - return false; - } - if (userId == null) - { - if (other.userId != null) - { - return false; - } - } - else if (!userId.equals(other.userId)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("LoginInfo [userId="); - builder.append(userId); - builder.append(", key="); - builder.append(key); - builder.append(", registrationState="); - builder.append(registrationState); - builder.append(", edpLoginStatus="); - builder.append(edpLoginStatus); - builder.append(", edpLoginMessage="); - builder.append(edpLoginMessage); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java deleted file mode 100644 index 07835f054e..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -public class LoginRequest -{ - private String login; - private String password; - - public String getLogin() - { - return login; - } - - public void setLogin(String login) - { - this.login = login; - } - - public LoginRequest withLogin(String login) - { - setLogin(login); - return this; - } - - public String getPassword() - { - return password; - } - - public void setPassword(String password) - { - this.password = password; - } - - public LoginRequest withPassword(String password) - { - setPassword(password); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((login == null) ? 0 : login.hashCode()); - result = prime * result + ((password == null) ? 0 : password.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof LoginRequest)) - { - return false; - } - LoginRequest other = (LoginRequest)obj; - if (login == null) - { - if (other.login != null) - { - return false; - } - } - else if (!login.equals(other.login)) - { - return false; - } - if (password == null) - { - if (other.password != null) - { - return false; - } - } - else if (!password.equals(other.password)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("LoginRequest [login="); - builder.append(login); - builder.append(", password="); - builder.append(password); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java deleted file mode 100644 index 5627886465..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -public class PauseMode -{ - private String accountId; - private String bedId; - private String pauseMode; - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public PauseMode withAccountId(String accountId) - { - setAccountId(accountId); - return this; - } - - public String getBedId() - { - return bedId; - } - - public void setBedId(String bedId) - { - this.bedId = bedId; - } - - public PauseMode withBedId(String bedId) - { - setBedId(bedId); - return this; - } - - public String getPauseMode() - { - return pauseMode; - } - - public void setPauseMode(String pauseMode) - { - this.pauseMode = pauseMode; - } - - public PauseMode withPauseMode(String pauseMode) - { - setPauseMode(pauseMode); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((accountId == null) ? 0 : accountId.hashCode()); - result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof PauseMode)) - { - return false; - } - PauseMode other = (PauseMode)obj; - if (accountId == null) - { - if (other.accountId != null) - { - return false; - } - } - else if (!accountId.equals(other.accountId)) - { - return false; - } - if (bedId == null) - { - if (other.bedId != null) - { - return false; - } - } - else if (!bedId.equals(other.bedId)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("PauseMode [accountId="); - builder.append(accountId); - builder.append(", bedId="); - builder.append(bedId); - builder.append(", pauseMode="); - builder.append(pauseMode); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java deleted file mode 100644 index 8a9ff0adfc..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import com.google.gson.annotations.SerializedName; - -public class Sleeper -{ - private String firstName; - private Boolean active; - private Boolean emailValidated; - @SerializedName("isChild") - private Boolean child; - private String bedId; - private String birthYear; - private String zipCode; - private String timezone; - @SerializedName("isMale") - private Boolean male; - private Integer weight; // lbs - private String duration; - private String sleeperId; - private Integer height; // inches - private Long licenseVersion; - private String username; - private Integer birthMonth; // 0-based; 12 means not entered? - private Integer sleepGoal; - @SerializedName("isAccountOwner") - private Boolean accountOwner; - private String accountId; - private String email; - private String avatar; - private String lastLogin; // should be ZonedDateTime but provider passes string "null" when missing - private Integer side; // 0=left; 1=right - - public String getFirstName() - { - return firstName; - } - - public void setFirstName(String firstName) - { - this.firstName = firstName; - } - - public Sleeper withFirstName(String firstName) - { - setFirstName(firstName); - return this; - } - - public Boolean isActive() - { - return active; - } - - public void setActive(Boolean active) - { - this.active = active; - } - - public Sleeper withActive(Boolean active) - { - setActive(active); - return this; - } - - public Boolean isEmailValidated() - { - return emailValidated; - } - - public void setEmailValidated(Boolean emailValidated) - { - this.emailValidated = emailValidated; - } - - public Sleeper withEmailValidated(Boolean emailValidated) - { - setEmailValidated(emailValidated); - return this; - } - - public Boolean isChild() - { - return child; - } - - public void setChild(Boolean child) - { - this.child = child; - } - - public Sleeper withChild(Boolean child) - { - setChild(child); - return this; - } - - public String getBedId() - { - return bedId; - } - - public void setBedId(String bedId) - { - this.bedId = bedId; - } - - public Sleeper withBedId(String bedId) - { - setBedId(bedId); - return this; - } - - public String getBirthYear() - { - return birthYear; - } - - public void setBirthYear(String birthYear) - { - this.birthYear = birthYear; - } - - public Sleeper withBirthYear(String birthYear) - { - setBirthYear(birthYear); - return this; - } - - public String getZipCode() - { - return zipCode; - } - - public void setZipCode(String zipCode) - { - this.zipCode = zipCode; - } - - public Sleeper withZipCode(String zipCode) - { - setZipCode(zipCode); - return this; - } - - public String getTimezone() - { - return timezone; - } - - public void setTimezone(String timezone) - { - this.timezone = timezone; - } - - public Sleeper withTimezone(String timezone) - { - setTimezone(timezone); - return this; - } - - public Boolean isMale() - { - return male; - } - - public void setMale(Boolean male) - { - this.male = male; - } - - public Sleeper withMale(Boolean male) - { - setMale(male); - return this; - } - - public Integer getWeight() - { - return weight; - } - - public void setWeight(Integer weight) - { - this.weight = weight; - } - - public Sleeper withWeight(Integer weight) - { - setWeight(weight); - return this; - } - - public String getDuration() - { - return duration; - } - - public void setDuration(String duration) - { - this.duration = duration; - } - - public Sleeper withDuration(String duration) - { - setDuration(duration); - return this; - } - - public String getSleeperId() - { - return sleeperId; - } - - public void setSleeperId(String sleeperId) - { - this.sleeperId = sleeperId; - } - - public Sleeper withSleeperId(String sleeperId) - { - setSleeperId(sleeperId); - return this; - } - - public Integer getHeight() - { - return height; - } - - public void setHeight(Integer height) - { - this.height = height; - } - - public Sleeper withHeight(Integer height) - { - setHeight(height); - return this; - } - - public Long getLicenseVersion() - { - return licenseVersion; - } - - public void setLicenseVersion(Long licenseVersion) - { - this.licenseVersion = licenseVersion; - } - - public Sleeper withLicenseVersion(Long licenseVersion) - { - setLicenseVersion(licenseVersion); - return this; - } - - public String getUsername() - { - return username; - } - - public void setUsername(String username) - { - this.username = username; - } - - public Sleeper withUsername(String username) - { - setUsername(username); - return this; - } - - public Integer getBirthMonth() - { - return birthMonth; - } - - public void setBirthMonth(Integer birthMonth) - { - this.birthMonth = birthMonth; - } - - public Sleeper withBirthMonth(Integer birthMonth) - { - setBirthMonth(birthMonth); - return this; - } - - public Integer getSleepGoal() - { - return sleepGoal; - } - - public void setSleepGoal(Integer sleepGoal) - { - this.sleepGoal = sleepGoal; - } - - public Sleeper withSleepGoal(Integer sleepGoal) - { - setSleepGoal(sleepGoal); - return this; - } - - public Boolean isAccountOwner() - { - return accountOwner; - } - - public void setAccountOwner(Boolean accountOwner) - { - this.accountOwner = accountOwner; - } - - public Sleeper withAccountOwner(Boolean accountOwner) - { - setAccountOwner(accountOwner); - return this; - } - - public String getAccountId() - { - return accountId; - } - - public void setAccountId(String accountId) - { - this.accountId = accountId; - } - - public Sleeper withAccountId(String accountId) - { - setAccountId(accountId); - return this; - } - - public String getEmail() - { - return email; - } - - public void setEmail(String email) - { - this.email = email; - } - - public Sleeper withEmail(String email) - { - setEmail(email); - return this; - } - - public String getAvatar() - { - return avatar; - } - - public void setAvatar(String avatar) - { - this.avatar = avatar; - } - - public Sleeper withAvatar(String avatar) - { - setAvatar(avatar); - return this; - } - - public String getLastLogin() - { - return lastLogin; - } - - public void setLastLogin(String lastLogin) - { - this.lastLogin = lastLogin; - } - - public Sleeper withLastLogin(String lastLogin) - { - setLastLogin(lastLogin); - return this; - } - - public Integer getSide() - { - return side; - } - - public void setSide(Integer side) - { - this.side = side; - } - - public Sleeper withSide(Integer side) - { - setSide(side); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof Sleeper)) - { - return false; - } - Sleeper other = (Sleeper)obj; - if (sleeperId == null) - { - if (other.sleeperId != null) - { - return false; - } - } - else if (!sleeperId.equals(other.sleeperId)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("Sleeper [firstName="); - builder.append(firstName); - builder.append(", active="); - builder.append(active); - builder.append(", emailValidated="); - builder.append(emailValidated); - builder.append(", child="); - builder.append(child); - builder.append(", bedId="); - builder.append(bedId); - builder.append(", birthYear="); - builder.append(birthYear); - builder.append(", zipCode="); - builder.append(zipCode); - builder.append(", timezone="); - builder.append(timezone); - builder.append(", male="); - builder.append(male); - builder.append(", weight="); - builder.append(weight); - builder.append(", duration="); - builder.append(duration); - builder.append(", sleeperId="); - builder.append(sleeperId); - builder.append(", height="); - builder.append(height); - builder.append(", licenseVersion="); - builder.append(licenseVersion); - builder.append(", username="); - builder.append(username); - builder.append(", birthMonth="); - builder.append(birthMonth); - builder.append(", sleepGoal="); - builder.append(sleepGoal); - builder.append(", accountOwner="); - builder.append(accountOwner); - builder.append(", accountId="); - builder.append(accountId); - builder.append(", email="); - builder.append(email); - builder.append(", avatar="); - builder.append(avatar); - builder.append(", lastLogin="); - builder.append(lastLogin); - builder.append(", side="); - builder.append(side); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java deleted file mode 100644 index 4c793ef1a0..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import java.util.List; - -public class SleepersResponse -{ - private List sleepers; - - public List getSleepers() - { - return sleepers; - } - - public void setSleepers(List sleepers) - { - this.sleepers = sleepers; - } - - public SleepersResponse withSleepers(List sleepers) - { - setSleepers(sleepers); - return this; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + ((sleepers == null) ? 0 : sleepers.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (obj == null) - { - return false; - } - if (!(obj instanceof SleepersResponse)) - { - return false; - } - SleepersResponse other = (SleepersResponse)obj; - if (sleepers == null) - { - if (other.sleepers != null) - { - return false; - } - } - else if (!sleepers.equals(other.sleepers)) - { - return false; - } - return true; - } - - @Override - public String toString() - { - StringBuilder builder = new StringBuilder(); - builder.append("SleepersResponse [sleepers="); - builder.append(sleepers); - builder.append("]"); - return builder.toString(); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java deleted file mode 100644 index c6c8704861..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import java.time.Duration; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class TimeSince { - private static final Pattern PATTERN = Pattern.compile("(([0-9]+) d )?([0-9]{2}):([0-9]{2}):([0-9]{2})", - Pattern.CASE_INSENSITIVE); - - private Duration duration; - - public Duration getDuration() { - return duration; - } - - public void setDuration(Duration duration) { - this.duration = duration == null ? null : duration.abs(); - } - - public TimeSince withDuration(long days, long hours, long minutes, long seconds) { - return withDuration(Duration.ofSeconds(TimeUnit.DAYS.toSeconds(days) + TimeUnit.HOURS.toSeconds(hours) - + TimeUnit.MINUTES.toSeconds(minutes) + seconds)); - } - - public TimeSince withDuration(Duration duration) { - setDuration(duration); - return this; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((duration == null) ? 0 : duration.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof TimeSince)) { - return false; - } - TimeSince other = (TimeSince) obj; - if (duration == null) { - if (other.duration != null) { - return false; - } - } else if (!duration.equals(other.duration)) { - return false; - } - return true; - } - - @Override - public String toString() { - long totalDays = duration.toDays(); - long totalHours = duration.toHours(); - long totalMinutes = duration.toMinutes(); - long totalSeconds = duration.getSeconds(); - - long hours = totalHours - TimeUnit.DAYS.toHours(totalDays); - long minutes = totalMinutes - TimeUnit.HOURS.toMinutes(totalHours); - long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(totalMinutes); - - if (totalDays > 0) { - return String.format("%d d %02d:%02d:%02d", totalDays, hours, minutes, seconds); - } - - return String.format("%02d:%02d:%02d", hours, minutes, seconds); - } - - public static TimeSince parse(CharSequence text) { - Objects.requireNonNull(text, "text"); - - Matcher matcher = PATTERN.matcher(text); - if (!matcher.matches()) { - return new TimeSince().withDuration(Duration.ZERO); - } - - String dayMatch = matcher.group(2); - String hourMatch = matcher.group(3); - String minuteMatch = matcher.group(4); - String secondMatch = matcher.group(5); - - StringBuilder sb = new StringBuilder("P"); - if (dayMatch != null) { - sb.append(dayMatch).append('D'); - } - sb.append('T').append(hourMatch).append('H').append(minuteMatch).append('M').append(secondMatch).append('S'); - - return new TimeSince().withDuration(Duration.parse(sb.toString())); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java deleted file mode 100644 index 796bd5aeb3..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.FileReader; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class BedSideStatusTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - BedSideStatus bedSideStatus = new BedSideStatus().withAlertDetailedMessage("No Alert").withAlertId(0L) - .withInBed(false).withLastLink(new TimeSince().withDuration(3, 5, 4, 38)).withPressure(573) - .withSleepNumber(55); - assertEquals(readJson("bed-side-status.json"), gson.toJson(bedSideStatus)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("bed-side-status.json"))) { - BedSideStatus bedSideStatus = gson.fromJson(reader, BedSideStatus.class); - assertEquals("No Alert", bedSideStatus.getAlertDetailedMessage()); - assertEquals(Long.valueOf(0L), bedSideStatus.getAlertId()); - assertFalse(bedSideStatus.isInBed()); - assertEquals(new TimeSince().withDuration(3, 5, 4, 38), bedSideStatus.getLastLink()); - assertEquals(Integer.valueOf(573), bedSideStatus.getPressure()); - assertEquals(Integer.valueOf(55), bedSideStatus.getSleepNumber()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java deleted file mode 100644 index 331675ba80..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.FileReader; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class BedStatusTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - BedStatus bedStatus = new BedStatus().withBedId("-9999999999999999999") - .withLeftSide(new BedSideStatus().withInBed(true)).withRightSide(new BedSideStatus().withInBed(false)) - .withStatus(1L); - assertEquals(readJson("bed-status.json"), gson.toJson(bedStatus)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("bed-status.json"))) { - BedStatus bedStatus = gson.fromJson(reader, BedStatus.class); - assertEquals("-9999999999999999999", bedStatus.getBedId()); - assertEquals(Long.valueOf(1L), bedStatus.getStatus()); - - BedSideStatus leftSide = bedStatus.getLeftSide(); - assertNotNull(leftSide); - assertTrue(leftSide.isInBed()); - - BedSideStatus rightSide = bedStatus.getRightSide(); - assertNotNull(rightSide); - assertFalse(rightSide.isInBed()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java deleted file mode 100644 index 3873351011..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.FileReader; -import java.time.ZoneId; -import java.time.ZonedDateTime; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class BedTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - Bed bed = new Bed().withAccountId("-8888888888888888888").withBase("MODULAR").withBedId("-9999999999999999999") - .withDualSleep(true).withKidsBed(false).withMacAddress("AABBCCDDEEFF").withModel("P5").withName("Bed") - .withPurchaseDate(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized())) - .withReference("55555555555-5") - .withRegistrationDate(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized())) - .withReturnRequestStatus(0L).withSerial("").withSize("QUEEN").withSku("QP5") - .withSleeperLeftId("-2222222222222222222").withSleeperRightId("-1111111111111111111").withStatus(1L) - .withTimezone("US/Pacific").withVersion("").withZipCode("90210"); - assertEquals(readJson("bed.json"), gson.toJson(bed)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("bed.json"))) { - Bed bed = gson.fromJson(reader, Bed.class); - assertEquals("-8888888888888888888", bed.getAccountId()); - assertEquals("MODULAR", bed.getBase()); - assertEquals("-9999999999999999999", bed.getBedId()); - assertEquals(true, bed.isDualSleep()); - assertEquals(false, bed.isKidsBed()); - assertEquals("AABBCCDDEEFF", bed.getMacAddress()); - assertEquals("P5", bed.getModel()); - assertEquals("Bed", bed.getName()); - assertEquals(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()), bed.getPurchaseDate()); - assertEquals("55555555555-5", bed.getReference()); - assertEquals(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()), - bed.getRegistrationDate()); - assertEquals(Long.valueOf(0L), bed.getReturnRequestStatus()); - assertEquals("", bed.getSerial()); - assertEquals("QUEEN", bed.getSize()); - assertEquals("QP5", bed.getSku()); - assertEquals("-2222222222222222222", bed.getSleeperLeftId()); - assertEquals("-1111111111111111111", bed.getSleeperRightId()); - assertEquals(Long.valueOf(1L), bed.getStatus()); - assertEquals("US/Pacific", bed.getTimezone()); - assertEquals("", bed.getVersion()); - assertEquals("90210", bed.getZipCode()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java deleted file mode 100644 index 5a1f6c4074..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.FileReader; -import java.util.Arrays; -import java.util.List; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class BedsResponseTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - BedsResponse bedsResponse = new BedsResponse() - .withBeds(Arrays.asList(new Bed().withName("Bed1"), new Bed().withName("Bed2"))); - assertEquals(readJson("beds-response.json"), gson.toJson(bedsResponse)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("beds-response.json"))) { - BedsResponse bedsResponse = gson.fromJson(reader, BedsResponse.class); - - List beds = bedsResponse.getBeds(); - assertNotNull(beds); - assertEquals(2, beds.size()); - assertEquals("Bed1", beds.get(0).getName()); - assertEquals("Bed2", beds.get(1).getName()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java deleted file mode 100644 index 2fa2016938..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.FileReader; -import java.util.Arrays; -import java.util.List; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class FamilyStatusTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - FamilyStatus familyStatus = new FamilyStatus().withBeds(Arrays.asList(new BedStatus().withStatus(1L))); - assertEquals(readJson("family-status.json"), gson.toJson(familyStatus)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("family-status.json"))) { - FamilyStatus familyStatus = gson.fromJson(reader, FamilyStatus.class); - - List beds = familyStatus.getBeds(); - assertNotNull(beds); - assertEquals(1, beds.size()); - assertEquals(Long.valueOf(1L), beds.get(0).getStatus()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java deleted file mode 100644 index d36bd3acc8..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.FileReader; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class PauseModeTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - PauseMode pauseMode = new PauseMode().withAccountId("-8888888888888888888").withBedId("-9999999999999999999") - .withPauseMode("off"); - assertEquals(readJson("pause-mode.json"), gson.toJson(pauseMode)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("pause-mode.json"))) { - PauseMode pauseMode = gson.fromJson(reader, PauseMode.class); - assertEquals("-8888888888888888888", pauseMode.getAccountId()); - assertEquals("-9999999999999999999", pauseMode.getBedId()); - assertEquals("off", pauseMode.getPauseMode()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java deleted file mode 100644 index 8b184b6c39..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.io.FileReader; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class SleeperTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - Sleeper sleeper = new Sleeper().withAccountId("-5555555555555555555").withAccountOwner(true).withActive(true) - .withAvatar("").withBedId("-9999999999999999999").withBirthMonth(6).withBirthYear("1970") - .withChild(false).withDuration("").withEmail("alice@domain.com").withEmailValidated(true) - .withFirstName("Alice").withHeight(64).withLastLogin("2017-02-17 20:19:36 CST").withLicenseVersion(6L) - .withMale(false).withSide(1).withSleeperId("-1111111111111111111").withSleepGoal(450) - .withTimezone("US/Pacific").withUsername("alice@domain.com").withWeight(110).withZipCode("90210"); - assertEquals(readJson("sleeper.json"), gson.toJson(sleeper)); - } - - @Test - public void testSerializeLastLoginNull() throws Exception { - Sleeper sleeper = new Sleeper().withLastLogin("null"); - assertEquals(readJson("sleeper-lastlogin-null.json"), gson.toJson(sleeper)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("sleeper.json"))) { - Sleeper sleeper = gson.fromJson(reader, Sleeper.class); - assertEquals("-5555555555555555555", sleeper.getAccountId()); - assertEquals(true, sleeper.isAccountOwner()); - assertEquals(true, sleeper.isActive()); - assertEquals("", sleeper.getAvatar()); - assertEquals("-9999999999999999999", sleeper.getBedId()); - assertEquals(Integer.valueOf(6), sleeper.getBirthMonth()); - assertEquals("1970", sleeper.getBirthYear()); - assertEquals(false, sleeper.isChild()); - assertEquals("", sleeper.getDuration()); - assertEquals("alice@domain.com", sleeper.getEmail()); - assertEquals(true, sleeper.isEmailValidated()); - assertEquals("Alice", sleeper.getFirstName()); - assertEquals(Integer.valueOf(64), sleeper.getHeight()); - assertEquals("2017-02-17 20:19:36 CST", sleeper.getLastLogin()); - assertEquals(Long.valueOf(6L), sleeper.getLicenseVersion()); - assertEquals(false, sleeper.isMale()); - assertEquals(Integer.valueOf(1), sleeper.getSide()); - assertEquals("-1111111111111111111", sleeper.getSleeperId()); - assertEquals(Integer.valueOf(450), sleeper.getSleepGoal()); - assertEquals("US/Pacific", sleeper.getTimezone()); - assertEquals("alice@domain.com", sleeper.getUsername()); - assertEquals(Integer.valueOf(110), sleeper.getWeight()); - assertEquals("90210", sleeper.getZipCode()); - } - } - - @Test - public void testDeserializeLastLoginNull() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("sleeper-lastlogin-null.json"))) { - Sleeper sleeper = gson.fromJson(reader, Sleeper.class); - assertEquals("null", sleeper.getLastLogin()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java deleted file mode 100644 index 118a24a4cc..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.*; - -import java.io.FileReader; -import java.util.Arrays; -import java.util.List; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; -import org.openhab.binding.sleepiq.api.test.AbstractTest; - -import com.google.gson.Gson; - -public class SleepersResponseTest extends AbstractTest { - private static Gson gson; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } - - @Test - public void testSerializeAllFields() throws Exception { - SleepersResponse sleepersResponse = new SleepersResponse() - .withSleepers(Arrays.asList(new Sleeper().withFirstName("Alice"), new Sleeper().withFirstName("Bob"))); - assertEquals(readJson("sleepers-response.json"), gson.toJson(sleepersResponse)); - } - - @Test - public void testDeserializeAllFields() throws Exception { - try (FileReader reader = new FileReader(getTestDataFile("sleepers-response.json"))) { - SleepersResponse sleepersResponse = gson.fromJson(reader, SleepersResponse.class); - - List sleepers = sleepersResponse.getSleepers(); - assertNotNull(sleepers); - assertEquals(2, sleepers.size()); - assertEquals("Alice", sleepers.get(0).getFirstName()); - assertEquals("Bob", sleepers.get(1).getFirstName()); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java deleted file mode 100644 index 3e5d3d14be..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.model; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.time.Duration; - -import org.junit.jupiter.api.Test; - -public class TimeSinceTest { - @Test - public void testWithDuration() { - assertEquals(new TimeSince().withDuration(0, 0, 0, 0).getDuration(), - new TimeSince().withDuration(Duration.parse("PT00H00M00S")).getDuration()); - assertEquals(new TimeSince().withDuration(0, 2, 3, 4).getDuration(), - new TimeSince().withDuration(Duration.parse("PT02H03M04S")).getDuration()); - assertEquals(new TimeSince().withDuration(0, 12, 34, 56).getDuration(), - new TimeSince().withDuration(Duration.parse("PT12H34M56S")).getDuration()); - assertEquals(new TimeSince().withDuration(1, 2, 3, 4).getDuration(), - new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).getDuration()); - assertEquals(new TimeSince().withDuration(12, 23, 34, 45).getDuration(), - new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).getDuration()); - } - - @Test - public void testToString() { - assertEquals("00:00:00", new TimeSince().withDuration(Duration.parse("PT00H00M00S")).toString()); - assertEquals("02:03:04", new TimeSince().withDuration(Duration.parse("PT02H03M04S")).toString()); - assertEquals("12:34:56", new TimeSince().withDuration(Duration.parse("PT12H34M56S")).toString()); - assertEquals("1 d 02:03:04", new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).toString()); - assertEquals("12 d 23:34:45", new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).toString()); - } - - @Test - public void testParse() { - assertEquals(Duration.parse("PT00H00M00S"), TimeSince.parse("00:00:00").getDuration()); - assertEquals(Duration.parse("PT2H3M4S"), TimeSince.parse("02:03:04").getDuration()); - assertEquals(Duration.parse("PT12H34M56S"), TimeSince.parse("12:34:56").getDuration()); - assertEquals(Duration.parse("P1DT2H3M4S"), TimeSince.parse("1 d 02:03:04").getDuration()); - assertEquals(Duration.parse("P12DT23H34M45S"), TimeSince.parse("12 d 23:34:45").getDuration()); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java deleted file mode 100644 index 955f7e2ef8..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2017 Gregory Moyer - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openhab.binding.sleepiq.api.test; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public abstract class AbstractTest { - private static final String RESOURCES_PATH = "src/test/resources/"; - - protected File getTestDataFile(String name) { - return getTestDataPath(name).toFile(); - } - - protected Path getTestDataPath(String name) { - String packageName = this.getClass().getPackage().getName(); - - List paths = new ArrayList<>(); - paths.addAll(Arrays.asList(packageName.split("\\."))); - paths.add(name); - - return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()])); - } - - protected String readJson(String jsonFileName) throws IOException { - return String.join("\n", Files.readAllLines(getTestDataPath(jsonFileName))); - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java deleted file mode 100644 index 1438a5e2c9..0000000000 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2010-2023 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.sleepiq.internal; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; - -import javax.ws.rs.Consumes; -import javax.ws.rs.Produces; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.ext.MessageBodyReader; -import javax.ws.rs.ext.MessageBodyWriter; -import javax.ws.rs.ext.Provider; - -import com.google.gson.Gson; - -/** - * JSON reader/writer for Jersey using GSON. - * - * @author Simon Kaufmann - Initial contribution - * - * @param - */ -@Provider -@Produces(MediaType.APPLICATION_JSON) -@Consumes(MediaType.APPLICATION_JSON) -public class GsonProvider implements MessageBodyReader, MessageBodyWriter { - - private final Gson gson; - - public GsonProvider(Gson gson) { - this.gson = gson; - } - - @Override - public long getSize(T t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return -1; - } - - @Override - public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; - } - - @Override - public void writeTo(T object, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, OutputStream entityStream) - throws IOException, WebApplicationException { - try (OutputStream stream = entityStream) { - entityStream.write(gson.toJson(object).getBytes(StandardCharsets.UTF_8)); - entityStream.flush(); - } - } - - @Override - public boolean isReadable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { - return true; - } - - @Override - public T readFrom(Class type, Type genericType, Annotation[] annotations, MediaType mediaType, - MultivaluedMap httpHeaders, InputStream entityStream) - throws IOException, WebApplicationException { - try (InputStreamReader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) { - return gson.fromJson(reader, type); - } - } -} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQBindingConstants.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQBindingConstants.java index f5eb4642a8..63023921ad 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQBindingConstants.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQBindingConstants.java @@ -31,34 +31,60 @@ public class SleepIQBindingConstants { public static final ThingTypeUID THING_TYPE_CLOUD = new ThingTypeUID(BINDING_ID, "cloud"); // generic thing types - // public static final ThingTypeUID THING_TYPE_SINGLE_BED = new ThingTypeUID(BINDING_ID, "singleBed"); public static final ThingTypeUID THING_TYPE_DUAL_BED = new ThingTypeUID(BINDING_ID, "dualBed"); // List of all Channel ids - // public static final String CHANNEL_BED_IN_BED = "bed#inBed"; public static final String CHANNEL_LEFT_IN_BED = "left#inBed"; public static final String CHANNEL_RIGHT_IN_BED = "right#inBed"; - // public static final String CHANNEL_BED_SLEEP_NUMBER = "bed#sleepNumber"; public static final String CHANNEL_LEFT_SLEEP_NUMBER = "left#sleepNumber"; public static final String CHANNEL_RIGHT_SLEEP_NUMBER = "right#sleepNumber"; - // public static final String CHANNEL_BED_PRESSURE = "bed#pressure"; public static final String CHANNEL_LEFT_PRESSURE = "left#pressure"; public static final String CHANNEL_RIGHT_PRESSURE = "right#pressure"; - // public static final String CHANNEL_BED_LAST_LINK = "bed#lastLink"; public static final String CHANNEL_LEFT_LAST_LINK = "left#lastLink"; public static final String CHANNEL_RIGHT_LAST_LINK = "right#lastLink"; - // public static final String CHANNEL_BED_ALERT_ID = "bed#alertId"; public static final String CHANNEL_LEFT_ALERT_ID = "left#alertId"; public static final String CHANNEL_RIGHT_ALERT_ID = "right#alertId"; - // public static final String CHANNEL_BED_ALERT_DETAILED_MESSAGE = "bed#alertDetailedMessage"; public static final String CHANNEL_LEFT_ALERT_DETAILED_MESSAGE = "left#alertDetailedMessage"; public static final String CHANNEL_RIGHT_ALERT_DETAILED_MESSAGE = "right#alertDetailedMessage"; + public static final String CHANNEL_LEFT_FIRST_NAME = "left#firstName"; + public static final String CHANNEL_RIGHT_FIRST_NAME = "right#firstName"; + + public static final String CHANNEL_LEFT_SLEEP_GOAL_MINUTES = "left#sleepGoalMinutes"; + public static final String CHANNEL_RIGHT_SLEEP_GOAL_MINUTES = "right#sleepGoalMinutes"; + + public static final String CHANNEL_LEFT_PRIVACY_MODE = "left#privacyMode"; + public static final String CHANNEL_RIGHT_PRIVACY_MODE = "right#privacyMode"; + + public static final String CHANNEL_LEFT_TODAY_SLEEP_IQ = "left#todaySleepIQ"; + public static final String CHANNEL_RIGHT_TODAY_SLEEP_IQ = "right#todaySleepIQ"; + + public static final String CHANNEL_LEFT_TODAY_AVG_HEART_RATE = "left#todayAverageHeartRate"; + public static final String CHANNEL_RIGHT_TODAY_AVG_HEART_RATE = "right#todayAverageHeartRate"; + + public static final String CHANNEL_LEFT_TODAY_AVG_RESPIRATION_RATE = "left#todayAverageRespirationRate"; + public static final String CHANNEL_RIGHT_TODAY_AVG_RESPIRATION_RATE = "right#todayAverageRespirationRate"; + + public static final String CHANNEL_LEFT_TODAY_MESSAGE = "left#todayMessage"; + public static final String CHANNEL_RIGHT_TODAY_MESSAGE = "right#todayMessage"; + + public static final String CHANNEL_LEFT_TODAY_SLEEP_DURATION_SECONDS = "left#todaySleepDurationSeconds"; + public static final String CHANNEL_RIGHT_TODAY_SLEEP_DURATION_SECONDS = "right#todaySleepDurationSeconds"; + + public static final String CHANNEL_LEFT_MONTHLY_SLEEP_IQ = "left#monthlySleepIQ"; + public static final String CHANNEL_RIGHT_MONTHLY_SLEEP_IQ = "right#monthlySleepIQ"; + + public static final String CHANNEL_LEFT_MONTHLY_AVG_HEART_RATE = "left#monthlyAverageHeartRate"; + public static final String CHANNEL_RIGHT_MONTHLY_AVG_HEART_RATE = "right#monthlyAverageHeartRate"; + + public static final String CHANNEL_LEFT_MONTHLY_AVG_RESPIRATION_RATE = "left#monthlyAverageRespirationRate"; + public static final String CHANNEL_RIGHT_MONTHLY_AVG_RESPIRATION_RATE = "right#monthlyAverageRespirationRate"; + // List of non-standard Properties public static final String PROPERTY_BASE = "base"; public static final String PROPERTY_KIDS_BED = "kidsBed"; @@ -67,8 +93,4 @@ public class SleepIQBindingConstants { public static final String PROPERTY_PURCHASE_DATE = "purchaseDate"; public static final String PROPERTY_SIZE = "size"; public static final String PROPERTY_SKU = "sku"; - - private SleepIQBindingConstants() { - // utility class - } } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQConfigStatusMessage.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQConfigStatusMessage.java index e4fc45aed0..a599b1a7b8 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQConfigStatusMessage.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQConfigStatusMessage.java @@ -12,12 +12,15 @@ */ package org.openhab.binding.sleepiq.internal; +import org.eclipse.jdt.annotation.NonNullByDefault; + /** * The {@link SleepIQConfigStatusMessage} defines the keys to be used for configuration status messages. * * @author Gregory Moyer - Initial contribution * */ +@NonNullByDefault public interface SleepIQConfigStatusMessage { public static final String USERNAME_MISSING = "missing-username-configuration"; public static final String PASSWORD_MISSING = "missing-password-configuration"; diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQHandlerFactory.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQHandlerFactory.java index 318974b299..7bda6c0002 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQHandlerFactory.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQHandlerFactory.java @@ -20,12 +20,14 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.ws.rs.client.ClientBuilder; - +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.sleepiq.internal.discovery.SleepIQBedDiscoveryService; import org.openhab.binding.sleepiq.internal.handler.SleepIQCloudHandler; import org.openhab.binding.sleepiq.internal.handler.SleepIQDualBedHandler; import org.openhab.core.config.discovery.DiscoveryService; +import org.openhab.core.io.net.http.HttpClientFactory; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingTypeUID; @@ -45,6 +47,7 @@ import org.slf4j.LoggerFactory; * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault @Component(service = ThingHandlerFactory.class, configurationPid = "binding.sleepiq") public class SleepIQHandlerFactory extends BaseThingHandlerFactory { private static final Set SUPPORTED_THING_TYPE_UIDS = Collections @@ -53,13 +56,13 @@ public class SleepIQHandlerFactory extends BaseThingHandlerFactory { private final Logger logger = LoggerFactory.getLogger(SleepIQHandlerFactory.class); - private final ClientBuilder clientBuilder; + private final HttpClient httpClient; private final Map> discoveryServiceReg = new HashMap<>(); @Activate - public SleepIQHandlerFactory(@Reference ClientBuilder clientBuilder) { - this.clientBuilder = clientBuilder; + public SleepIQHandlerFactory(@Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); } @Override @@ -68,26 +71,23 @@ public class SleepIQHandlerFactory extends BaseThingHandlerFactory { } @Override - protected ThingHandler createHandler(final Thing thing) { + protected @Nullable ThingHandler createHandler(final Thing thing) { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); - if (SleepIQCloudHandler.SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID)) { logger.debug("Creating SleepIQ cloud thing handler"); - SleepIQCloudHandler cloudHandler = new SleepIQCloudHandler((Bridge) thing, clientBuilder); + SleepIQCloudHandler cloudHandler = new SleepIQCloudHandler((Bridge) thing, httpClient); registerBedDiscoveryService(cloudHandler); return cloudHandler; } else if (SleepIQDualBedHandler.SUPPORTED_THING_TYPE_UIDS.contains(thingTypeUID)) { logger.debug("Creating SleepIQ dual bed thing handler"); return new SleepIQDualBedHandler(thing); } - return null; } @Override protected void removeHandler(final ThingHandler thingHandler) { logger.debug("Removing SleepIQ thing handler"); - if (thingHandler instanceof SleepIQCloudHandler) { unregisterBedDiscoveryService((SleepIQCloudHandler) thingHandler); } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/BedNotFoundException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/BedNotFoundException.java new file mode 100644 index 0000000000..de653f6b9a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/BedNotFoundException.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link BedNotFoundException} is thrown when a bedId is missing or invalid. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class BedNotFoundException extends SleepIQException { + private static final long serialVersionUID = 1L; + + public BedNotFoundException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/CommunicationException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/CommunicationException.java new file mode 100644 index 0000000000..f25f94a9a0 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/CommunicationException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link CommunicationException} is thrown when there's an error communicating with + * the sleepiq service. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class CommunicationException extends SleepIQException { + private static final long serialVersionUID = 1L; + + public CommunicationException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java new file mode 100644 index 0000000000..861b4a11b7 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java @@ -0,0 +1,166 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import java.net.URI; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * This class represents configuration parameters for using {@link SleepIQ}. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class Configuration { + private String username = ""; + private String password = ""; + + private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com"); + + private boolean logging = false; + + /** + * Get the username on the account. + * + * @return the username + */ + public String getUsername() { + return username; + } + + /** + * Set the username on the account. This should be the username used to + * register with SleepIQ. + * + * @param username + * the value to set + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * Set the username on the account. This should be the username used to + * register with SleepIQ. + * + * @param username + * the value to set + * @return this configuration instance + */ + public Configuration withUsername(String username) { + setUsername(username); + return this; + } + + /** + * Get the password on the account. + * + * @return the password + */ + public String getPassword() { + return password; + } + + /** + * Set the password on the account. This should be the password used to + * register with SleepIQ. + * + * @param password + * the value to set + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * Set the password on the account. This should be the password used to + * register with SleepIQ. + * + * @param password + * the value to set + * @return this configuration instance + */ + public Configuration withPassword(String password) { + setPassword(password); + return this; + } + + /** + * Get the base URI of the SleepIQ cloud service. + * + * @return the base URI + */ + public URI getBaseUri() { + return baseUri; + } + + /** + * Set the base URI of the SleepIQ cloud service. It is unlikely that this + * will need to be changed from its default value. + * + * @param baseUri + * the value to set + */ + public void setBaseUri(URI baseUri) { + this.baseUri = baseUri; + } + + /** + * Set the base URI of the SleepIQ cloud service. It is unlikely that this + * will need to be changed from its default value. + * + * @param baseUri + * the value to set + * @return this configuration instance + */ + public Configuration withBaseUri(URI baseUri) { + setBaseUri(baseUri); + return this; + } + + /** + * Get the logging flag. + * + * @return the logging flag + */ + public boolean isLogging() { + return logging; + } + + /** + * Set the logging flag. When this is set to true, all requests + * and responses will be logged at the {@link Level#INFO} level. This + * includes usernames and passwords! + * + * @param logging + * the value to set + */ + public void setLogging(boolean logging) { + this.logging = logging; + } + + /** + * Set the logging flag. When this is set to true, all requests + * and responses will be logged at the {@link Level#INFO} level. This + * includes usernames and passwords! + * + * @param logging + * the value to set + * @return this configuration instance + */ + public Configuration withLogging(boolean logging) { + setLogging(logging); + return this; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java new file mode 100644 index 0000000000..fcd957c1de --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link LoginException} is thrown when there's a failure to log + * into the sleepiq service. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class LoginException extends SleepIQException { + private static final long serialVersionUID = 1L; + + public LoginException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/ResponseFormatException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/ResponseFormatException.java new file mode 100644 index 0000000000..07a18b8c21 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/ResponseFormatException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link LoginException} is thrown when a badly formatted response is + * received from the sleepiq service. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class ResponseFormatException extends SleepIQException { + private static final long serialVersionUID = 1L; + + public ResponseFormatException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQ.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQ.java new file mode 100644 index 0000000000..ca6a9bf74d --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQ.java @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.dto.FamilyStatusResponse; +import org.openhab.binding.sleepiq.internal.api.dto.LoginInfo; +import org.openhab.binding.sleepiq.internal.api.dto.PauseModeResponse; +import org.openhab.binding.sleepiq.internal.api.dto.SleepDataResponse; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.enums.Side; +import org.openhab.binding.sleepiq.internal.api.enums.SleepDataInterval; +import org.openhab.binding.sleepiq.internal.api.impl.SleepIQImpl; + +/** + * This interface is the main API to access the SleepIQ system. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public interface SleepIQ { + /** + * Login to the {@link Configuration configured} account. This method is not + * required to be called before other methods because all methods must + * ensure login before acting. However, when the only desired action is to + * login and not retrieve other data, this method is the most efficient + * option. + * + * @return basic information about the logged in user + * @throws UnauthorizedException + * if the credentials provided are not valid + * @throws LoginException + * if the login request fails for any reason other than bad + * credentials (including missing credentials) + */ + public @Nullable LoginInfo login() throws LoginException, UnauthorizedException; + + /** + * Get a list of beds connected to the account. + * + * @return the list of beds + * @throws LoginException + * if the login request fails for any reason other than bad + * credentials (including missing credentials) + * @throws SleepIQException + */ + public List getBeds() throws LoginException, SleepIQException, BedNotFoundException; + + /** + * Get a list of sleepers registered to this account for beds or bed positions + * (left or right side). + * + * @return the list of sleepers + * @throws LoginException + * @throws SleepIQException + */ + public List getSleepers() throws LoginException, SleepIQException; + + /** + * Get the status of all beds and all air chambers registered to this + * account. + * + * @return the complete status of beds on the account + * @throws LoginException + * @throws SleepIQException + */ + public FamilyStatusResponse getFamilyStatus() throws LoginException, SleepIQException; + + /** + * Get the Sleep Data for a sleeper registered to this account. + * + * @param sleeperId the sleeper Id to query + * @param interval The time period for which data is to be queried + * @return the Sleep Data + * @throws BedNotFoundException + * if the bed identifier was not found on the account + * @throws LoginException + * @throws SleepIQException + */ + public SleepDataResponse getSleepData(String sleeperId, SleepDataInterval interval) + throws BedNotFoundException, LoginException, SleepIQException; + + /** + * Get the status of "pause mode" (disabling SleepIQ data upload) for a + * specific bed. A bed in pause mode will send no information to the SleepIQ + * cloud services. For example, if a sleeper is in bed and disables SleepIQ + * (enables pause mode), the service will continue to report that the bed is + * occupied even after the sleeper exits the bed until pause mode is + * disabled. + * + * @return the status of pause mode for the specified bed + * @throws BedNotFoundException + * if the bed identifier was not found on the account + * @throws LoginException + * @throws SleepIQException + */ + public PauseModeResponse getPauseMode(String bedId) throws BedNotFoundException, LoginException, SleepIQException; + + /** + * Set the sleep number for a chamber of a bed + * + * @param bedId the unique identifier of the bed + * @param side thethe chamber of the bed + * @param sleepNumber the new sleep number + * + * @throws LoginException + * @throws SleepIQException + */ + public void setSleepNumber(String bedId, Side side, int sleepNumber) throws LoginException, SleepIQException; + + /** + * Set the pause (privacy) mode for a bed + * + * @param bedId the unique identifier of the bed + * + * @throws LoginException + * @throws SleepIQException + */ + public void setPauseMode(String bedId, boolean command) throws LoginException, SleepIQException; + + /** + * Create a default implementation instance of this interface. Each call to + * this method will create a new object. + * + * @param config the configuration to use for the new instance + * @param httpClient handle to the Jetty http client + * @return a concrete implementation of this interface + */ + public static SleepIQ create(Configuration config, HttpClient httpClient) { + return new SleepIQImpl(config, httpClient); + } + + /** + * Close down the cloud service + */ + public void shutdown(); +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQException.java new file mode 100644 index 0000000000..bf463e46f4 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link SleepIQException} is the base exception class from which other + * sleepiq exceptions are derived. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class SleepIQException extends Exception { + private static final long serialVersionUID = 1L; + + public SleepIQException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/UnauthorizedException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/UnauthorizedException.java new file mode 100644 index 0000000000..98a47781d5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/UnauthorizedException.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link UnauthorizedException} is thrown when a login to the sleepiq service + * is unauthorized to use the API. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class UnauthorizedException extends LoginException { + private static final long serialVersionUID = 1L; + + public UnauthorizedException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java new file mode 100644 index 0000000000..c8342cc9e5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java @@ -0,0 +1,400 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.time.ZonedDateTime; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link Bed} holds the bed response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class Bed { + private ZonedDateTime registrationDate; + private String sleeperRightId; + private String base; + private Long returnRequestStatus; + private String size; + private String name; + private String serial; + @SerializedName("isKidsBed") + private Boolean kidsBed; + private Boolean dualSleep; + private String bedId; + private Long status; + private String sleeperLeftId; + private String version; + private String accountId; + private String timezone; + private String model; + private ZonedDateTime purchaseDate; + private String macAddress; + private String sku; + @SerializedName("zipcode") + private String zipCode; + private String reference; + + public ZonedDateTime getRegistrationDate() { + return registrationDate; + } + + public void setRegistrationDate(ZonedDateTime registrationDate) { + this.registrationDate = registrationDate; + } + + public Bed withRegistrationDate(ZonedDateTime registrationDate) { + setRegistrationDate(registrationDate); + return this; + } + + public String getSleeperRightId() { + return sleeperRightId; + } + + public void setSleeperRightId(String sleeperRightId) { + this.sleeperRightId = sleeperRightId; + } + + public Bed withSleeperRightId(String sleeperRightId) { + setSleeperRightId(sleeperRightId); + return this; + } + + public String getBase() { + return base; + } + + public void setBase(String base) { + this.base = base; + } + + public Bed withBase(String base) { + setBase(base); + return this; + } + + public Long getReturnRequestStatus() { + return returnRequestStatus; + } + + public void setReturnRequestStatus(Long returnRequestStatus) { + this.returnRequestStatus = returnRequestStatus; + } + + public Bed withReturnRequestStatus(Long returnRequestStatus) { + setReturnRequestStatus(returnRequestStatus); + return this; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public Bed withSize(String size) { + setSize(size); + return this; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Bed withName(String name) { + setName(name); + return this; + } + + public String getSerial() { + return serial; + } + + public void setSerial(String serial) { + this.serial = serial; + } + + public Bed withSerial(String serial) { + setSerial(serial); + return this; + } + + public Boolean isKidsBed() { + return kidsBed; + } + + public void setKidsBed(Boolean kidsBed) { + this.kidsBed = kidsBed; + } + + public Bed withKidsBed(Boolean kidsBed) { + setKidsBed(kidsBed); + return this; + } + + public Boolean isDualSleep() { + return dualSleep; + } + + public void setDualSleep(Boolean dualSleep) { + this.dualSleep = dualSleep; + } + + public Bed withDualSleep(Boolean dualSleep) { + setDualSleep(dualSleep); + return this; + } + + public String getBedId() { + return bedId; + } + + public void setBedId(String bedId) { + this.bedId = bedId; + } + + public Bed withBedId(String bedId) { + setBedId(bedId); + return this; + } + + public Long getStatus() { + return status; + } + + public void setStatus(Long status) { + this.status = status; + } + + public Bed withStatus(Long status) { + setStatus(status); + return this; + } + + public String getSleeperLeftId() { + return sleeperLeftId; + } + + public void setSleeperLeftId(String sleeperLeftId) { + this.sleeperLeftId = sleeperLeftId; + } + + public Bed withSleeperLeftId(String sleeperLeftId) { + setSleeperLeftId(sleeperLeftId); + return this; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public Bed withVersion(String version) { + setVersion(version); + return this; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public Bed withAccountId(String accountId) { + setAccountId(accountId); + return this; + } + + public String getTimezone() { + return timezone; + } + + public void setTimezone(String timezone) { + this.timezone = timezone; + } + + public Bed withTimezone(String timezone) { + setTimezone(timezone); + return this; + } + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public Bed withModel(String model) { + setModel(model); + return this; + } + + public ZonedDateTime getPurchaseDate() { + return purchaseDate; + } + + public void setPurchaseDate(ZonedDateTime purchaseDate) { + this.purchaseDate = purchaseDate; + } + + public Bed withPurchaseDate(ZonedDateTime purchaseDate) { + setPurchaseDate(purchaseDate); + return this; + } + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public Bed withMacAddress(String macAddress) { + setMacAddress(macAddress); + return this; + } + + public String getSku() { + return sku; + } + + public void setSku(String sku) { + this.sku = sku; + } + + public Bed withSku(String sku) { + setSku(sku); + return this; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public Bed withZipCode(String zipCode) { + setZipCode(zipCode); + return this; + } + + public String getReference() { + return reference; + } + + public void setReference(String reference) { + this.reference = reference; + } + + public Bed withReference(String reference) { + setReference(reference); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Bed)) { + return false; + } + Bed other = (Bed) obj; + if (bedId == null) { + if (other.bedId != null) { + return false; + } + } else if (!bedId.equals(other.bedId)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Bed [registrationDate="); + builder.append(registrationDate); + builder.append(", sleeperRightId="); + builder.append(sleeperRightId); + builder.append(", base="); + builder.append(base); + builder.append(", returnRequestStatus="); + builder.append(returnRequestStatus); + builder.append(", size="); + builder.append(size); + builder.append(", name="); + builder.append(name); + builder.append(", serial="); + builder.append(serial); + builder.append(", kidsBed="); + builder.append(kidsBed); + builder.append(", dualSleep="); + builder.append(dualSleep); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", status="); + builder.append(status); + builder.append(", sleeperLeftId="); + builder.append(sleeperLeftId); + builder.append(", version="); + builder.append(version); + builder.append(", accountId="); + builder.append(accountId); + builder.append(", timezone="); + builder.append(timezone); + builder.append(", model="); + builder.append(model); + builder.append(", purchaseDate="); + builder.append(purchaseDate); + builder.append(", macAddress="); + builder.append(macAddress); + builder.append(", sku="); + builder.append(sku); + builder.append(", zipCode="); + builder.append(zipCode); + builder.append(", reference="); + builder.append(reference); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java new file mode 100644 index 0000000000..72844ffa90 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link BedSideStatus} holds the BedSideStatus response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class BedSideStatus { + @SerializedName("isInBed") + private Boolean inBed; + private String alertDetailedMessage; + private Integer sleepNumber; + private Long alertId; + private TimeSince lastLink; + private Integer pressure; // appears to be in kPa + + public Boolean isInBed() { + return inBed; + } + + public void setInBed(Boolean inBed) { + this.inBed = inBed; + } + + public BedSideStatus withInBed(Boolean inBed) { + setInBed(inBed); + return this; + } + + public String getAlertDetailedMessage() { + return alertDetailedMessage; + } + + public void setAlertDetailedMessage(String alertDetailedMessage) { + this.alertDetailedMessage = alertDetailedMessage; + } + + public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) { + setAlertDetailedMessage(alertDetailedMessage); + return this; + } + + public Integer getSleepNumber() { + return sleepNumber; + } + + public void setSleepNumber(Integer sleepNumber) { + this.sleepNumber = sleepNumber; + } + + public BedSideStatus withSleepNumber(Integer sleepNumber) { + setSleepNumber(sleepNumber); + return this; + } + + public Long getAlertId() { + return alertId; + } + + public void setAlertId(Long alertId) { + this.alertId = alertId; + } + + public BedSideStatus withAlertId(Long alertId) { + setAlertId(alertId); + return this; + } + + public TimeSince getLastLink() { + return lastLink; + } + + public void setLastLink(TimeSince lastLink) { + this.lastLink = lastLink; + } + + public BedSideStatus withLastLink(TimeSince lastLink) { + setLastLink(lastLink); + return this; + } + + public Integer getPressure() { + return pressure; + } + + public void setPressure(Integer pressure) { + this.pressure = pressure; + } + + public BedSideStatus withPressure(Integer pressure) { + setPressure(pressure); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode()); + result = prime * result + ((alertId == null) ? 0 : alertId.hashCode()); + result = prime * result + ((inBed == null) ? 0 : inBed.hashCode()); + result = prime * result + ((lastLink == null) ? 0 : lastLink.hashCode()); + result = prime * result + ((pressure == null) ? 0 : pressure.hashCode()); + result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof BedSideStatus)) { + return false; + } + BedSideStatus other = (BedSideStatus) obj; + if (alertDetailedMessage == null) { + if (other.alertDetailedMessage != null) { + return false; + } + } else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) { + return false; + } + if (alertId == null) { + if (other.alertId != null) { + return false; + } + } else if (!alertId.equals(other.alertId)) { + return false; + } + if (inBed == null) { + if (other.inBed != null) { + return false; + } + } else if (!inBed.equals(other.inBed)) { + return false; + } + if (lastLink == null) { + if (other.lastLink != null) { + return false; + } + } else if (!lastLink.equals(other.lastLink)) { + return false; + } + if (pressure == null) { + if (other.pressure != null) { + return false; + } + } else if (!pressure.equals(other.pressure)) { + return false; + } + if (sleepNumber == null) { + if (other.sleepNumber != null) { + return false; + } + } else if (!sleepNumber.equals(other.sleepNumber)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BedSideStatus [inBed="); + builder.append(inBed); + builder.append(", alertDetailedMessage="); + builder.append(alertDetailedMessage); + builder.append(", sleepNumber="); + builder.append(sleepNumber); + builder.append(", alertId="); + builder.append(alertId); + builder.append(", lastLink="); + builder.append(lastLink); + builder.append(", pressure="); + builder.append(pressure); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java new file mode 100644 index 0000000000..c5f25ab119 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java @@ -0,0 +1,122 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +/** + * The {@link BedStatus} holds the BedStatus response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class BedStatus { + private Long status; + private String bedId; + private BedSideStatus leftSide; + private BedSideStatus rightSide; + + public Long getStatus() { + return status; + } + + public void setStatus(Long status) { + this.status = status; + } + + public BedStatus withStatus(Long status) { + setStatus(status); + return this; + } + + public String getBedId() { + return bedId; + } + + public void setBedId(String bedId) { + this.bedId = bedId; + } + + public BedStatus withBedId(String bedId) { + setBedId(bedId); + return this; + } + + public BedSideStatus getLeftSide() { + return leftSide; + } + + public void setLeftSide(BedSideStatus leftSide) { + this.leftSide = leftSide; + } + + public BedStatus withLeftSide(BedSideStatus leftSide) { + setLeftSide(leftSide); + return this; + } + + public BedSideStatus getRightSide() { + return rightSide; + } + + public void setRightSide(BedSideStatus rightSide) { + this.rightSide = rightSide; + } + + public BedStatus withRightSide(BedSideStatus rightSide) { + setRightSide(rightSide); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof BedStatus)) { + return false; + } + BedStatus other = (BedStatus) obj; + if (bedId == null) { + if (other.bedId != null) { + return false; + } + } else if (!bedId.equals(other.bedId)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BedStatus [status="); + builder.append(status); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", leftSide="); + builder.append(leftSide); + builder.append(", rightSide="); + builder.append(rightSide); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedsResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedsResponse.java new file mode 100644 index 0000000000..9cdaa4dab7 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedsResponse.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.util.List; + +/** + * The {@link BedsResponse} holds the BedsResponse response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class BedsResponse { + private List beds; + + public List getBeds() { + return beds; + } + + public void setBeds(List beds) { + this.beds = beds; + } + + public BedsResponse withBeds(List beds) { + setBeds(beds); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((beds == null) ? 0 : beds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof BedsResponse)) { + return false; + } + BedsResponse other = (BedsResponse) obj; + if (beds == null) { + if (other.beds != null) { + return false; + } + } else if (!beds.equals(other.beds)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("BedsResponse [beds="); + builder.append(beds); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Error.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Error.java new file mode 100644 index 0000000000..6865067ae1 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Error.java @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link Error} holds the Error response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class Error { + @SerializedName("Code") + private Long code; + @SerializedName("Message") + private String message; + + public Long getCode() { + return code; + } + + public void setCode(Long code) { + this.code = code; + } + + public Error withCode(Long code) { + setCode(code); + return this; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public Error withMessage(String message) { + setMessage(message); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((code == null) ? 0 : code.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Error)) { + return false; + } + Error other = (Error) obj; + if (code == null) { + if (other.code != null) { + return false; + } + } else if (!code.equals(other.code)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Error [code="); + builder.append(code); + builder.append(", message="); + builder.append(message); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Failure.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Failure.java new file mode 100644 index 0000000000..028055c4b3 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Failure.java @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link Failure} holds the Failure response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class Failure { + @SerializedName("Error") + private Error error; + + public Error getError() { + return error; + } + + public void setError(Error error) { + this.error = error; + } + + public Failure withError(Error error) { + setError(error); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((error == null) ? 0 : error.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Failure)) { + return false; + } + Failure other = (Failure) obj; + if (error == null) { + if (other.error != null) { + return false; + } + } else if (!error.equals(other.error)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Failure [error="); + builder.append(error); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/FamilyStatusResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/FamilyStatusResponse.java new file mode 100644 index 0000000000..b0f90c12dd --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/FamilyStatusResponse.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.util.List; + +/** + * The {@link FamilyStatusResponse} holds the FamilyStatusResponse response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class FamilyStatusResponse { + private List beds; + + public List getBeds() { + return beds; + } + + public void setBeds(List beds) { + this.beds = beds; + } + + public FamilyStatusResponse withBeds(List beds) { + setBeds(beds); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((beds == null) ? 0 : beds.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof FamilyStatusResponse)) { + return false; + } + FamilyStatusResponse other = (FamilyStatusResponse) obj; + if (beds == null) { + if (other.beds != null) { + return false; + } + } else if (!beds.equals(other.beds)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("FamilyStatus [beds="); + builder.append(beds); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java new file mode 100644 index 0000000000..9f51fc92f7 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +/** + * The {@link LoginInfo} holds the LoginInfo response from the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class LoginInfo { + private String userId; + private String key; + private Long registrationState; + private Long edpLoginStatus; + private String edpLoginMessage; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public LoginInfo withUserId(String userId) { + setUserId(userId); + return this; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public LoginInfo withKey(String key) { + setKey(key); + return this; + } + + public Long getRegistrationState() { + return registrationState; + } + + public void setRegistrationState(Long registrationState) { + this.registrationState = registrationState; + } + + public LoginInfo withRegistrationState(Long registrationState) { + setRegistrationState(registrationState); + return this; + } + + public Long getEdpLoginStatus() { + return edpLoginStatus; + } + + public void setEdpLoginStatus(Long edpLoginStatus) { + this.edpLoginStatus = edpLoginStatus; + } + + public LoginInfo withEdpLoginStatus(Long edpLoginStatus) { + setEdpLoginStatus(edpLoginStatus); + return this; + } + + public String getEdpLoginMessage() { + return edpLoginMessage; + } + + public void setEdpLoginMessage(String edpLoginMessage) { + this.edpLoginMessage = edpLoginMessage; + } + + public LoginInfo withEdpLoginMessage(String edpLoginMessage) { + setEdpLoginMessage(edpLoginMessage); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + (int) (registrationState ^ (registrationState >>> 32)); + result = prime * result + ((userId == null) ? 0 : userId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof LoginInfo)) { + return false; + } + LoginInfo other = (LoginInfo) obj; + if (key == null) { + if (other.key != null) { + return false; + } + } else if (!key.equals(other.key)) { + return false; + } + if (!registrationState.equals(other.registrationState)) { + return false; + } + if (userId == null) { + if (other.userId != null) { + return false; + } + } else if (!userId.equals(other.userId)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("LoginInfo [userId="); + builder.append(userId); + builder.append(", key="); + builder.append(key); + builder.append(", registrationState="); + builder.append(registrationState); + builder.append(", edpLoginStatus="); + builder.append(edpLoginStatus); + builder.append(", edpLoginMessage="); + builder.append(edpLoginMessage); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java new file mode 100644 index 0000000000..6cbe4d1121 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +/** + * The {@link LoginRequest} holds the Login request sent to the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +public class LoginRequest { + private String login; + private String password; + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public LoginRequest withLogin(String login) { + setLogin(login); + return this; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public LoginRequest withPassword(String password) { + setPassword(password); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((login == null) ? 0 : login.hashCode()); + result = prime * result + ((password == null) ? 0 : password.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof LoginRequest)) { + return false; + } + LoginRequest other = (LoginRequest) obj; + if (login == null) { + if (other.login != null) { + return false; + } + } else if (!login.equals(other.login)) { + return false; + } + if (password == null) { + if (other.password != null) { + return false; + } + } else if (!password.equals(other.password)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("LoginRequest [login="); + builder.append(login); + builder.append(", password="); + builder.append(password); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeRequest.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeRequest.java new file mode 100644 index 0000000000..f536d800c1 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeRequest.java @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +/** + * The {@link PauseModeRequest} holds the request to pause the bed data collection. + * + * @author Mark Hilbush - Initial contribution + */ +public class PauseModeRequest { + private String mode; + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public PauseModeRequest withMode(String mode) { + setMode(mode); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mode == null) ? 0 : mode.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof PauseModeRequest)) { + return false; + } + PauseModeRequest other = (PauseModeRequest) obj; + if (mode == null) { + if (other.mode != null) { + return false; + } + } else if (!mode.equals(other.mode)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SleepNumberRequest [mode="); + builder.append(mode); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeResponse.java new file mode 100644 index 0000000000..966093bde9 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeResponse.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +/** + * The {@link PauseModeResponse} holds the response to the request to pause the bed data collection. + * + * @author Mark Hilbush - Initial contribution + */ +public class PauseModeResponse { + private String accountId; + private String bedId; + private String pauseMode; + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public PauseModeResponse withAccountId(String accountId) { + setAccountId(accountId); + return this; + } + + public String getBedId() { + return bedId; + } + + public void setBedId(String bedId) { + this.bedId = bedId; + } + + public PauseModeResponse withBedId(String bedId) { + setBedId(bedId); + return this; + } + + public String getPauseMode() { + return pauseMode; + } + + public void setPauseMode(String pauseMode) { + this.pauseMode = pauseMode; + } + + public PauseModeResponse withPauseMode(String pauseMode) { + setPauseMode(pauseMode); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((accountId == null) ? 0 : accountId.hashCode()); + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof PauseModeResponse)) { + return false; + } + PauseModeResponse other = (PauseModeResponse) obj; + if (accountId == null) { + if (other.accountId != null) { + return false; + } + } else if (!accountId.equals(other.accountId)) { + return false; + } + if (bedId == null) { + if (other.bedId != null) { + return false; + } + } else if (!bedId.equals(other.bedId)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PauseMode [accountId="); + builder.append(accountId); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", pauseMode="); + builder.append(pauseMode); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataDay.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataDay.java new file mode 100644 index 0000000000..72ee26f13f --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataDay.java @@ -0,0 +1,47 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.time.LocalDate; +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link SleepDataDay} holds the information for a daily sleep session. + * + * @author Mark Hilbush - Initial contribution + */ +public class SleepDataDay { + + @SerializedName("date") + private LocalDate date; + + @SerializedName("message") + private String dailyMessage; + + @SerializedName("sessions") + private List dailySessions; + + public LocalDate getDate() { + return date; + } + + public String getMessage() { + return dailyMessage; + } + + public List getDailySessions() { + return dailySessions; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataResponse.java new file mode 100644 index 0000000000..c8a36e72d5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataResponse.java @@ -0,0 +1,115 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.util.List; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link SleepDataResponse} holds the response to a request for sleep data. + * + * @author Mark Hilbush - Initial contribution + */ +public class SleepDataResponse { + @SerializedName("sleeperId") + private String sleeperId; + + @SerializedName("avgSleepIQ") + private Integer averageSleepIQ; + + @SerializedName("avgHeartRate") + private Integer averageHeartRate; + + @SerializedName("avgRespirationRate") + private Integer averageResperationRate; + + @SerializedName("inBed") + private Integer totalInBedSeconds; + + @SerializedName("outOfBed") + private Integer totalOutOfBedSeconds; + + @SerializedName("restful") + private Integer totalRestfulSeconds; + + @SerializedName("restless") + private Integer totalRestlessSeconds; + + @SerializedName("sleepData") + private List sleepDataDays; + + public String getSleeperId() { + return sleeperId; + } + + public Integer getAverageSleepIQ() { + return averageSleepIQ; + } + + public Integer getAverageHeartRate() { + return averageHeartRate; + } + + public Integer getAverageRespirationRate() { + return averageResperationRate; + } + + public Integer getTotalSleepSessionTime() { + return totalInBedSeconds + totalOutOfBedSeconds; + } + + public Integer getTotalInBedSeconds() { + return totalInBedSeconds; + } + + public Integer getTotalOutOfBedSeconds() { + return totalOutOfBedSeconds; + } + + public Integer getTotalRestfulSeconds() { + return totalRestfulSeconds; + } + + public Integer getTotalRestlessSeconds() { + return totalRestlessSeconds; + } + + public List getSleepDataDays() { + return sleepDataDays; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SleepDataResponse [sleepData="); + builder.append("averageSleepIQ="); + builder.append(averageSleepIQ); + builder.append(", averageHeartRate="); + builder.append(averageHeartRate); + builder.append(", averageResperationRate="); + builder.append(averageResperationRate); + builder.append(", totalInBedSeconds="); + builder.append(totalInBedSeconds); + builder.append(", totalOutOfBedSeconds="); + builder.append(totalOutOfBedSeconds); + builder.append(", totalRestfulSeconds="); + builder.append(totalRestfulSeconds); + builder.append(", totalRestlessSeconds="); + builder.append(totalRestlessSeconds); + builder.append(", totalSleepSessionTime="); + builder.append(getTotalSleepSessionTime()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataSession.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataSession.java new file mode 100644 index 0000000000..be6cd94de7 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataSession.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link SleepDataSession} holds the data for a sleep session. + * + * @author Mark Hilbush - Initial contribution + */ +public class SleepDataSession { + + @SerializedName("avgSleepIQ") + private Integer sessionAverageSleepIQ; + + @SerializedName("avgHeartRate") + private Integer sessionAverageHeartRate; + + @SerializedName("avgRespirationRate") + private Integer sessionAverageRespirationRate; + + @SerializedName("isFinalized") + private boolean sessionIsFinalized; + + @SerializedName("totalSleepSessionTime") + private Integer sessionTotalSeconds; + + @SerializedName("inBed") + private Integer sessionInBedSeconds; + + @SerializedName("outOfBed") + private Integer sessionOutOfBedSeconds; + + @SerializedName("restful") + private Integer sessionRestfulSeconds; + + @SerializedName("restless") + private Integer sessionRestlessSeconds; + + public Integer getSessionAverageSleepIQ() { + return sessionAverageSleepIQ; + } + + public Integer getSessionAverageHeartRate() { + return sessionAverageHeartRate; + } + + public Integer getSessionAverageRespirationRate() { + return sessionAverageRespirationRate; + } + + public Boolean sessionIsFinalized() { + return sessionIsFinalized; + } + + public Integer getSessionTotalSeconds() { + return sessionTotalSeconds; + } + + public Integer getSessionInBedSeconds() { + return sessionInBedSeconds; + } + + public Integer getSessionOutOfBedSeconds() { + return sessionOutOfBedSeconds; + } + + public Integer getSessionRestfulSeconds() { + return sessionRestfulSeconds; + } + + public Integer getSessionRestlessSeconds() { + return sessionRestlessSeconds; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepNumberRequest.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepNumberRequest.java new file mode 100644 index 0000000000..b07a2ffe53 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepNumberRequest.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import org.openhab.binding.sleepiq.internal.api.enums.Side; + +/** + * The {@link SleepNumberRequest} holds the information used to set the sleep number + * for a bed side. + * + * @author Gregory Moyer - Initial contribution + */ +public class SleepNumberRequest { + private String bedId; + private Integer sleepNumber; + private Side side; + + public String getBedId() { + return bedId; + } + + public void setBedId(String bedId) { + this.bedId = bedId; + } + + public SleepNumberRequest withBedId(String bedId) { + setBedId(bedId); + return this; + } + + public Integer getSleepNumber() { + return sleepNumber; + } + + public void setSleepNumber(Integer sleepNumber) { + this.sleepNumber = sleepNumber; + } + + public SleepNumberRequest withSleepNumber(Integer sleepNumber) { + setSleepNumber(sleepNumber); + return this; + } + + public Side getSide() { + return side; + } + + public void setSide(Side side) { + this.side = side; + } + + public SleepNumberRequest withSide(Side side) { + setSide(side); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); + result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode()); + result = prime * result + ((side == null) ? 0 : side.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SleepNumberRequest)) { + return false; + } + SleepNumberRequest other = (SleepNumberRequest) obj; + if (bedId == null) { + if (other.bedId != null) { + return false; + } + } else if (!bedId.equals(other.bedId)) { + return false; + } + if (sleepNumber == null) { + if (other.sleepNumber != null) { + return false; + } + } else if (sleepNumber.equals(other.sleepNumber)) { + return false; + } + if (side == null) { + if (other.side != null) { + return false; + } + } else if (!side.equals(other.side)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SleepNumberRequest [bedId="); + builder.append(bedId); + builder.append(", sleepNumber="); + builder.append(sleepNumber); + builder.append(", side="); + builder.append(side); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java new file mode 100644 index 0000000000..d10b6c4e63 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java @@ -0,0 +1,434 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import org.openhab.binding.sleepiq.internal.api.enums.Side; + +import com.google.gson.annotations.SerializedName; + +/** + * The {@link Sleeper} holds the information about the sleeper that's + * associated with a bed side. + * + * @author Gregory Moyer - Initial contribution + */ +public class Sleeper { + private String firstName; + private Boolean active; + private Boolean emailValidated; + @SerializedName("isChild") + private Boolean child; + private String bedId; + private String birthYear; + private String zipCode; + private String timezone; + @SerializedName("isMale") + private Boolean male; + private Integer weight; // lbs + private String duration; + private String sleeperId; + private Integer height; // inches + private Long licenseVersion; + private String username; + private Integer birthMonth; // 0-based; 12 means not entered? + private Integer sleepGoal; + @SerializedName("isAccountOwner") + private Boolean accountOwner; + private String accountId; + private String email; + private String avatar; + private String lastLogin; // should be ZonedDateTime but provider passes string "null" when missing + private Side side; // 0=left; 1=right + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public Sleeper withFirstName(String firstName) { + setFirstName(firstName); + return this; + } + + public Boolean isActive() { + return active; + } + + public void setActive(Boolean active) { + this.active = active; + } + + public Sleeper withActive(Boolean active) { + setActive(active); + return this; + } + + public Boolean isEmailValidated() { + return emailValidated; + } + + public void setEmailValidated(Boolean emailValidated) { + this.emailValidated = emailValidated; + } + + public Sleeper withEmailValidated(Boolean emailValidated) { + setEmailValidated(emailValidated); + return this; + } + + public Boolean isChild() { + return child; + } + + public void setChild(Boolean child) { + this.child = child; + } + + public Sleeper withChild(Boolean child) { + setChild(child); + return this; + } + + public String getBedId() { + return bedId; + } + + public void setBedId(String bedId) { + this.bedId = bedId; + } + + public Sleeper withBedId(String bedId) { + setBedId(bedId); + return this; + } + + public String getBirthYear() { + return birthYear; + } + + public void setBirthYear(String birthYear) { + this.birthYear = birthYear; + } + + public Sleeper withBirthYear(String birthYear) { + setBirthYear(birthYear); + return this; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public Sleeper withZipCode(String zipCode) { + setZipCode(zipCode); + return this; + } + + public String getTimezone() { + return timezone; + } + + public void setTimezone(String timezone) { + this.timezone = timezone; + } + + public Sleeper withTimezone(String timezone) { + setTimezone(timezone); + return this; + } + + public Boolean isMale() { + return male; + } + + public void setMale(Boolean male) { + this.male = male; + } + + public Sleeper withMale(Boolean male) { + setMale(male); + return this; + } + + public Integer getWeight() { + return weight; + } + + public void setWeight(Integer weight) { + this.weight = weight; + } + + public Sleeper withWeight(Integer weight) { + setWeight(weight); + return this; + } + + public String getDuration() { + return duration; + } + + public void setDuration(String duration) { + this.duration = duration; + } + + public Sleeper withDuration(String duration) { + setDuration(duration); + return this; + } + + public String getSleeperId() { + return sleeperId; + } + + public void setSleeperId(String sleeperId) { + this.sleeperId = sleeperId; + } + + public Sleeper withSleeperId(String sleeperId) { + setSleeperId(sleeperId); + return this; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + public Sleeper withHeight(Integer height) { + setHeight(height); + return this; + } + + public Long getLicenseVersion() { + return licenseVersion; + } + + public void setLicenseVersion(Long licenseVersion) { + this.licenseVersion = licenseVersion; + } + + public Sleeper withLicenseVersion(Long licenseVersion) { + setLicenseVersion(licenseVersion); + return this; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public Sleeper withUsername(String username) { + setUsername(username); + return this; + } + + public Integer getBirthMonth() { + return birthMonth; + } + + public void setBirthMonth(Integer birthMonth) { + this.birthMonth = birthMonth; + } + + public Sleeper withBirthMonth(Integer birthMonth) { + setBirthMonth(birthMonth); + return this; + } + + public Integer getSleepGoal() { + return sleepGoal; + } + + public void setSleepGoal(Integer sleepGoal) { + this.sleepGoal = sleepGoal; + } + + public Sleeper withSleepGoal(Integer sleepGoal) { + setSleepGoal(sleepGoal); + return this; + } + + public Boolean isAccountOwner() { + return accountOwner; + } + + public void setAccountOwner(Boolean accountOwner) { + this.accountOwner = accountOwner; + } + + public Sleeper withAccountOwner(Boolean accountOwner) { + setAccountOwner(accountOwner); + return this; + } + + public String getAccountId() { + return accountId; + } + + public void setAccountId(String accountId) { + this.accountId = accountId; + } + + public Sleeper withAccountId(String accountId) { + setAccountId(accountId); + return this; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public Sleeper withEmail(String email) { + setEmail(email); + return this; + } + + public String getAvatar() { + return avatar; + } + + public void setAvatar(String avatar) { + this.avatar = avatar; + } + + public Sleeper withAvatar(String avatar) { + setAvatar(avatar); + return this; + } + + public String getLastLogin() { + return lastLogin; + } + + public void setLastLogin(String lastLogin) { + this.lastLogin = lastLogin; + } + + public Sleeper withLastLogin(String lastLogin) { + setLastLogin(lastLogin); + return this; + } + + public Side getSide() { + return side; + } + + public void setSide(Side side) { + this.side = side; + } + + public Sleeper withSide(Side side) { + setSide(side); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof Sleeper)) { + return false; + } + Sleeper other = (Sleeper) obj; + if (sleeperId == null) { + if (other.sleeperId != null) { + return false; + } + } else if (!sleeperId.equals(other.sleeperId)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Sleeper [firstName="); + builder.append(firstName); + builder.append(", active="); + builder.append(active); + builder.append(", emailValidated="); + builder.append(emailValidated); + builder.append(", child="); + builder.append(child); + builder.append(", bedId="); + builder.append(bedId); + builder.append(", birthYear="); + builder.append(birthYear); + builder.append(", zipCode="); + builder.append(zipCode); + builder.append(", timezone="); + builder.append(timezone); + builder.append(", male="); + builder.append(male); + builder.append(", weight="); + builder.append(weight); + builder.append(", duration="); + builder.append(duration); + builder.append(", sleeperId="); + builder.append(sleeperId); + builder.append(", height="); + builder.append(height); + builder.append(", licenseVersion="); + builder.append(licenseVersion); + builder.append(", username="); + builder.append(username); + builder.append(", birthMonth="); + builder.append(birthMonth); + builder.append(", sleepGoal="); + builder.append(sleepGoal); + builder.append(", accountOwner="); + builder.append(accountOwner); + builder.append(", accountId="); + builder.append(accountId); + builder.append(", email="); + builder.append(email); + builder.append(", avatar="); + builder.append(avatar); + builder.append(", lastLogin="); + builder.append(lastLogin); + builder.append(", side="); + builder.append(side); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java new file mode 100644 index 0000000000..d482d4712b --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.util.List; + +/** + * The {@link SleeperResponse} holds the information about the sleepers assigned to the bed sides. + * + * @author Gregory Moyer - Initial contribution + */ +public class SleepersResponse { + private List sleepers; + + public List getSleepers() { + return sleepers; + } + + public void setSleepers(List sleepers) { + this.sleepers = sleepers; + } + + public SleepersResponse withSleepers(List sleepers) { + setSleepers(sleepers); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((sleepers == null) ? 0 : sleepers.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof SleepersResponse)) { + return false; + } + SleepersResponse other = (SleepersResponse) obj; + if (sleepers == null) { + if (other.sleepers != null) { + return false; + } + } else if (!sleepers.equals(other.sleepers)) { + return false; + } + return true; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SleepersResponse [sleepers="); + builder.append(sleepers); + builder.append("]"); + return builder.toString(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java new file mode 100644 index 0000000000..3b83451cfc --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.dto; + +import java.time.Duration; +import java.util.Objects; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * The {@link TimeSince} converts from "nn d hh:mm:ss" to Duration + * + * @author Gregory Moyer - Initial contribution + */ +public class TimeSince { + private static final Pattern PATTERN = Pattern.compile("(([0-9]+) d )?([0-9]{2}):([0-9]{2}):([0-9]{2})", + Pattern.CASE_INSENSITIVE); + + private Duration duration; + + public Duration getDuration() { + return duration; + } + + public void setDuration(Duration duration) { + this.duration = duration == null ? null : duration.abs(); + } + + public TimeSince withDuration(long days, long hours, long minutes, long seconds) { + return withDuration(Duration.ofSeconds(TimeUnit.DAYS.toSeconds(days) + TimeUnit.HOURS.toSeconds(hours) + + TimeUnit.MINUTES.toSeconds(minutes) + seconds)); + } + + public TimeSince withDuration(Duration duration) { + setDuration(duration); + return this; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((duration == null) ? 0 : duration.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof TimeSince)) { + return false; + } + TimeSince other = (TimeSince) obj; + if (duration == null) { + if (other.duration != null) { + return false; + } + } else if (!duration.equals(other.duration)) { + return false; + } + return true; + } + + @Override + public String toString() { + long totalDays = duration.toDays(); + long totalHours = duration.toHours(); + long totalMinutes = duration.toMinutes(); + long totalSeconds = duration.getSeconds(); + + long hours = totalHours - TimeUnit.DAYS.toHours(totalDays); + long minutes = totalMinutes - TimeUnit.HOURS.toMinutes(totalHours); + long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(totalMinutes); + + if (totalDays > 0) { + return String.format("%d d %02d:%02d:%02d", totalDays, hours, minutes, seconds); + } + + return String.format("%02d:%02d:%02d", hours, minutes, seconds); + } + + public static TimeSince parse(CharSequence text) { + Objects.requireNonNull(text, "text"); + + Matcher matcher = PATTERN.matcher(text); + if (!matcher.matches()) { + return new TimeSince().withDuration(Duration.ZERO); + } + + String dayMatch = matcher.group(2); + String hourMatch = matcher.group(3); + String minuteMatch = matcher.group(4); + String secondMatch = matcher.group(5); + + StringBuilder sb = new StringBuilder("P"); + if (dayMatch != null) { + sb.append(dayMatch).append('D'); + } + sb.append('T').append(hourMatch).append('H').append(minuteMatch).append('M').append(secondMatch).append('S'); + + return new TimeSince().withDuration(Duration.parse(sb.toString())); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java new file mode 100644 index 0000000000..51763626bd --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.enums; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +/** + * The {@link Side} represents the possible sides of the bed (i.e. left and right). + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public enum Side { + LEFT(0), + RIGHT(1); + + private final int side; + + Side(final int side) { + this.side = side; + } + + public int value() { + return side; + } + + public static Side forValue(int value) { + for (Side s : Side.values()) { + if (s.side == value) { + return s; + } + } + throw new IllegalArgumentException("Invalid side: " + value); + } + + public static Side convertFromGroup(@Nullable String channelGroup) { + return "left".equalsIgnoreCase(channelGroup) ? Side.LEFT : Side.RIGHT; + } + + @Override + public String toString() { + return side == 0 ? LEFT.name() : RIGHT.name(); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/SleepDataInterval.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/SleepDataInterval.java new file mode 100644 index 0000000000..a73f0f6969 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/SleepDataInterval.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.enums; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link SleepDataInterval} represents the time periods that can be + * used for sleep data requests. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public enum SleepDataInterval { + DAY("D1"), + WEEK("W1"), + MONTH("M1"); + + private final String interval; + + SleepDataInterval(final String interval) { + this.interval = interval; + } + + public String value() { + return interval; + } + + public static SleepDataInterval forValue(String value) { + for (SleepDataInterval s : SleepDataInterval.values()) { + if (s.interval.equals(value)) { + return s; + } + } + throw new IllegalArgumentException("Invalid sleep data interval: " + value); + } + + @Override + public String toString() { + return interval; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/Endpoints.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/Endpoints.java new file mode 100644 index 0000000000..c806e3ec64 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/Endpoints.java @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link Endpoints} class contains all endpoints for the sleepiq API. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class Endpoints { + private static final String LOGIN = "/rest/login"; + private static final String BED = "/rest/bed"; + private static final String SLEEPER = "/rest/sleeper"; + private static final String FAMILY_STATUS = "/rest/bed/familyStatus"; + private static final String PAUSE_MODE = "/rest/bed/%s/pauseMode"; + private static final String SLEEP_DATA = "/rest/sleepData"; + private static final String SET_SLEEP_NUMBER = "/rest/bed/%s/sleepNumber"; + private static final String SET_PAUSE_MODE = "/rest/bed/%s/pauseMode"; + + public static String login() { + return LOGIN; + } + + public static String bed() { + return BED; + } + + public static String sleeper() { + return SLEEPER; + } + + public static String familyStatus() { + return FAMILY_STATUS; + } + + public static String pauseMode(String bedId) { + return String.format(PAUSE_MODE, bedId); + } + + public static String sleepData() { + return SLEEP_DATA; + } + + public static String setSleepNumber(String bedId) { + return String.format(SET_SLEEP_NUMBER, bedId); + } + + public static String setPauseMode(String bedId) { + return String.format(SET_PAUSE_MODE, bedId); + } + + private Endpoints() { + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/GsonGenerator.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/GsonGenerator.java new file mode 100644 index 0000000000..64e99adb24 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/GsonGenerator.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl; + +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.sleepiq.internal.api.dto.SleepNumberRequest; +import org.openhab.binding.sleepiq.internal.api.dto.TimeSince; +import org.openhab.binding.sleepiq.internal.api.enums.Side; +import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.SideTypeAdapter; +import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.SleepNumberRequestAdapter; +import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.TimeSinceTypeAdapter; +import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.ZonedDateTimeTypeAdapter; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +/** + * The {@link GsonGenerator} class creates the GSON generator object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class GsonGenerator { + public static Gson create() { + return create(false); + } + + public static Gson create(boolean prettyPrint) { + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeTypeAdapter()); + builder.registerTypeAdapter(TimeSince.class, new TimeSinceTypeAdapter()); + builder.registerTypeAdapter(SleepNumberRequest.class, new SleepNumberRequestAdapter()); + builder.registerTypeAdapter(Side.class, new SideTypeAdapter()); + + if (prettyPrint) { + builder.setPrettyPrinting(); + } + return builder.create(); + } + + private GsonGenerator() { + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/SleepIQImpl.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/SleepIQImpl.java new file mode 100644 index 0000000000..587ee30854 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/SleepIQImpl.java @@ -0,0 +1,322 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl; + +import java.net.CookieStore; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpHeader; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.openhab.binding.sleepiq.internal.api.CommunicationException; +import org.openhab.binding.sleepiq.internal.api.Configuration; +import org.openhab.binding.sleepiq.internal.api.LoginException; +import org.openhab.binding.sleepiq.internal.api.ResponseFormatException; +import org.openhab.binding.sleepiq.internal.api.SleepIQ; +import org.openhab.binding.sleepiq.internal.api.UnauthorizedException; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.dto.BedsResponse; +import org.openhab.binding.sleepiq.internal.api.dto.Failure; +import org.openhab.binding.sleepiq.internal.api.dto.FamilyStatusResponse; +import org.openhab.binding.sleepiq.internal.api.dto.LoginInfo; +import org.openhab.binding.sleepiq.internal.api.dto.LoginRequest; +import org.openhab.binding.sleepiq.internal.api.dto.PauseModeResponse; +import org.openhab.binding.sleepiq.internal.api.dto.SleepDataResponse; +import org.openhab.binding.sleepiq.internal.api.dto.SleepNumberRequest; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.dto.SleepersResponse; +import org.openhab.binding.sleepiq.internal.api.enums.Side; +import org.openhab.binding.sleepiq.internal.api.enums.SleepDataInterval; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link SleepIQImpl} class handles all interactions with the sleepiq service. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class SleepIQImpl implements SleepIQ { + private static final String PARAM_KEY = "_k"; + private static final String USER_AGENT = "SleepIQ/1593766370 CFNetwork/1185.2 Darwin/20.0.0"; + + private static final Gson GSON = GsonGenerator.create(false); + + private final Logger logger = LoggerFactory.getLogger(SleepIQImpl.class); + + private final HttpClient httpClient; + private final CookieStore cookieStore; + + protected final Configuration config; + + private final LoginRequest loginRequest = new LoginRequest(); + private volatile @Nullable LoginInfo loginInfo; + + public SleepIQImpl(Configuration config, HttpClient httpClient) { + this.config = config; + this.httpClient = httpClient; + cookieStore = httpClient.getCookieStore(); + loginRequest.setLogin(config.getUsername()); + loginRequest.setPassword(config.getPassword()); + } + + @Override + public void shutdown() { + cookieStore.removeAll(); + } + + @Override + public @Nullable LoginInfo login() throws LoginException, UnauthorizedException { + logger.trace("SleepIQ: login: loginInfo={}", loginInfo); + if (loginInfo == null) { + synchronized (this) { + if (loginInfo == null) { + Request request = httpClient.newRequest(config.getBaseUri()).path(Endpoints.login()) + .agent(USER_AGENT).header(HttpHeader.CONTENT_TYPE, "application/json") + .timeout(10, TimeUnit.SECONDS).method(HttpMethod.PUT) + .content(new StringContentProvider(GSON.toJson(loginRequest)), "application/json"); + logger.trace("SleepIQ: login: request url={}", request.getURI()); + + try { + ContentResponse response = request.send(); + logger.debug("SleepIQ: login: status={}, content={}", response.getStatus(), + response.getContentAsString()); + if (isUnauthorized(response)) { + Failure failure = GSON.fromJson(response.getContentAsString(), Failure.class); + String message = failure != null ? failure.getError().getMessage() : "Login unauthorized"; + throw new UnauthorizedException(message); + } + if (isNotOk(response)) { + Failure failure = GSON.fromJson(response.getContentAsString(), Failure.class); + String message = failure != null ? failure.getError().getMessage() : "Login failed"; + throw new LoginException(message); + } + try { + loginInfo = GSON.fromJson(response.getContentAsString(), LoginInfo.class); + } catch (JsonSyntaxException e) { + throw new LoginException("Failed to parse 'login' response"); + } + } catch (InterruptedException | TimeoutException | ExecutionException e) { + logger.info("SleepIQ: login: Login failed message={}", e.getMessage(), e); + throw new LoginException("Problem communicating with SleepIQ cloud service"); + } + } + } + } + return loginInfo; + } + + @Override + public List getBeds() throws LoginException, CommunicationException, ResponseFormatException { + try { + String contentResponse = cloudRequest(Endpoints.bed()); + BedsResponse response = GSON.fromJson(contentResponse, BedsResponse.class); + if (response != null) { + return response.getBeds(); + } else { + throw new ResponseFormatException("Failed to get a valid 'beds' response from cloud"); + } + } catch (JsonSyntaxException e) { + throw new ResponseFormatException("Failed to parse 'beds' response"); + } + } + + @Override + public FamilyStatusResponse getFamilyStatus() + throws LoginException, ResponseFormatException, CommunicationException { + try { + String contentResponse = cloudRequest(Endpoints.familyStatus()); + FamilyStatusResponse response = GSON.fromJson(contentResponse, FamilyStatusResponse.class); + if (response != null) { + return response; + } else { + throw new ResponseFormatException("Failed to get a valid 'familyStatus' response from cloud"); + } + } catch (JsonSyntaxException e) { + throw new ResponseFormatException("Failed to parse 'familyStatus' response"); + } + } + + @Override + public List getSleepers() throws LoginException, ResponseFormatException, CommunicationException { + try { + String contentResponse = cloudRequest(Endpoints.sleeper()); + SleepersResponse response = GSON.fromJson(contentResponse, SleepersResponse.class); + if (response != null) { + return response.getSleepers(); + } else { + throw new ResponseFormatException("Failed to get a valid 'sleepers' response from cloud"); + } + } catch (JsonSyntaxException e) { + throw new ResponseFormatException("Failed to parse 'sleepers' response"); + } + } + + @Override + public PauseModeResponse getPauseMode(String bedId) + throws LoginException, ResponseFormatException, CommunicationException { + try { + String contentResponse = cloudRequest(Endpoints.pauseMode(bedId)); + PauseModeResponse response = GSON.fromJson(contentResponse, PauseModeResponse.class); + if (response != null) { + return response; + } else { + throw new ResponseFormatException("Failed to get a valid 'pauseMode' response from cloud"); + } + } catch (JsonSyntaxException e) { + throw new ResponseFormatException("Failed to parse 'pauseMode' response"); + } + } + + @Override + public SleepDataResponse getSleepData(String sleeperId, SleepDataInterval interval) + throws LoginException, ResponseFormatException, CommunicationException { + try { + Map parameters = new HashMap<>(); + parameters.put("interval", interval.value()); + parameters.put("sleeper", sleeperId); + parameters.put("includeSlices", "false"); + parameters.put("date", formatSleepDataDate(ZonedDateTime.now())); + String contentResponse = cloudRequest(Endpoints.sleepData(), parameters); + SleepDataResponse response = GSON.fromJson(contentResponse, SleepDataResponse.class); + if (response != null) { + return response; + } else { + throw new ResponseFormatException("Failed to get a valid 'sleepData' response from cloud"); + } + } catch (JsonSyntaxException e) { + throw new ResponseFormatException("Failed to parse 'sleepData' response"); + } + } + + private String formatSleepDataDate(ZonedDateTime zonedDateTime) { + return DateTimeFormatter.ofPattern("yyyy-MM-dd").format(zonedDateTime); + } + + @Override + public void setSleepNumber(String bedId, Side side, int sleepNumber) + throws LoginException, ResponseFormatException, CommunicationException { + String body = GSON.toJson(new SleepNumberRequest().withBedId(bedId).withSleepNumber(sleepNumber).withSide(side), + SleepNumberRequest.class); + logger.debug("SleepIQ: setSleepNumber: Request body={}", body); + cloudRequest(Endpoints.setSleepNumber(bedId), null, body); + } + + @Override + public void setPauseMode(String bedId, boolean pauseMode) + throws LoginException, ResponseFormatException, CommunicationException { + logger.debug("SleepIQ: setPauseMode: command={}", pauseMode); + Map requestParameters = new HashMap<>(); + requestParameters.put("mode", pauseMode ? "on" : "off"); + cloudRequest(Endpoints.setPauseMode(bedId), requestParameters, ""); + } + + private String cloudRequest(String endpoint) + throws LoginException, ResponseFormatException, CommunicationException { + return cloudRequest(endpoint, null, null); + } + + private String cloudRequest(String endpoint, Map parameters) + throws LoginException, ResponseFormatException, CommunicationException { + return cloudRequest(endpoint, parameters, null); + } + + private String cloudRequest(String endpoint, @Nullable Map parameters, @Nullable String body) + throws LoginException, ResponseFormatException, CommunicationException { + logger.debug("SleepIQ: cloudGetRequest: Invoke endpoint={}", endpoint); + ContentResponse response = (body == null ? doGet(endpoint, parameters) : doPut(endpoint, parameters, body)); + if (isUnauthorized(response)) { + logger.debug("SleepIQ: cloudGetRequest: UNAUTHORIZED, reset login"); + // Force new login and try again + resetLogin(); + response = (body == null ? doGet(endpoint, parameters) : doPut(endpoint, parameters, body)); + } + if (isNotOk(response)) { + throw new ResponseFormatException(String.format("Cloud API returned error: status=%d, message=%s", + response.getStatus(), HttpStatus.getCode(response.getStatus()).getMessage())); + } + return response.getContentAsString(); + } + + private ContentResponse doGet(String endpoint, @Nullable Map parameters) + throws CommunicationException, LoginException { + LoginInfo login = login(); + Request request = httpClient.newRequest(config.getBaseUri()).path(endpoint).param(PARAM_KEY, login.getKey()) + .agent(USER_AGENT).header(HttpHeader.CONTENT_TYPE, "application/json").timeout(10, TimeUnit.SECONDS) + .method(HttpMethod.GET); + return doRequest(request, parameters); + } + + private ContentResponse doPut(String endpoint, @Nullable Map parameters, String body) + throws CommunicationException, LoginException { + LoginInfo login = login(); + Request request = httpClient.newRequest(config.getBaseUri()).path(endpoint).param(PARAM_KEY, login.getKey()) + .agent(USER_AGENT).header(HttpHeader.CONTENT_TYPE, "application/json").timeout(10, TimeUnit.SECONDS) + .method(HttpMethod.PUT).content(new StringContentProvider(body), "application/json"); + return doRequest(request, parameters); + } + + private ContentResponse doRequest(Request request, @Nullable Map parameters) + throws CommunicationException { + try { + if (parameters != null) { + for (String key : parameters.keySet()) { + request.param(key, parameters.get(key)); + } + } + addCookiesToRequest(request); + logger.debug("SleepIQ: doPut: request url={}", request.getURI()); + ContentResponse response = request.send(); + logger.trace("SleepIQ: doPut: status={} response={}", response.getStatus(), response.getContentAsString()); + return response; + } catch (InterruptedException | TimeoutException | ExecutionException e) { + logger.debug("SleepIQ: doPut: Exception message={}", e.getMessage(), e); + throw new CommunicationException("Communication error while accessing API: " + e.getMessage()); + } + } + + private void addCookiesToRequest(Request request) { + cookieStore.get(config.getBaseUri()).forEach(cookie -> { + request.cookie(cookie); + }); + } + + private boolean isUnauthorized(ContentResponse response) { + return response.getStatus() == HttpStatus.Code.UNAUTHORIZED.getCode(); + } + + private boolean isNotOk(ContentResponse response) { + return response.getStatus() != HttpStatus.Code.OK.getCode(); + } + + private synchronized void resetLogin() { + logger.debug("SleepIQ: resetLogin: Set loginInfo=null to force login on next transaction"); + loginInfo = null; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/DateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/DateTimeTypeAdapter.java new file mode 100644 index 0000000000..811618358b --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/DateTimeTypeAdapter.java @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import java.util.function.Function; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet - Initial contribution + */ +@NonNullByDefault +abstract class DateTimeTypeAdapter extends TemporalTypeAdapter { + + DateTimeTypeAdapter(Function parseFunction) { + super(parseFunction); + } + + @Override + public String preProcess(String in) { + if (in.endsWith("+0000")) { + return in.substring(0, in.length() - 5) + "Z"; + } + return in; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SideTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SideTypeAdapter.java new file mode 100644 index 0000000000..655a3d5c40 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SideTypeAdapter.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import java.lang.reflect.Type; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.sleepiq.internal.api.enums.Side; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * The {@link SideTypeAdapter} converts the Side enum to the format expected by the sleepiq API. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class SideTypeAdapter implements JsonDeserializer, JsonSerializer { + + @Override + public JsonElement serialize(Side side, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(side.value()); + } + + @Override + public @Nullable Side deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) + throws JsonParseException { + int key = element.getAsInt(); + return Side.forValue(key); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SleepNumberRequestAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SleepNumberRequestAdapter.java new file mode 100644 index 0000000000..5019bbf94a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SleepNumberRequestAdapter.java @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import java.lang.reflect.Type; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.sleepiq.internal.api.dto.SleepNumberRequest; +import org.openhab.binding.sleepiq.internal.api.enums.Side; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +/** + * The {@link SleepNumberRequestAdapter} serializes the request to set the sleep number. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class SleepNumberRequestAdapter implements JsonSerializer { + + @Override + public JsonElement serialize(SleepNumberRequest src, Type typeOfSrc, JsonSerializationContext context) { + // Sleep number must be >= 5 and <= 100, and be a multiple of 5 + int sleepNumber = src.getSleepNumber(); + sleepNumber = Math.min(100, sleepNumber); + sleepNumber = Math.max(5, sleepNumber); + sleepNumber = 5 * (int) (Math.round(sleepNumber / 5.0)); + + JsonObject obj = new JsonObject(); + obj.addProperty("bedId", src.getBedId()); + obj.addProperty("sleepNumber", sleepNumber); + obj.addProperty("side", src.getSide().equals(Side.LEFT) ? "L" : "R"); + return obj; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java new file mode 100644 index 0000000000..2503eb964e --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import java.io.IOException; +import java.util.Objects; +import java.util.function.Function; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +/** + * Abstract type adapter for jsr310 date-time types. + * + * @author Christophe Bornet - Initial contribution + */ +@NonNullByDefault +abstract class TemporalTypeAdapter extends TypeAdapter { + + Function parseFunction; + + TemporalTypeAdapter(Function parseFunction) { + Objects.requireNonNull(parseFunction); + this.parseFunction = parseFunction; + } + + @Override + public void write(JsonWriter out, @Nullable T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + out.value(value.toString()); + } + } + + @Override + public @Nullable T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + String temporalString = preProcess(in.nextString()); + return parseFunction.apply(temporalString); + } + + public String preProcess(String in) { + return in; + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java new file mode 100644 index 0000000000..6377feca6e --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.binding.sleepiq.internal.api.dto.TimeSince; + +/** + * The {@link TimeSinceTypeAdapter} handles the parsing of the TimeSince. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class TimeSinceTypeAdapter extends TemporalTypeAdapter { + public TimeSinceTypeAdapter() { + super(TimeSince::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java new file mode 100644 index 0000000000..bb3e64b755 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.internal.api.impl.typeadapters; + +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * Type adapter for jsr310 {@link ZonedDateTime} class. + * + * @author Christophe Bornet - Initial contribution + */ +@NonNullByDefault +public class ZonedDateTimeTypeAdapter extends DateTimeTypeAdapter { + + public ZonedDateTimeTypeAdapter() { + super(ZonedDateTime::parse); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/config/SleepIQBedConfiguration.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/config/SleepIQBedConfiguration.java index 3d8fcd30de..96e09ea316 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/config/SleepIQBedConfiguration.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/config/SleepIQBedConfiguration.java @@ -12,13 +12,17 @@ */ package org.openhab.binding.sleepiq.internal.config; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Configuration class for a SleepIQ bed. * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault public class SleepIQBedConfiguration { public static final String BED_ID = "bedId"; - public String bedId; + public @Nullable String bedId; } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java index b9b14a7abe..e60525e220 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java @@ -13,10 +13,12 @@ package org.openhab.binding.sleepiq.internal.discovery; import java.util.HashMap; +import java.util.List; import java.util.Map; -import org.openhab.binding.sleepiq.api.model.Bed; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.openhab.binding.sleepiq.internal.SleepIQBindingConstants; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; import org.openhab.binding.sleepiq.internal.config.SleepIQBedConfiguration; import org.openhab.binding.sleepiq.internal.handler.SleepIQCloudHandler; import org.openhab.binding.sleepiq.internal.handler.SleepIQDualBedHandler; @@ -33,6 +35,7 @@ import org.slf4j.LoggerFactory; * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault public class SleepIQBedDiscoveryService extends AbstractDiscoveryService { private static final int TIMEOUT = 60; @@ -59,34 +62,34 @@ public class SleepIQBedDiscoveryService extends AbstractDiscoveryService { @Override protected void startScan() { logger.debug("Starting scan for new beds"); + List beds = cloudHandler.getBeds(); + if (beds != null) { + for (Bed bed : beds) { + // only dual chamber beds are supported currently + if (!bed.isDualSleep()) { + logger.info("Found a bed that is not dual chamber - currently unsupported"); + continue; + } - for (Bed bed : cloudHandler.getBeds()) { - // only dual chamber beds are supported currently - if (!bed.isDualSleep()) { - logger.info("Found a bed that is not dual chamber - currently unsupported"); - continue; - } - - ThingUID bridgeUID = cloudHandler.getThing().getUID(); - ThingUID thingUID = new ThingUID(SleepIQBindingConstants.THING_TYPE_DUAL_BED, bridgeUID, - bed.getMacAddress()); - - // thing already exists - if (cloudHandler.getThing().getThing(thingUID) != null) { - continue; - } + ThingUID bridgeUID = cloudHandler.getThing().getUID(); + ThingUID thingUID = new ThingUID(SleepIQBindingConstants.THING_TYPE_DUAL_BED, bridgeUID, + bed.getMacAddress()); - logger.debug("New bed found with MAC address {}", bed.getMacAddress()); + // thing already exists + if (cloudHandler.getThing().getThing(thingUID) != null) { + continue; + } - @SuppressWarnings({ "unchecked", "rawtypes" }) - Map properties = (Map) cloudHandler.updateProperties(bed, new HashMap<>()); - properties.put(SleepIQBedConfiguration.BED_ID, bed.getBedId()); + logger.debug("New bed found with MAC address {}", bed.getMacAddress()); + @SuppressWarnings({ "unchecked", "rawtypes" }) + Map properties = (Map) cloudHandler.updateProperties(bed, new HashMap<>()); + properties.put(SleepIQBedConfiguration.BED_ID, bed.getBedId()); - DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) - .withBridge(bridgeUID).withLabel(bed.getName() + " - " + bed.getModel()).build(); - thingDiscovered(discoveryResult); + DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties) + .withBridge(bridgeUID).withLabel(bed.getName() + " - " + bed.getModel()).build(); + thingDiscovered(discoveryResult); + } } - stopScan(); } } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java index 7ecc336550..aa9c3b0734 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java @@ -12,14 +12,17 @@ */ package org.openhab.binding.sleepiq.internal.handler; -import org.openhab.binding.sleepiq.api.SleepIQ; -import org.openhab.binding.sleepiq.api.model.BedStatus; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.sleepiq.internal.api.dto.BedStatus; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; /** * The {@link BedStatusListener} is notified when a chamber is updated. * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault public interface BedStatusListener { /** * This method will be called whenever a new bed status is received by the cloud handler. @@ -27,5 +30,7 @@ public interface BedStatusListener { * @param cloud the cloud service that can be used to gather additional information * @param status the status returned from the cloud service */ - public void onBedStateChanged(SleepIQ cloud, BedStatus status); + public void onBedStateChanged(BedStatus status); + + public void onSleeperChanged(@Nullable Sleeper sleeper); } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java index 052553692f..30f3160844 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java @@ -25,19 +25,24 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import javax.ws.rs.client.ClientBuilder; - -import org.openhab.binding.sleepiq.api.Configuration; -import org.openhab.binding.sleepiq.api.LoginException; -import org.openhab.binding.sleepiq.api.SleepIQ; -import org.openhab.binding.sleepiq.api.UnauthorizedException; -import org.openhab.binding.sleepiq.api.model.Bed; -import org.openhab.binding.sleepiq.api.model.BedStatus; -import org.openhab.binding.sleepiq.api.model.FamilyStatus; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.sleepiq.internal.SleepIQBindingConstants; import org.openhab.binding.sleepiq.internal.SleepIQConfigStatusMessage; +import org.openhab.binding.sleepiq.internal.api.Configuration; +import org.openhab.binding.sleepiq.internal.api.LoginException; +import org.openhab.binding.sleepiq.internal.api.SleepIQ; +import org.openhab.binding.sleepiq.internal.api.SleepIQException; +import org.openhab.binding.sleepiq.internal.api.UnauthorizedException; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.dto.BedStatus; +import org.openhab.binding.sleepiq.internal.api.dto.FamilyStatusResponse; +import org.openhab.binding.sleepiq.internal.api.dto.SleepDataResponse; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.enums.Side; +import org.openhab.binding.sleepiq.internal.api.enums.SleepDataInterval; import org.openhab.binding.sleepiq.internal.config.SleepIQCloudConfiguration; -import org.openhab.core.cache.ExpiringCache; import org.openhab.core.config.core.status.ConfigStatusMessage; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; @@ -56,124 +61,82 @@ import org.slf4j.LoggerFactory; * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault public class SleepIQCloudHandler extends ConfigStatusBridgeHandler { public static final Set SUPPORTED_THING_TYPE_UIDS = Collections.singleton(THING_TYPE_CLOUD); + private static final int SLEEPER_POLLING_INTERVAL_HOURS = 12; + private final Logger logger = LoggerFactory.getLogger(SleepIQCloudHandler.class); - private final List bedStatusListeners = new CopyOnWriteArrayList<>(); + private final HttpClient httpClient; - private ExpiringCache statusCache; + private final List bedStatusListeners = new CopyOnWriteArrayList<>(); - private ScheduledFuture pollingJob; + private @Nullable ScheduledFuture statusPollingJob; + private @Nullable ScheduledFuture sleeperPollingJob; - private SleepIQ cloud; + private @Nullable SleepIQ cloud; - private ClientBuilder clientBuilder; + private @Nullable List sleepers; - public SleepIQCloudHandler(final Bridge bridge, ClientBuilder clientBuilder) { + public SleepIQCloudHandler(final Bridge bridge, HttpClient httpClient) { super(bridge); - this.clientBuilder = clientBuilder; + this.httpClient = httpClient; } @Override public void initialize() { - try { - logger.debug("Configuring bed status cache"); - statusCache = new ExpiringCache<>(TimeUnit.SECONDS.toMillis(getPollingInterval() / 2), - () -> cloud.getFamilyStatus()); - - createCloudConnection(); - - logger.debug("Setting SleepIQ cloud online"); - updateListenerManagement(); - updateStatus(ThingStatus.ONLINE); - } catch (UnauthorizedException e) { - logger.debug("SleepIQ cloud authentication failed", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid SleepIQ credentials"); - } catch (LoginException e) { - logger.debug("SleepIQ cloud login failed", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "SleepIQ cloud login failed: " + e.getMessage()); - } catch (Exception e) { - logger.debug("Unexpected error while communicating with SleepIQ cloud", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Unable to connect to SleepIQ cloud: " + e.getMessage()); - } - } - - /** - * Create a new SleepIQ cloud service connection. If a connection already exists, it will be lost. - * - * @param clientBuilder2 - * - * @throws LoginException if there is an error while authenticating to the service - */ - private void createCloudConnection() throws LoginException { - logger.debug("Reading SleepIQ cloud binding configuration"); - SleepIQCloudConfiguration bindingConfig = getConfigAs(SleepIQCloudConfiguration.class); - - logger.debug("Creating SleepIQ client"); - Configuration cloudConfig = new Configuration().withUsername(bindingConfig.username) - .withPassword(bindingConfig.password).withLogging(logger.isDebugEnabled()); - cloud = SleepIQ.create(cloudConfig, clientBuilder); - - logger.debug("Authenticating at the SleepIQ cloud service"); - cloud.login(); - - logger.info("Successfully authenticated at the SleepIQ cloud service"); + scheduler.execute(() -> { + try { + createCloudConnection(); + updateListenerManagement(); + updateStatus(ThingStatus.ONLINE); + } catch (UnauthorizedException e) { + logger.debug("CloudHandler: SleepIQ cloud authentication failed", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid SleepIQ credentials"); + } catch (LoginException e) { + logger.debug("CloudHandler: SleepIQ cloud login failed", e); + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "SleepIQ cloud login failed: " + e.getMessage()); + } + }); } @Override public synchronized void dispose() { - logger.debug("Disposing SleepIQ cloud handler"); - - if (pollingJob != null && !pollingJob.isCancelled()) { - pollingJob.cancel(true); - pollingJob = null; + stopSleeperPollingJob(); + stopStatusPollingJob(); + if (cloud != null) { + cloud.shutdown(); } } - /** - * Start or stop a background polling job to look for bed status updates based on whether or not there are any - * listeners to notify. - */ - private synchronized void updateListenerManagement() { - if (!bedStatusListeners.isEmpty() && (pollingJob == null || pollingJob.isCancelled())) { - int pollingInterval = getPollingInterval(); - pollingJob = scheduler.scheduleWithFixedDelay(this::refreshBedStatus, pollingInterval, pollingInterval, - TimeUnit.SECONDS); - } else if (bedStatusListeners.isEmpty() && pollingJob != null && !pollingJob.isCancelled()) { - pollingJob.cancel(true); - pollingJob = null; - } + @Override + public void handleCommand(final ChannelUID channelUID, final Command command) { + // cloud handler has no channels } /** - * Retrieve the polling interval for updating bed status. + * Validate the config from openHAB * - * @return the polling interval in seconds + * @return validity status of config parameters */ - private int getPollingInterval() { - return getConfigAs(SleepIQCloudConfiguration.class).pollingInterval; - } - - /** - * Retrieve the latest status on all beds and update all registered listeners. - */ - public void refreshBedStatus() { - try { - FamilyStatus status = statusCache.getValue(); - updateStatus(ThingStatus.ONLINE); - - for (BedStatus bedStatus : status.getBeds()) { - bedStatusListeners.stream().forEach(l -> l.onBedStateChanged(cloud, bedStatus)); - } - } catch (Exception e) { - logger.debug("Unexpected error while communicating with SleepIQ cloud", e); - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, - "Unable to connect to SleepIQ cloud: " + e.getMessage()); + @Override + public Collection getConfigStatus() { + Collection configStatusMessages = new ArrayList<>(); + SleepIQCloudConfiguration config = getConfigAs(SleepIQCloudConfiguration.class); + String username = config.username; + String password = config.password; + if (username.isBlank()) { + configStatusMessages.add(ConfigStatusMessage.Builder.error(USERNAME) + .withMessageKeySuffix(SleepIQConfigStatusMessage.USERNAME_MISSING).withArguments(USERNAME).build()); } + if (password.isBlank()) { + configStatusMessages.add(ConfigStatusMessage.Builder.error(PASSWORD) + .withMessageKeySuffix(SleepIQConfigStatusMessage.PASSWORD_MISSING).withArguments(PASSWORD).build()); + } + return configStatusMessages; } /** @@ -182,13 +145,12 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler { * @param listener the listener to register */ public void registerBedStatusListener(final BedStatusListener listener) { - if (listener == null) { - return; - } - bedStatusListeners.add(listener); - refreshBedStatus(); - updateListenerManagement(); + scheduler.execute(() -> { + refreshSleepers(); + refreshBedStatus(); + updateListenerManagement(); + }); } /** @@ -203,59 +165,101 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler { if (result) { updateListenerManagement(); } - return result; } - @Override - public void handleCommand(final ChannelUID channelUID, final Command command) { - // cloud handler has no channels + /** + * Get a list of all beds registered to the cloud service account. + * + * @return the list of beds or null if unable to get list + */ + public @Nullable List getBeds() { + try { + return cloud.getBeds(); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception getting list of beds", e); + return null; + } } - @Override - public Collection getConfigStatus() { - Collection configStatusMessages = new ArrayList<>(); - - SleepIQCloudConfiguration config = getConfigAs(SleepIQCloudConfiguration.class); - String username = config.username; - String password = config.password; - - if (username.isEmpty()) { - configStatusMessages.add(ConfigStatusMessage.Builder.error(USERNAME) - .withMessageKeySuffix(SleepIQConfigStatusMessage.USERNAME_MISSING).withArguments(USERNAME).build()); + /** + * Get the bed corresponding to the given bed id + * + * @param bedId the bed identifier + * @return the identified {@link Bed} or null if no such bed exists + */ + public @Nullable Bed getBed(final @Nullable String bedId) { + logger.debug("CloudHandler: Get bed object for bedId={}", bedId); + if (bedId == null) { + return null; } - - if (password.isEmpty()) { - configStatusMessages.add(ConfigStatusMessage.Builder.error(PASSWORD) - .withMessageKeySuffix(SleepIQConfigStatusMessage.PASSWORD_MISSING).withArguments(PASSWORD).build()); + List beds = getBeds(); + if (beds != null) { + for (Bed bed : beds) { + if (bedId.equals(bed.getBedId())) { + return bed; + } + } } - - return configStatusMessages; + return null; } /** - * Get a list of all beds registered to the cloud service account. + * Get the sleeper associated with the bedId and side * - * @return the list of beds (never null) + * @param bedId the bed identifier + * @param side the side of the bed + * @return the sleeper or null if sleeper not found */ - public List getBeds() { - return cloud.getBeds(); + public @Nullable Sleeper getSleeper(@Nullable String bedId, Side side) { + logger.debug("CloudHandler: Get sleeper object for bedId={}, side={}", bedId, side); + if (bedId == null) { + return null; + } + List localSleepers = sleepers; + if (localSleepers != null) { + for (Sleeper sleeper : localSleepers) { + if (bedId.equals(sleeper.getBedId()) && side.equals(sleeper.getSide())) { + return sleeper; + } + } + } + return null; } /** - * Get the {@link Bed} corresponding to the given identifier. + * Set the sleep number of the specified chamber * * @param bedId the bed identifier - * @return the identified {@link Bed} or null if no such bed exists + * @param sleepNumber the sleep number multiple of 5 between 5 and 100 + * @param side the chamber to set */ - public Bed getBed(final String bedId) { - for (Bed bed : getBeds()) { - if (bedId.equals(bed.getBedId())) { - return bed; - } + public void setSleepNumber(@Nullable String bedId, Side side, int sleepNumber) { + if (bedId == null) { + return; } + try { + cloud.setSleepNumber(bedId, side, sleepNumber); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception setting sleep number of bed={}", bedId, e); + } + } - return null; + /** + * Set the pause mode of the specified bed + * + * @param bedId the bed identifier + * @param mode turn pause mode on or off + */ + public void setPauseMode(@Nullable String bedId, boolean mode) { + if (bedId == null) { + return; + } + try { + cloud.setPauseMode(bedId, mode); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception setting pause mode of bed={}", bedId, e); + } } /** @@ -266,8 +270,9 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler { * @param properties the properties to update (this may be null) * @return the given map (or a new map if no map was given) with updated/set properties from the supplied bed */ - public Map updateProperties(final Bed bed, Map properties) { + public Map updateProperties(final @Nullable Bed bed, Map properties) { if (bed != null) { + logger.debug("CloudHandler: Updating bed properties for bed={}", bed.getBedId()); properties.put(Thing.PROPERTY_MODEL_ID, bed.getModel()); properties.put(SleepIQBindingConstants.PROPERTY_BASE, bed.getBase()); if (bed.isKidsBed() != null) { @@ -281,7 +286,146 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler { properties.put(SleepIQBindingConstants.PROPERTY_SIZE, bed.getSize()); properties.put(SleepIQBindingConstants.PROPERTY_SKU, bed.getSku()); } - return properties; } + + /** + * Retrieve the latest status on all beds and update all registered listeners + * with bed status, sleepers and sleep data. + */ + private void refreshBedStatus() { + logger.debug("CloudHandler: Refreshing BED STATUS, updating chanels with status, sleepers, and sleep data"); + try { + FamilyStatusResponse familyStatus = cloud.getFamilyStatus(); + if (familyStatus != null && familyStatus.getBeds() != null) { + updateStatus(ThingStatus.ONLINE); + for (BedStatus bedStatus : familyStatus.getBeds()) { + logger.debug("CloudHandler: Informing listeners with bed status for bedId={}", + bedStatus.getBedId()); + bedStatusListeners.stream().forEach(l -> l.onBedStateChanged(bedStatus)); + } + + List localSleepers = sleepers; + if (localSleepers != null) { + for (Sleeper sleeper : localSleepers) { + logger.debug("CloudHandler: Informing listeners with sleepers for sleeperId={}", + sleeper.getSleeperId()); + bedStatusListeners.stream().forEach(l -> l.onSleeperChanged(sleeper)); + } + } + return; + } + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception refreshing bed status", e); + } + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, "Unable to connect to SleepIQ cloud"); + } + + /** + * Refresh the list of sleepers + */ + private void refreshSleepers() { + logger.debug("CloudHandler: Refreshing SLEEPERS"); + try { + sleepers = cloud.getSleepers(); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception refreshing list of sleepers", e); + } + } + + public @Nullable SleepDataResponse getDailySleepData(String sleeperId) { + return getSleepData(sleeperId, SleepDataInterval.DAY); + } + + public @Nullable SleepDataResponse getMonthlySleepData(String sleeperId) { + return getSleepData(sleeperId, SleepDataInterval.MONTH); + } + + private @Nullable SleepDataResponse getSleepData(String sleeperId, SleepDataInterval interval) { + try { + return cloud.getSleepData(sleeperId, interval); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception getting sleep data for sleeperId={}", sleeperId, e); + } + return null; + } + + /** + * Create a new SleepIQ cloud service connection. If a connection already exists, it will be lost. + * + * @throws LoginException if there is an error while authenticating to the service + */ + private void createCloudConnection() throws LoginException { + SleepIQCloudConfiguration bindingConfig = getConfigAs(SleepIQCloudConfiguration.class); + Configuration cloudConfig = new Configuration().withUsername(bindingConfig.username) + .withPassword(bindingConfig.password).withLogging(logger.isTraceEnabled()); + logger.debug("CloudHandler: Authenticating at the SleepIQ cloud service"); + cloud = SleepIQ.create(cloudConfig, httpClient); + cloud.login(); + } + + /** + * Start or stop the background polling jobs + */ + private synchronized void updateListenerManagement() { + startSleeperPollingJob(); + startStatusPollingJob(); + } + + /** + * Start or stop the bed status polling job + */ + private void startStatusPollingJob() { + ScheduledFuture localPollingJob = statusPollingJob; + if (!bedStatusListeners.isEmpty() && (localPollingJob == null || localPollingJob.isCancelled())) { + int pollingInterval = getStatusPollingIntervalSeconds(); + logger.debug("CloudHandler: Scheduling bed status polling job every {} seconds", pollingInterval); + statusPollingJob = scheduler.scheduleWithFixedDelay(this::refreshBedStatus, pollingInterval, + pollingInterval, TimeUnit.SECONDS); + } else if (bedStatusListeners.isEmpty()) { + stopStatusPollingJob(); + } + } + + /** + * Stop the bed status polling job + */ + private void stopStatusPollingJob() { + ScheduledFuture localPollingJob = statusPollingJob; + if (localPollingJob != null) { + logger.debug("CloudHandler: Canceling bed status polling job"); + localPollingJob.cancel(true); + statusPollingJob = null; + } + } + + private int getStatusPollingIntervalSeconds() { + return getConfigAs(SleepIQCloudConfiguration.class).pollingInterval; + } + + /** + * Start or stop the sleeper polling job + */ + private void startSleeperPollingJob() { + ScheduledFuture localJob = sleeperPollingJob; + if (!bedStatusListeners.isEmpty() && (localJob == null || localJob.isCancelled())) { + logger.debug("CloudHandler: Scheduling sleeper polling job every {} hours", SLEEPER_POLLING_INTERVAL_HOURS); + sleeperPollingJob = scheduler.scheduleWithFixedDelay(this::refreshSleepers, SLEEPER_POLLING_INTERVAL_HOURS, + SLEEPER_POLLING_INTERVAL_HOURS, TimeUnit.HOURS); + } else if (bedStatusListeners.isEmpty()) { + stopSleeperPollingJob(); + } + } + + /** + * Stop the sleeper polling job + */ + private void stopSleeperPollingJob() { + ScheduledFuture localJob = sleeperPollingJob; + if (localJob != null && !localJob.isCancelled()) { + logger.debug("CloudHandler: Canceling sleeper polling job"); + localJob.cancel(true); + sleeperPollingJob = null; + } + } } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java index 00a3c0046b..b20b6884f0 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java @@ -16,15 +16,22 @@ import static org.openhab.binding.sleepiq.internal.SleepIQBindingConstants.*; import java.util.Collections; import java.util.Set; +import java.util.concurrent.TimeUnit; -import org.openhab.binding.sleepiq.api.SleepIQ; -import org.openhab.binding.sleepiq.api.model.Bed; -import org.openhab.binding.sleepiq.api.model.BedSideStatus; -import org.openhab.binding.sleepiq.api.model.BedStatus; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.dto.BedSideStatus; +import org.openhab.binding.sleepiq.internal.api.dto.BedStatus; +import org.openhab.binding.sleepiq.internal.api.dto.SleepDataResponse; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.enums.Side; import org.openhab.binding.sleepiq.internal.config.SleepIQBedConfiguration; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.OnOffType; +import org.openhab.core.library.types.QuantityType; import org.openhab.core.library.types.StringType; +import org.openhab.core.library.unit.Units; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; @@ -33,10 +40,10 @@ import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.ThingStatusInfo; import org.openhab.core.thing.ThingTypeUID; import org.openhab.core.thing.binding.BaseThingHandler; -import org.openhab.core.thing.binding.BridgeHandler; import org.openhab.core.thing.binding.ThingHandler; import org.openhab.core.types.Command; import org.openhab.core.types.RefreshType; +import org.openhab.core.types.UnDefType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,12 +52,20 @@ import org.slf4j.LoggerFactory; * * @author Gregory Moyer - Initial contribution */ +@NonNullByDefault public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatusListener { public static final Set SUPPORTED_THING_TYPE_UIDS = Collections.singleton(THING_TYPE_DUAL_BED); + private static final long GET_SLEEP_DATA_DELAY_MINUTES = 5; + private final Logger logger = LoggerFactory.getLogger(SleepIQDualBedHandler.class); - private volatile String bedId; + private volatile @Nullable String bedId; + + private @Nullable Sleeper sleeperLeft; + private @Nullable Sleeper sleeperRight; + + private @Nullable BedStatus previousStatus; public SleepIQDualBedHandler(final Thing thing) { super(thing); @@ -58,80 +73,113 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus @Override public void initialize() { - logger.debug("Verifying SleepIQ cloud/bridge configuration"); - Bridge bridge = getBridge(); if (bridge == null) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No cloud service bridge has been configured"); return; } - ThingHandler handler = bridge.getHandler(); if (!(handler instanceof SleepIQCloudHandler)) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect bridge thing found"); return; } - - logger.debug("Reading SleepIQ bed binding configuration"); bedId = getConfigAs(SleepIQBedConfiguration.class).bedId; + if (bedId == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "Bed id not found in configuration"); + return; + } - logger.debug("Registering SleepIQ bed status listener"); + logger.debug("BedHandler: Registering SleepIQ bed status listener for bedId={}", bedId); SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) handler; cloudHandler.registerBedStatusListener(this); if (ThingStatus.ONLINE != bridge.getStatus()) { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE); } else { - updateProperties(); updateStatus(ThingStatus.ONLINE); + scheduler.execute(() -> { + updateProperties(); + }); + } + } + + @Override + public void dispose() { + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler != null) { + cloudHandler.unregisterBedStatusListener(this); } + bedId = null; } @Override public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) { super.bridgeStatusChanged(bridgeStatusInfo); - if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) { updateProperties(); } } - private void updateProperties() { - logger.debug("Updating SleepIQ bed properties for bed {}", bedId); - - SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) getBridge().getHandler(); - Bed bed = cloudHandler.getBed(bedId); - if (bed == null) { - updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bed found with ID " + bedId); + @Override + public void handleCommand(final ChannelUID channelUID, final Command command) { + if (command == RefreshType.REFRESH) { + // Channels will be refreshed automatically by cloud handler return; } - updateProperties(cloudHandler.updateProperties(bed, editProperties())); + switch (channelUID.getId()) { + case CHANNEL_LEFT_SLEEP_NUMBER: + case CHANNEL_RIGHT_SLEEP_NUMBER: + if (command instanceof DecimalType) { + Side side = Side.convertFromGroup(channelUID.getGroupId()); + logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side); + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler != null) { + cloudHandler.setSleepNumber(bedId, side, ((DecimalType) command).intValue()); + } + } + break; + case CHANNEL_LEFT_PRIVACY_MODE: + case CHANNEL_RIGHT_PRIVACY_MODE: + if (command instanceof OnOffType) { + Side side = Side.convertFromGroup(channelUID.getGroupId()); + logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side); + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler != null) { + cloudHandler.setPauseMode(bedId, command == OnOffType.ON ? true : false); + } + } + break; + } } @Override - public void dispose() { - logger.debug("Disposing bed handler for bed {}", bedId); - - Bridge bridge = getBridge(); - if (bridge != null) { - BridgeHandler bridgeHandler = bridge.getHandler(); - if (bridgeHandler instanceof SleepIQCloudHandler) { - ((SleepIQCloudHandler) bridgeHandler).unregisterBedStatusListener(this); - } + public void onSleeperChanged(final @Nullable Sleeper sleeper) { + if (sleeper == null || !sleeper.getBedId().equals(bedId)) { + return; } + logger.debug("BedHandler: Updating sleeper information channels for bed={}, side={}", bedId, sleeper.getSide()); - bedId = null; + if (sleeper.getSide().equals(Side.LEFT)) { + sleeperLeft = sleeper; + updateState(CHANNEL_LEFT_FIRST_NAME, new StringType(sleeper.getFirstName())); + updateState(CHANNEL_LEFT_SLEEP_GOAL_MINUTES, new QuantityType<>(sleeper.getSleepGoal(), Units.MINUTE)); + } else { + sleeperRight = sleeper; + updateState(CHANNEL_RIGHT_FIRST_NAME, new StringType(sleeper.getFirstName())); + updateState(CHANNEL_RIGHT_SLEEP_GOAL_MINUTES, new QuantityType<>(sleeper.getSleepGoal(), Units.MINUTE)); + } } @Override - public void onBedStateChanged(final SleepIQ cloud, final BedStatus status) { - if (!status.getBedId().equals(bedId)) { + public void onBedStateChanged(final @Nullable BedStatus status) { + if (status == null || !status.getBedId().equals(bedId)) { return; } + logger.debug("BedHandler: Updating bed status channels for bed {}", bedId); - logger.debug("Updating left side status for bed {}", bedId); BedSideStatus left = status.getLeftSide(); updateState(CHANNEL_LEFT_IN_BED, left.isInBed() ? OnOffType.ON : OnOffType.OFF); updateState(CHANNEL_LEFT_SLEEP_NUMBER, new DecimalType(left.getSleepNumber())); @@ -139,8 +187,10 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus updateState(CHANNEL_LEFT_LAST_LINK, new StringType(left.getLastLink().toString())); updateState(CHANNEL_LEFT_ALERT_ID, new DecimalType(left.getAlertId())); updateState(CHANNEL_LEFT_ALERT_DETAILED_MESSAGE, new StringType(left.getAlertDetailedMessage())); + if (previousStatus != null) { + updateSleepDataChannels(previousStatus.getLeftSide(), left, sleeperLeft); + } - logger.debug("Updating right side status for bed {}", bedId); BedSideStatus right = status.getRightSide(); updateState(CHANNEL_RIGHT_IN_BED, right.isInBed() ? OnOffType.ON : OnOffType.OFF); updateState(CHANNEL_RIGHT_SLEEP_NUMBER, new DecimalType(right.getSleepNumber())); @@ -148,15 +198,123 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus updateState(CHANNEL_RIGHT_LAST_LINK, new StringType(right.getLastLink().toString())); updateState(CHANNEL_RIGHT_ALERT_ID, new DecimalType(right.getAlertId())); updateState(CHANNEL_RIGHT_ALERT_DETAILED_MESSAGE, new StringType(right.getAlertDetailedMessage())); + if (previousStatus != null) { + updateSleepDataChannels(previousStatus.getRightSide(), right, sleeperRight); + } + + previousStatus = status; } - @Override - public void handleCommand(final ChannelUID channelUID, final Command command) { - // all channels are read-only + private void updateSleepDataChannels(BedSideStatus previousSideStatus, BedSideStatus currentSideStatus, + @Nullable Sleeper sleeper) { + if (sleeper == null) { + logger.debug("BedHandler: Can't update sleep data channels because sleeper is null"); + return; + } + if (previousSideStatus.isInBed() && !currentSideStatus.isInBed()) { + logger.debug("BedHandler: Bed status changed from IN BED to OUT OF BED for {}, side {}", bedId, + sleeper.getSide()); + scheduler.schedule(() -> { + updateDailySleepDataChannels(sleeper); + updateMonthlySleepDataChannels(sleeper); + }, GET_SLEEP_DATA_DELAY_MINUTES, TimeUnit.MINUTES); + } + } - if (command == RefreshType.REFRESH) { - SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) getBridge().getHandler(); - cloudHandler.refreshBedStatus(); + public void updateDailySleepDataChannels(final @Nullable Sleeper sleeper) { + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler == null || sleeper == null) { + return; + } + SleepDataResponse sleepData = cloudHandler.getDailySleepData(sleeper.getSleeperId()); + if (sleepData == null) { + logger.debug("BedHandler: Received no daily sleep data for bedId={}, sleeperId={}", sleeper.getBedId(), + sleeper.getSleeperId()); + return; + } + + logger.debug("BedHandler: UPDATING DAILY SLEEP DATA CHANNELS for bedId={}, sleeperId={}", sleeper.getBedId(), + sleeper.getSleeperId()); + if (sleepData.getSleepDataDays() == null || sleepData.getSleepDataDays().size() != 1) { + if (sleeper.getSide().equals(Side.LEFT)) { + updateState(CHANNEL_LEFT_TODAY_SLEEP_IQ, UnDefType.UNDEF); + updateState(CHANNEL_LEFT_TODAY_AVG_HEART_RATE, UnDefType.UNDEF); + updateState(CHANNEL_LEFT_TODAY_AVG_RESPIRATION_RATE, UnDefType.UNDEF); + updateState(CHANNEL_LEFT_TODAY_MESSAGE, UnDefType.UNDEF); + updateState(CHANNEL_LEFT_TODAY_SLEEP_DURATION_SECONDS, UnDefType.UNDEF); + } else { + updateState(CHANNEL_RIGHT_TODAY_SLEEP_IQ, UnDefType.UNDEF); + updateState(CHANNEL_RIGHT_TODAY_AVG_HEART_RATE, UnDefType.UNDEF); + updateState(CHANNEL_RIGHT_TODAY_AVG_RESPIRATION_RATE, UnDefType.UNDEF); + updateState(CHANNEL_RIGHT_TODAY_MESSAGE, UnDefType.UNDEF); + updateState(CHANNEL_RIGHT_TODAY_SLEEP_DURATION_SECONDS, UnDefType.UNDEF); + } + return; + } else if (sleeper.getSide().equals(Side.LEFT)) { + updateState(CHANNEL_LEFT_TODAY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ())); + updateState(CHANNEL_LEFT_TODAY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate())); + updateState(CHANNEL_LEFT_TODAY_AVG_RESPIRATION_RATE, + new DecimalType(sleepData.getAverageRespirationRate())); + updateState(CHANNEL_LEFT_TODAY_MESSAGE, new StringType(sleepData.getSleepDataDays().get(0).getMessage())); + updateState(CHANNEL_LEFT_TODAY_SLEEP_DURATION_SECONDS, + new QuantityType<>(sleepData.getTotalSleepSessionTime(), Units.SECOND)); + } else if (sleeper.getSide().equals(Side.RIGHT)) { + updateState(CHANNEL_RIGHT_TODAY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ())); + updateState(CHANNEL_RIGHT_TODAY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate())); + updateState(CHANNEL_RIGHT_TODAY_AVG_RESPIRATION_RATE, + new DecimalType(sleepData.getAverageRespirationRate())); + updateState(CHANNEL_RIGHT_TODAY_MESSAGE, new StringType(sleepData.getSleepDataDays().get(0).getMessage())); + updateState(CHANNEL_RIGHT_TODAY_SLEEP_DURATION_SECONDS, + new QuantityType<>(sleepData.getTotalSleepSessionTime(), Units.SECOND)); + } + } + + public void updateMonthlySleepDataChannels(final @Nullable Sleeper sleeper) { + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler == null || sleeper == null) { + return; + } + SleepDataResponse sleepData = cloudHandler.getMonthlySleepData(sleeper.getSleeperId()); + if (sleepData == null) { + logger.debug("BedHandler: Received no monthly sleep data for bedId={}, sleeperId={}", sleeper.getBedId(), + sleeper.getSleeperId()); + return; + } + + logger.debug("BedHandler: UPDATING MONTHLY SLEEP DATA CHANNELS for bedId={}, sleeperId={}", sleeper.getBedId(), + sleeper.getSleeperId()); + if (sleeper.getSide().equals(Side.LEFT)) { + updateState(CHANNEL_LEFT_MONTHLY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ())); + updateState(CHANNEL_LEFT_MONTHLY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate())); + updateState(CHANNEL_LEFT_MONTHLY_AVG_RESPIRATION_RATE, + new DecimalType(sleepData.getAverageRespirationRate())); + } else { + updateState(CHANNEL_RIGHT_MONTHLY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ())); + updateState(CHANNEL_RIGHT_MONTHLY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate())); + updateState(CHANNEL_RIGHT_MONTHLY_AVG_RESPIRATION_RATE, + new DecimalType(sleepData.getAverageRespirationRate())); + } + } + + private void updateProperties() { + logger.debug("BedHandler: Updating bed properties for bedId={}", bedId); + SleepIQCloudHandler cloudHandler = getCloudHandler(); + if (cloudHandler != null) { + Bed bed = cloudHandler.getBed(bedId); + if (bed == null) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, + "No bed found with ID " + bedId); + return; + } + updateProperties(cloudHandler.updateProperties(bed, editProperties())); + } + } + + private @Nullable SleepIQCloudHandler getCloudHandler() { + Bridge bridge = getBridge(); + if (bridge != null) { + return (SleepIQCloudHandler) bridge.getHandler(); } + return null; } } diff --git a/bundles/org.openhab.binding.sleepiq/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.sleepiq/src/main/resources/OH-INF/thing/thing-types.xml index ebef3f07c6..2c91eac630 100644 --- a/bundles/org.openhab.binding.sleepiq/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.sleepiq/src/main/resources/OH-INF/thing/thing-types.xml @@ -19,14 +19,14 @@ Username of a registered SleepIQ account owner - password Password of a registered SleepIQ account owner + password Seconds between fetching values from the cloud service - 60 + 120 @@ -86,6 +86,17 @@ + + + + + + + + + + + @@ -99,7 +110,7 @@ Number The Sleep Number setting of the chamber - + Number @@ -126,5 +137,71 @@ A detailed message describing an alert condition with the chamber + + String + + The first name of the sleeper + + + + Number:Time + + The goal for the amount of sleep per night (in minutes) + + + + Switch + + Enable/disable privacy mode + + + + Number + + The Sleep Quotient for today + + + + Number + + The average heart rate for today + + + + Number + + The average respiration rate for today + + + + String + + The description of today's sleep quality + + + + Number:Time + + The total duration of sleep for today in seconds + + + + Number + + The overall Sleep Quotient for the past month + + + + Number + + The average heart rate for the past month + + + + Number + + The average respiration rate for the past month + + diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java new file mode 100644 index 0000000000..8c510540d1 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileReader; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.BedSideStatus; +import org.openhab.binding.sleepiq.internal.api.dto.TimeSince; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link BedSideStatusTest} tests deserialization of a bed side status object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class BedSideStatusTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + BedSideStatus bedSideStatus = new BedSideStatus().withAlertDetailedMessage("No Alert").withAlertId(0L) + .withInBed(false).withLastLink(new TimeSince().withDuration(3, 5, 4, 38)).withPressure(573) + .withSleepNumber(55); + assertEquals(readJson("bed-side-status.json"), gson.toJson(bedSideStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("bed-side-status.json"))) { + BedSideStatus bedSideStatus = gson.fromJson(reader, BedSideStatus.class); + assertEquals("No Alert", bedSideStatus.getAlertDetailedMessage()); + assertEquals(Long.valueOf(0L), bedSideStatus.getAlertId()); + assertFalse(bedSideStatus.isInBed()); + assertEquals(new TimeSince().withDuration(3, 5, 4, 38), bedSideStatus.getLastLink()); + assertEquals(Integer.valueOf(573), bedSideStatus.getPressure()); + assertEquals(Integer.valueOf(55), bedSideStatus.getSleepNumber()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java new file mode 100644 index 0000000000..83bbf81328 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileReader; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.BedSideStatus; +import org.openhab.binding.sleepiq.internal.api.dto.BedStatus; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link BedStatusText} tests deserialization of a bed status object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class BedStatusTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + BedStatus bedStatus = new BedStatus().withBedId("-9999999999999999999") + .withLeftSide(new BedSideStatus().withInBed(true)).withRightSide(new BedSideStatus().withInBed(false)) + .withStatus(1L); + assertEquals(readJson("bed-status.json"), gson.toJson(bedStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("bed-status.json"))) { + BedStatus bedStatus = gson.fromJson(reader, BedStatus.class); + assertEquals("-9999999999999999999", bedStatus.getBedId()); + assertEquals(Long.valueOf(1L), bedStatus.getStatus()); + + BedSideStatus leftSide = bedStatus.getLeftSide(); + assertNotNull(leftSide); + assertTrue(leftSide.isInBed()); + + BedSideStatus rightSide = bedStatus.getRightSide(); + assertNotNull(rightSide); + assertFalse(rightSide.isInBed()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java new file mode 100644 index 0000000000..5bf26e0b76 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.FileReader; +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link BedTest} tests deserialization of a bed object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class BedTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + Bed bed = new Bed().withAccountId("-8888888888888888888").withBase("MODULAR").withBedId("-9999999999999999999") + .withDualSleep(true).withKidsBed(false).withMacAddress("AABBCCDDEEFF").withModel("P5").withName("Bed") + .withPurchaseDate(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized())) + .withReference("55555555555-5") + .withRegistrationDate(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized())) + .withReturnRequestStatus(0L).withSerial("").withSize("QUEEN").withSku("QP5") + .withSleeperLeftId("-2222222222222222222").withSleeperRightId("-1111111111111111111").withStatus(1L) + .withTimezone("US/Pacific").withVersion("").withZipCode("90210"); + assertEquals(readJson("bed.json"), gson.toJson(bed)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("bed.json"))) { + Bed bed = gson.fromJson(reader, Bed.class); + assertEquals("-8888888888888888888", bed.getAccountId()); + assertEquals("MODULAR", bed.getBase()); + assertEquals("-9999999999999999999", bed.getBedId()); + assertEquals(true, bed.isDualSleep()); + assertEquals(false, bed.isKidsBed()); + assertEquals("AABBCCDDEEFF", bed.getMacAddress()); + assertEquals("P5", bed.getModel()); + assertEquals("Bed", bed.getName()); + assertEquals(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()), bed.getPurchaseDate()); + assertEquals("55555555555-5", bed.getReference()); + assertEquals(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()), + bed.getRegistrationDate()); + assertEquals(Long.valueOf(0L), bed.getReturnRequestStatus()); + assertEquals("", bed.getSerial()); + assertEquals("QUEEN", bed.getSize()); + assertEquals("QP5", bed.getSku()); + assertEquals("-2222222222222222222", bed.getSleeperLeftId()); + assertEquals("-1111111111111111111", bed.getSleeperRightId()); + assertEquals(Long.valueOf(1L), bed.getStatus()); + assertEquals("US/Pacific", bed.getTimezone()); + assertEquals("", bed.getVersion()); + assertEquals("90210", bed.getZipCode()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java new file mode 100644 index 0000000000..147613a59a --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.Bed; +import org.openhab.binding.sleepiq.internal.api.dto.BedsResponse; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link BedsResponseTest} tests deserialization of a beds response object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class BedsResponseTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + BedsResponse bedsResponse = new BedsResponse() + .withBeds(Arrays.asList(new Bed().withName("Bed1"), new Bed().withName("Bed2"))); + assertEquals(readJson("beds-response.json"), gson.toJson(bedsResponse)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("beds-response.json"))) { + BedsResponse bedsResponse = gson.fromJson(reader, BedsResponse.class); + + List beds = bedsResponse.getBeds(); + assertNotNull(beds); + assertEquals(2, beds.size()); + assertEquals("Bed1", beds.get(0).getName()); + assertEquals("Bed2", beds.get(1).getName()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java new file mode 100644 index 0000000000..6dd01daeb0 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.BedStatus; +import org.openhab.binding.sleepiq.internal.api.dto.FamilyStatusResponse; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link FamilyStatusText} tests deserialization of a family status object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class FamilyStatusTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + FamilyStatusResponse familyStatus = new FamilyStatusResponse() + .withBeds(Arrays.asList(new BedStatus().withStatus(1L))); + assertEquals(readJson("family-status.json"), gson.toJson(familyStatus)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("family-status.json"))) { + FamilyStatusResponse familyStatus = gson.fromJson(reader, FamilyStatusResponse.class); + + List beds = familyStatus.getBeds(); + assertNotNull(beds); + assertEquals(1, beds.size()); + assertEquals(Long.valueOf(1L), beds.get(0).getStatus()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/PauseModeTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/PauseModeTest.java new file mode 100644 index 0000000000..438c05e01f --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/PauseModeTest.java @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.FileReader; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.PauseModeResponse; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link PauseModeTest} tests deserialization of a pause mode object. + * + * @author Mark Hilbush - Initial contribution + */ +@NonNullByDefault +public class PauseModeTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + PauseModeResponse pauseMode = new PauseModeResponse().withAccountId("-8888888888888888888") + .withBedId("-9999999999999999999").withPauseMode("off"); + assertEquals(readJson("pause-mode.json"), gson.toJson(pauseMode)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("pause-mode.json"))) { + PauseModeResponse pauseMode = gson.fromJson(reader, PauseModeResponse.class); + assertEquals("-8888888888888888888", pauseMode.getAccountId()); + assertEquals("-9999999999999999999", pauseMode.getBedId()); + assertEquals("off", pauseMode.getPauseMode()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java new file mode 100644 index 0000000000..28cbabfbf5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.FileReader; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.enums.Side; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link SleeperTest} tests deserialization of a sleeper object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class SleeperTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + Sleeper sleeper = new Sleeper().withAccountId("-5555555555555555555").withAccountOwner(true).withActive(true) + .withAvatar("").withBedId("-9999999999999999999").withBirthMonth(6).withBirthYear("1970") + .withChild(false).withDuration("").withEmail("alice@domain.com").withEmailValidated(true) + .withFirstName("Alice").withHeight(64).withLastLogin("2017-02-17 20:19:36 CST").withLicenseVersion(6L) + .withMale(false).withSide(Side.RIGHT).withSleeperId("-1111111111111111111").withSleepGoal(450) + .withTimezone("US/Pacific").withUsername("alice@domain.com").withWeight(110).withZipCode("90210"); + assertEquals(readJson("sleeper.json"), gson.toJson(sleeper)); + } + + @Test + public void testSerializeLastLoginNull() throws Exception { + Sleeper sleeper = new Sleeper().withLastLogin("null"); + assertEquals(readJson("sleeper-lastlogin-null.json"), gson.toJson(sleeper)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("sleeper.json"))) { + Sleeper sleeper = gson.fromJson(reader, Sleeper.class); + assertEquals("-5555555555555555555", sleeper.getAccountId()); + assertEquals(true, sleeper.isAccountOwner()); + assertEquals(true, sleeper.isActive()); + assertEquals("", sleeper.getAvatar()); + assertEquals("-9999999999999999999", sleeper.getBedId()); + assertEquals(Integer.valueOf(6), sleeper.getBirthMonth()); + assertEquals("1970", sleeper.getBirthYear()); + assertEquals(false, sleeper.isChild()); + assertEquals("", sleeper.getDuration()); + assertEquals("alice@domain.com", sleeper.getEmail()); + assertEquals(true, sleeper.isEmailValidated()); + assertEquals("Alice", sleeper.getFirstName()); + assertEquals(Integer.valueOf(64), sleeper.getHeight()); + assertEquals("2017-02-17 20:19:36 CST", sleeper.getLastLogin()); + assertEquals(Long.valueOf(6L), sleeper.getLicenseVersion()); + assertEquals(false, sleeper.isMale()); + assertEquals(Side.RIGHT, sleeper.getSide()); + assertEquals("-1111111111111111111", sleeper.getSleeperId()); + assertEquals(Integer.valueOf(450), sleeper.getSleepGoal()); + assertEquals("US/Pacific", sleeper.getTimezone()); + assertEquals("alice@domain.com", sleeper.getUsername()); + assertEquals(Integer.valueOf(110), sleeper.getWeight()); + assertEquals("90210", sleeper.getZipCode()); + } + } + + @Test + public void testDeserializeLastLoginNull() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("sleeper-lastlogin-null.json"))) { + Sleeper sleeper = gson.fromJson(reader, Sleeper.class); + assertEquals("null", sleeper.getLastLogin()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java new file mode 100644 index 0000000000..6c866222aa --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.FileReader; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.api.test.AbstractTest; +import org.openhab.binding.sleepiq.internal.api.dto.Sleeper; +import org.openhab.binding.sleepiq.internal.api.dto.SleepersResponse; +import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator; + +import com.google.gson.Gson; + +/** + * The {@link SleepersResponseTest} tests deserialization of a sleepers response object. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class SleepersResponseTest extends AbstractTest { + private static Gson gson = GsonGenerator.create(true); + + @Test + public void testSerializeAllFields() throws Exception { + SleepersResponse sleepersResponse = new SleepersResponse() + .withSleepers(Arrays.asList(new Sleeper().withFirstName("Alice"), new Sleeper().withFirstName("Bob"))); + assertEquals(readJson("sleepers-response.json"), gson.toJson(sleepersResponse)); + } + + @Test + public void testDeserializeAllFields() throws Exception { + try (FileReader reader = new FileReader(getTestDataFile("sleepers-response.json"))) { + SleepersResponse sleepersResponse = gson.fromJson(reader, SleepersResponse.class); + + List sleepers = sleepersResponse.getSleepers(); + assertNotNull(sleepers); + assertEquals(2, sleepers.size()); + assertEquals("Alice", sleepers.get(0).getFirstName()); + assertEquals("Bob", sleepers.get(1).getFirstName()); + } + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java new file mode 100644 index 0000000000..50f15d3eef --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.Duration; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.junit.jupiter.api.Test; +import org.openhab.binding.sleepiq.internal.api.dto.TimeSince; + +/** + * The {@link TimeSinceText} tests TimeSince. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public class TimeSinceTest { + @Test + public void testWithDuration() { + assertEquals(new TimeSince().withDuration(0, 0, 0, 0).getDuration(), + new TimeSince().withDuration(Duration.parse("PT00H00M00S")).getDuration()); + assertEquals(new TimeSince().withDuration(0, 2, 3, 4).getDuration(), + new TimeSince().withDuration(Duration.parse("PT02H03M04S")).getDuration()); + assertEquals(new TimeSince().withDuration(0, 12, 34, 56).getDuration(), + new TimeSince().withDuration(Duration.parse("PT12H34M56S")).getDuration()); + assertEquals(new TimeSince().withDuration(1, 2, 3, 4).getDuration(), + new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).getDuration()); + assertEquals(new TimeSince().withDuration(12, 23, 34, 45).getDuration(), + new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).getDuration()); + } + + @Test + public void testToString() { + assertEquals("00:00:00", new TimeSince().withDuration(Duration.parse("PT00H00M00S")).toString()); + assertEquals("02:03:04", new TimeSince().withDuration(Duration.parse("PT02H03M04S")).toString()); + assertEquals("12:34:56", new TimeSince().withDuration(Duration.parse("PT12H34M56S")).toString()); + assertEquals("1 d 02:03:04", new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).toString()); + assertEquals("12 d 23:34:45", new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).toString()); + } + + @Test + public void testParse() { + assertEquals(Duration.parse("PT00H00M00S"), TimeSince.parse("00:00:00").getDuration()); + assertEquals(Duration.parse("PT2H3M4S"), TimeSince.parse("02:03:04").getDuration()); + assertEquals(Duration.parse("PT12H34M56S"), TimeSince.parse("12:34:56").getDuration()); + assertEquals(Duration.parse("P1DT2H3M4S"), TimeSince.parse("1 d 02:03:04").getDuration()); + assertEquals(Duration.parse("P12DT23H34M45S"), TimeSince.parse("12 d 23:34:45").getDuration()); + } +} diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java new file mode 100644 index 0000000000..d3b541a9e5 --- /dev/null +++ b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2010-2023 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.sleepiq.api.test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link AbstractTest} tests deserialization of a sleepiq API objects. + * + * @author Gregory Moyer - Initial contribution + */ +@NonNullByDefault +public abstract class AbstractTest { + private static final String RESOURCES_PATH = "src/test/resources/"; + + protected File getTestDataFile(String name) { + return getTestDataPath(name).toFile(); + } + + @SuppressWarnings("null") + protected Path getTestDataPath(String name) { + String packageName = this.getClass().getPackage().getName(); + + List paths = new ArrayList<>(); + paths.addAll(Arrays.asList(packageName.split("\\."))); + paths.add(name); + + return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()])); + } + + protected String readJson(String jsonFileName) throws IOException { + return String.join("\n", Files.readAllLines(getTestDataPath(jsonFileName))); + } +}