diff --git a/CODEOWNERS b/CODEOWNERS index 0a9c9c64b..34ff5b5d4 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 4e47a9f47..d56c2a618 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. +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 | -| 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 | +| 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 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 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_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 754bf4078..842ada642 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 3eba85684..000000000 --- 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/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java deleted file mode 100644 index 6480ae4ff..000000000 --- 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 5785b24f7..000000000 --- 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 55935c1f7..000000000 --- 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 5a809005f..000000000 --- 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 5ce38e5ef..000000000 --- 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 7f5e3cbce..000000000 --- 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 a1e8f348e..000000000 --- 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 fb67e9b0a..000000000 --- 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 df1b85a38..000000000 --- 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 e148736f3..000000000 --- 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 7651064f6..000000000 --- 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 5f4b4f4d0..000000000 --- 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 4de838cf8..000000000 --- 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 10360c9ae..000000000 --- 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 3ac2762db..000000000 --- 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 597301e2f..000000000 --- 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 5a1ab7fe7..000000000 --- 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 ded37fd97..000000000 --- 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 e6f49e783..000000000 --- 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 74ade1885..000000000 --- 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/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 3504e1bfb..000000000 --- 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 5fe0a6e97..000000000 --- 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 37f2153a1..000000000 --- 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 0d31cad1a..000000000 --- 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/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java deleted file mode 100644 index c07fbd8d8..000000000 --- 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 3b3deeea0..000000000 --- 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 5593b59fe..000000000 --- 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 4ab0481e8..000000000 --- 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 cddea5a60..000000000 --- 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/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java deleted file mode 100644 index 07835f054..000000000 --- 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 562788646..000000000 --- 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/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java deleted file mode 100644 index 4c793ef1a..000000000 --- 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/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 2fa201693..000000000 --- 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 d36bd3acc..000000000 --- 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/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 1438a5e2c..000000000 --- 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 f5eb4642a..63023921a 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 e4fc45aed..a599b1a7b 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 318974b29..7bda6c000 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 000000000..de653f6b9 --- /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 000000000..f25f94a9a --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java similarity index 68% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java index cb0fd28ba..861b4a11b 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java @@ -1,34 +1,32 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api; +package org.openhab.binding.sleepiq.internal.api; import java.net.URI; -import java.util.logging.Level; + +import org.eclipse.jdt.annotation.NonNullByDefault; /** * This class represents configuration parameters for using {@link SleepIQ}. * - * @author Gregory Moyer + * @author Gregory Moyer - Initial contribution */ -public class Configuration -{ - private String username; - private String password; +@NonNullByDefault +public class Configuration { + private String username = ""; + private String password = ""; - private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com/rest"); + private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com"); private boolean logging = false; @@ -37,8 +35,7 @@ public class Configuration * * @return the username */ - public String getUsername() - { + public String getUsername() { return username; } @@ -49,8 +46,7 @@ public class Configuration * @param username * the value to set */ - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } @@ -62,8 +58,7 @@ public class Configuration * the value to set * @return this configuration instance */ - public Configuration withUsername(String username) - { + public Configuration withUsername(String username) { setUsername(username); return this; } @@ -73,8 +68,7 @@ public class Configuration * * @return the password */ - public String getPassword() - { + public String getPassword() { return password; } @@ -85,8 +79,7 @@ public class Configuration * @param password * the value to set */ - public void setPassword(String password) - { + public void setPassword(String password) { this.password = password; } @@ -98,8 +91,7 @@ public class Configuration * the value to set * @return this configuration instance */ - public Configuration withPassword(String password) - { + public Configuration withPassword(String password) { setPassword(password); return this; } @@ -109,8 +101,7 @@ public class Configuration * * @return the base URI */ - public URI getBaseUri() - { + public URI getBaseUri() { return baseUri; } @@ -121,8 +112,7 @@ public class Configuration * @param baseUri * the value to set */ - public void setBaseUri(URI baseUri) - { + public void setBaseUri(URI baseUri) { this.baseUri = baseUri; } @@ -134,8 +124,7 @@ public class Configuration * the value to set * @return this configuration instance */ - public Configuration withBaseUri(URI baseUri) - { + public Configuration withBaseUri(URI baseUri) { setBaseUri(baseUri); return this; } @@ -145,8 +134,7 @@ public class Configuration * * @return the logging flag */ - public boolean isLogging() - { + public boolean isLogging() { return logging; } @@ -158,8 +146,7 @@ public class Configuration * @param logging * the value to set */ - public void setLogging(boolean logging) - { + public void setLogging(boolean logging) { this.logging = logging; } @@ -172,8 +159,7 @@ public class Configuration * the value to set * @return this configuration instance */ - public Configuration withLogging(boolean logging) - { + 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 000000000..fcd957c1d --- /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 000000000..07a18b8c2 --- /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 000000000..ca6a9bf74 --- /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 000000000..bf463e46f --- /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 000000000..98a47781d --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java similarity index 60% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java index 6bfa86db0..c8342cc9e 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java @@ -1,26 +1,27 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api.model; +package org.openhab.binding.sleepiq.internal.api.dto; import java.time.ZonedDateTime; import com.google.gson.annotations.SerializedName; -public class Bed -{ +/** + * 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; @@ -45,345 +46,281 @@ public class Bed private String zipCode; private String reference; - public ZonedDateTime getRegistrationDate() - { + public ZonedDateTime getRegistrationDate() { return registrationDate; } - public void setRegistrationDate(ZonedDateTime registrationDate) - { + public void setRegistrationDate(ZonedDateTime registrationDate) { this.registrationDate = registrationDate; } - public Bed withRegistrationDate(ZonedDateTime registrationDate) - { + public Bed withRegistrationDate(ZonedDateTime registrationDate) { setRegistrationDate(registrationDate); return this; } - public String getSleeperRightId() - { + public String getSleeperRightId() { return sleeperRightId; } - public void setSleeperRightId(String sleeperRightId) - { + public void setSleeperRightId(String sleeperRightId) { this.sleeperRightId = sleeperRightId; } - public Bed withSleeperRightId(String sleeperRightId) - { + public Bed withSleeperRightId(String sleeperRightId) { setSleeperRightId(sleeperRightId); return this; } - public String getBase() - { + public String getBase() { return base; } - public void setBase(String base) - { + public void setBase(String base) { this.base = base; } - public Bed withBase(String base) - { + public Bed withBase(String base) { setBase(base); return this; } - public Long getReturnRequestStatus() - { + public Long getReturnRequestStatus() { return returnRequestStatus; } - public void setReturnRequestStatus(Long returnRequestStatus) - { + public void setReturnRequestStatus(Long returnRequestStatus) { this.returnRequestStatus = returnRequestStatus; } - public Bed withReturnRequestStatus(Long returnRequestStatus) - { + public Bed withReturnRequestStatus(Long returnRequestStatus) { setReturnRequestStatus(returnRequestStatus); return this; } - public String getSize() - { + public String getSize() { return size; } - public void setSize(String size) - { + public void setSize(String size) { this.size = size; } - public Bed withSize(String size) - { + public Bed withSize(String size) { setSize(size); return this; } - public String getName() - { + public String getName() { return name; } - public void setName(String name) - { + public void setName(String name) { this.name = name; } - public Bed withName(String name) - { + public Bed withName(String name) { setName(name); return this; } - public String getSerial() - { + public String getSerial() { return serial; } - public void setSerial(String serial) - { + public void setSerial(String serial) { this.serial = serial; } - public Bed withSerial(String serial) - { + public Bed withSerial(String serial) { setSerial(serial); return this; } - public Boolean isKidsBed() - { + public Boolean isKidsBed() { return kidsBed; } - public void setKidsBed(Boolean kidsBed) - { + public void setKidsBed(Boolean kidsBed) { this.kidsBed = kidsBed; } - public Bed withKidsBed(Boolean kidsBed) - { + public Bed withKidsBed(Boolean kidsBed) { setKidsBed(kidsBed); return this; } - public Boolean isDualSleep() - { + public Boolean isDualSleep() { return dualSleep; } - public void setDualSleep(Boolean dualSleep) - { + public void setDualSleep(Boolean dualSleep) { this.dualSleep = dualSleep; } - public Bed withDualSleep(Boolean dualSleep) - { + public Bed withDualSleep(Boolean dualSleep) { setDualSleep(dualSleep); return this; } - public String getBedId() - { + public String getBedId() { return bedId; } - public void setBedId(String bedId) - { + public void setBedId(String bedId) { this.bedId = bedId; } - public Bed withBedId(String bedId) - { + public Bed withBedId(String bedId) { setBedId(bedId); return this; } - public Long getStatus() - { + public Long getStatus() { return status; } - public void setStatus(Long status) - { + public void setStatus(Long status) { this.status = status; } - public Bed withStatus(Long status) - { + public Bed withStatus(Long status) { setStatus(status); return this; } - public String getSleeperLeftId() - { + public String getSleeperLeftId() { return sleeperLeftId; } - public void setSleeperLeftId(String sleeperLeftId) - { + public void setSleeperLeftId(String sleeperLeftId) { this.sleeperLeftId = sleeperLeftId; } - public Bed withSleeperLeftId(String sleeperLeftId) - { + public Bed withSleeperLeftId(String sleeperLeftId) { setSleeperLeftId(sleeperLeftId); return this; } - public String getVersion() - { + public String getVersion() { return version; } - public void setVersion(String version) - { + public void setVersion(String version) { this.version = version; } - public Bed withVersion(String version) - { + public Bed withVersion(String version) { setVersion(version); return this; } - public String getAccountId() - { + public String getAccountId() { return accountId; } - public void setAccountId(String accountId) - { + public void setAccountId(String accountId) { this.accountId = accountId; } - public Bed withAccountId(String accountId) - { + public Bed withAccountId(String accountId) { setAccountId(accountId); return this; } - public String getTimezone() - { + public String getTimezone() { return timezone; } - public void setTimezone(String timezone) - { + public void setTimezone(String timezone) { this.timezone = timezone; } - public Bed withTimezone(String timezone) - { + public Bed withTimezone(String timezone) { setTimezone(timezone); return this; } - public String getModel() - { + public String getModel() { return model; } - public void setModel(String model) - { + public void setModel(String model) { this.model = model; } - public Bed withModel(String model) - { + public Bed withModel(String model) { setModel(model); return this; } - public ZonedDateTime getPurchaseDate() - { + public ZonedDateTime getPurchaseDate() { return purchaseDate; } - public void setPurchaseDate(ZonedDateTime purchaseDate) - { + public void setPurchaseDate(ZonedDateTime purchaseDate) { this.purchaseDate = purchaseDate; } - public Bed withPurchaseDate(ZonedDateTime purchaseDate) - { + public Bed withPurchaseDate(ZonedDateTime purchaseDate) { setPurchaseDate(purchaseDate); return this; } - public String getMacAddress() - { + public String getMacAddress() { return macAddress; } - public void setMacAddress(String macAddress) - { + public void setMacAddress(String macAddress) { this.macAddress = macAddress; } - public Bed withMacAddress(String macAddress) - { + public Bed withMacAddress(String macAddress) { setMacAddress(macAddress); return this; } - public String getSku() - { + public String getSku() { return sku; } - public void setSku(String sku) - { + public void setSku(String sku) { this.sku = sku; } - public Bed withSku(String sku) - { + public Bed withSku(String sku) { setSku(sku); return this; } - public String getZipCode() - { + public String getZipCode() { return zipCode; } - public void setZipCode(String zipCode) - { + public void setZipCode(String zipCode) { this.zipCode = zipCode; } - public Bed withZipCode(String zipCode) - { + public Bed withZipCode(String zipCode) { setZipCode(zipCode); return this; } - public String getReference() - { + public String getReference() { return reference; } - public void setReference(String reference) - { + public void setReference(String reference) { this.reference = reference; } - public Bed withReference(String reference) - { + public Bed withReference(String reference) { setReference(reference); return this; } @Override - public int hashCode() - { + public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((bedId == null) ? 0 : bedId.hashCode()); @@ -391,38 +328,29 @@ public class Bed } @Override - public boolean equals(Object obj) - { - if (this == obj) - { + public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) - { + if (obj == null) { return false; } - if (!(obj instanceof Bed)) - { + if (!(obj instanceof Bed)) { return false; } - Bed other = (Bed)obj; - if (bedId == null) - { - if (other.bedId != null) - { + Bed other = (Bed) obj; + if (bedId == null) { + if (other.bedId != null) { return false; } - } - else if (!bedId.equals(other.bedId)) - { + } else if (!bedId.equals(other.bedId)) { return false; } return true; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Bed [registrationDate="); builder.append(registrationDate); 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/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java similarity index 50% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java index b7e994b2b..72844ffa9 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java @@ -1,24 +1,25 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api.model; +package org.openhab.binding.sleepiq.internal.api.dto; import com.google.gson.annotations.SerializedName; -public class BedSideStatus -{ +/** + * 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; @@ -27,109 +28,89 @@ public class BedSideStatus private TimeSince lastLink; private Integer pressure; // appears to be in kPa - public Boolean isInBed() - { + public Boolean isInBed() { return inBed; } - public void setInBed(Boolean inBed) - { + public void setInBed(Boolean inBed) { this.inBed = inBed; } - public BedSideStatus withInBed(Boolean inBed) - { + public BedSideStatus withInBed(Boolean inBed) { setInBed(inBed); return this; } - public String getAlertDetailedMessage() - { + public String getAlertDetailedMessage() { return alertDetailedMessage; } - public void setAlertDetailedMessage(String alertDetailedMessage) - { + public void setAlertDetailedMessage(String alertDetailedMessage) { this.alertDetailedMessage = alertDetailedMessage; } - public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) - { + public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) { setAlertDetailedMessage(alertDetailedMessage); return this; } - public Integer getSleepNumber() - { + public Integer getSleepNumber() { return sleepNumber; } - public void setSleepNumber(Integer sleepNumber) - { + public void setSleepNumber(Integer sleepNumber) { this.sleepNumber = sleepNumber; } - public BedSideStatus withSleepNumber(Integer sleepNumber) - { + public BedSideStatus withSleepNumber(Integer sleepNumber) { setSleepNumber(sleepNumber); return this; } - public Long getAlertId() - { + public Long getAlertId() { return alertId; } - public void setAlertId(Long alertId) - { + public void setAlertId(Long alertId) { this.alertId = alertId; } - public BedSideStatus withAlertId(Long alertId) - { + public BedSideStatus withAlertId(Long alertId) { setAlertId(alertId); return this; } - public TimeSince getLastLink() - { + public TimeSince getLastLink() { return lastLink; } - public void setLastLink(TimeSince lastLink) - { + public void setLastLink(TimeSince lastLink) { this.lastLink = lastLink; } - public BedSideStatus withLastLink(TimeSince lastLink) - { + public BedSideStatus withLastLink(TimeSince lastLink) { setLastLink(lastLink); return this; } - public Integer getPressure() - { + public Integer getPressure() { return pressure; } - public void setPressure(Integer pressure) - { + public void setPressure(Integer pressure) { this.pressure = pressure; } - public BedSideStatus withPressure(Integer pressure) - { + public BedSideStatus withPressure(Integer pressure) { setPressure(pressure); return this; } @Override - public int hashCode() - { + public int hashCode() { final int prime = 31; int result = 1; - result = prime * result - + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode()); + 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()); @@ -139,93 +120,64 @@ public class BedSideStatus } @Override - public boolean equals(Object obj) - { - if (this == obj) - { + public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) - { + if (obj == null) { return false; } - if (!(obj instanceof BedSideStatus)) - { + if (!(obj instanceof BedSideStatus)) { return false; } - BedSideStatus other = (BedSideStatus)obj; - if (alertDetailedMessage == null) - { - if (other.alertDetailedMessage != null) - { + BedSideStatus other = (BedSideStatus) obj; + if (alertDetailedMessage == null) { + if (other.alertDetailedMessage != null) { return false; } - } - else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) - { + } else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) { return false; } - if (alertId == null) - { - if (other.alertId != null) - { + if (alertId == null) { + if (other.alertId != null) { return false; } - } - else if (!alertId.equals(other.alertId)) - { + } else if (!alertId.equals(other.alertId)) { return false; } - if (inBed == null) - { - if (other.inBed != null) - { + if (inBed == null) { + if (other.inBed != null) { return false; } - } - else if (!inBed.equals(other.inBed)) - { + } else if (!inBed.equals(other.inBed)) { return false; } - if (lastLink == null) - { - if (other.lastLink != null) - { + if (lastLink == null) { + if (other.lastLink != null) { return false; } - } - else if (!lastLink.equals(other.lastLink)) - { + } else if (!lastLink.equals(other.lastLink)) { return false; } - if (pressure == null) - { - if (other.pressure != null) - { + if (pressure == null) { + if (other.pressure != null) { return false; } - } - else if (!pressure.equals(other.pressure)) - { + } else if (!pressure.equals(other.pressure)) { return false; } - if (sleepNumber == null) - { - if (other.sleepNumber != null) - { + if (sleepNumber == null) { + if (other.sleepNumber != null) { return false; } - } - else if (!sleepNumber.equals(other.sleepNumber)) - { + } else if (!sleepNumber.equals(other.sleepNumber)) { return false; } return true; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("BedSideStatus [inBed="); builder.append(inBed); 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 000000000..c5f25ab11 --- /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 000000000..9cdaa4dab --- /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 000000000..6865067ae --- /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 000000000..028055c4b --- /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 000000000..b0f90c12d --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java similarity index 51% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java index 7cc35096f..9f51fc92f 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java @@ -1,167 +1,138 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api.model; +package org.openhab.binding.sleepiq.internal.api.dto; -public class LoginInfo -{ +/** + * 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() - { + public String getUserId() { return userId; } - public void setUserId(String userId) - { + public void setUserId(String userId) { this.userId = userId; } - public LoginInfo withUserId(String userId) - { + public LoginInfo withUserId(String userId) { setUserId(userId); return this; } - public String getKey() - { + public String getKey() { return key; } - public void setKey(String key) - { + public void setKey(String key) { this.key = key; } - public LoginInfo withKey(String key) - { + public LoginInfo withKey(String key) { setKey(key); return this; } - public Long getRegistrationState() - { + public Long getRegistrationState() { return registrationState; } - public void setRegistrationState(Long registrationState) - { + public void setRegistrationState(Long registrationState) { this.registrationState = registrationState; } - public LoginInfo withRegistrationState(Long registrationState) - { + public LoginInfo withRegistrationState(Long registrationState) { setRegistrationState(registrationState); return this; } - public Long getEdpLoginStatus() - { + public Long getEdpLoginStatus() { return edpLoginStatus; } - public void setEdpLoginStatus(Long edpLoginStatus) - { + public void setEdpLoginStatus(Long edpLoginStatus) { this.edpLoginStatus = edpLoginStatus; } - public LoginInfo withEdpLoginStatus(Long edpLoginStatus) - { + public LoginInfo withEdpLoginStatus(Long edpLoginStatus) { setEdpLoginStatus(edpLoginStatus); return this; } - public String getEdpLoginMessage() - { + public String getEdpLoginMessage() { return edpLoginMessage; } - public void setEdpLoginMessage(String edpLoginMessage) - { + public void setEdpLoginMessage(String edpLoginMessage) { this.edpLoginMessage = edpLoginMessage; } - public LoginInfo withEdpLoginMessage(String edpLoginMessage) - { + public LoginInfo withEdpLoginMessage(String edpLoginMessage) { setEdpLoginMessage(edpLoginMessage); return this; } @Override - public int hashCode() - { + 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 + (int) (registrationState ^ (registrationState >>> 32)); result = prime * result + ((userId == null) ? 0 : userId.hashCode()); return result; } @Override - public boolean equals(Object obj) - { - if (this == obj) - { + public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) - { + if (obj == null) { return false; } - if (!(obj instanceof LoginInfo)) - { + if (!(obj instanceof LoginInfo)) { return false; } - LoginInfo other = (LoginInfo)obj; - if (key == null) - { - if (other.key != null) - { + LoginInfo other = (LoginInfo) obj; + if (key == null) { + if (other.key != null) { return false; } - } - else if (!key.equals(other.key)) - { + } else if (!key.equals(other.key)) { return false; } - if (!registrationState.equals(other.registrationState)) - { + if (!registrationState.equals(other.registrationState)) { return false; } - if (userId == null) - { - if (other.userId != null) - { + if (userId == null) { + if (other.userId != null) { return false; } - } - else if (!userId.equals(other.userId)) - { + } else if (!userId.equals(other.userId)) { return false; } return true; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("LoginInfo [userId="); builder.append(userId); 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 000000000..6cbe4d112 --- /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 000000000..f536d800c --- /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 000000000..966093bde --- /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 000000000..72ee26f13 --- /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 000000000..c8a36e72d --- /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 000000000..be6cd94de --- /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 000000000..b07a2ffe5 --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java similarity index 58% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java index 8a9ff0adf..d10b6c4e6 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java @@ -1,24 +1,28 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api.model; +package org.openhab.binding.sleepiq.internal.api.dto; + +import org.openhab.binding.sleepiq.internal.api.enums.Side; import com.google.gson.annotations.SerializedName; -public class Sleeper -{ +/** + * 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; @@ -44,379 +48,309 @@ public class Sleeper 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 + private Side side; // 0=left; 1=right - public String getFirstName() - { + public String getFirstName() { return firstName; } - public void setFirstName(String firstName) - { + public void setFirstName(String firstName) { this.firstName = firstName; } - public Sleeper withFirstName(String firstName) - { + public Sleeper withFirstName(String firstName) { setFirstName(firstName); return this; } - public Boolean isActive() - { + public Boolean isActive() { return active; } - public void setActive(Boolean active) - { + public void setActive(Boolean active) { this.active = active; } - public Sleeper withActive(Boolean active) - { + public Sleeper withActive(Boolean active) { setActive(active); return this; } - public Boolean isEmailValidated() - { + public Boolean isEmailValidated() { return emailValidated; } - public void setEmailValidated(Boolean emailValidated) - { + public void setEmailValidated(Boolean emailValidated) { this.emailValidated = emailValidated; } - public Sleeper withEmailValidated(Boolean emailValidated) - { + public Sleeper withEmailValidated(Boolean emailValidated) { setEmailValidated(emailValidated); return this; } - public Boolean isChild() - { + public Boolean isChild() { return child; } - public void setChild(Boolean child) - { + public void setChild(Boolean child) { this.child = child; } - public Sleeper withChild(Boolean child) - { + public Sleeper withChild(Boolean child) { setChild(child); return this; } - public String getBedId() - { + public String getBedId() { return bedId; } - public void setBedId(String bedId) - { + public void setBedId(String bedId) { this.bedId = bedId; } - public Sleeper withBedId(String bedId) - { + public Sleeper withBedId(String bedId) { setBedId(bedId); return this; } - public String getBirthYear() - { + public String getBirthYear() { return birthYear; } - public void setBirthYear(String birthYear) - { + public void setBirthYear(String birthYear) { this.birthYear = birthYear; } - public Sleeper withBirthYear(String birthYear) - { + public Sleeper withBirthYear(String birthYear) { setBirthYear(birthYear); return this; } - public String getZipCode() - { + public String getZipCode() { return zipCode; } - public void setZipCode(String zipCode) - { + public void setZipCode(String zipCode) { this.zipCode = zipCode; } - public Sleeper withZipCode(String zipCode) - { + public Sleeper withZipCode(String zipCode) { setZipCode(zipCode); return this; } - public String getTimezone() - { + public String getTimezone() { return timezone; } - public void setTimezone(String timezone) - { + public void setTimezone(String timezone) { this.timezone = timezone; } - public Sleeper withTimezone(String timezone) - { + public Sleeper withTimezone(String timezone) { setTimezone(timezone); return this; } - public Boolean isMale() - { + public Boolean isMale() { return male; } - public void setMale(Boolean male) - { + public void setMale(Boolean male) { this.male = male; } - public Sleeper withMale(Boolean male) - { + public Sleeper withMale(Boolean male) { setMale(male); return this; } - public Integer getWeight() - { + public Integer getWeight() { return weight; } - public void setWeight(Integer weight) - { + public void setWeight(Integer weight) { this.weight = weight; } - public Sleeper withWeight(Integer weight) - { + public Sleeper withWeight(Integer weight) { setWeight(weight); return this; } - public String getDuration() - { + public String getDuration() { return duration; } - public void setDuration(String duration) - { + public void setDuration(String duration) { this.duration = duration; } - public Sleeper withDuration(String duration) - { + public Sleeper withDuration(String duration) { setDuration(duration); return this; } - public String getSleeperId() - { + public String getSleeperId() { return sleeperId; } - public void setSleeperId(String sleeperId) - { + public void setSleeperId(String sleeperId) { this.sleeperId = sleeperId; } - public Sleeper withSleeperId(String sleeperId) - { + public Sleeper withSleeperId(String sleeperId) { setSleeperId(sleeperId); return this; } - public Integer getHeight() - { + public Integer getHeight() { return height; } - public void setHeight(Integer height) - { + public void setHeight(Integer height) { this.height = height; } - public Sleeper withHeight(Integer height) - { + public Sleeper withHeight(Integer height) { setHeight(height); return this; } - public Long getLicenseVersion() - { + public Long getLicenseVersion() { return licenseVersion; } - public void setLicenseVersion(Long licenseVersion) - { + public void setLicenseVersion(Long licenseVersion) { this.licenseVersion = licenseVersion; } - public Sleeper withLicenseVersion(Long licenseVersion) - { + public Sleeper withLicenseVersion(Long licenseVersion) { setLicenseVersion(licenseVersion); return this; } - public String getUsername() - { + public String getUsername() { return username; } - public void setUsername(String username) - { + public void setUsername(String username) { this.username = username; } - public Sleeper withUsername(String username) - { + public Sleeper withUsername(String username) { setUsername(username); return this; } - public Integer getBirthMonth() - { + public Integer getBirthMonth() { return birthMonth; } - public void setBirthMonth(Integer birthMonth) - { + public void setBirthMonth(Integer birthMonth) { this.birthMonth = birthMonth; } - public Sleeper withBirthMonth(Integer birthMonth) - { + public Sleeper withBirthMonth(Integer birthMonth) { setBirthMonth(birthMonth); return this; } - public Integer getSleepGoal() - { + public Integer getSleepGoal() { return sleepGoal; } - public void setSleepGoal(Integer sleepGoal) - { + public void setSleepGoal(Integer sleepGoal) { this.sleepGoal = sleepGoal; } - public Sleeper withSleepGoal(Integer sleepGoal) - { + public Sleeper withSleepGoal(Integer sleepGoal) { setSleepGoal(sleepGoal); return this; } - public Boolean isAccountOwner() - { + public Boolean isAccountOwner() { return accountOwner; } - public void setAccountOwner(Boolean accountOwner) - { + public void setAccountOwner(Boolean accountOwner) { this.accountOwner = accountOwner; } - public Sleeper withAccountOwner(Boolean accountOwner) - { + public Sleeper withAccountOwner(Boolean accountOwner) { setAccountOwner(accountOwner); return this; } - public String getAccountId() - { + public String getAccountId() { return accountId; } - public void setAccountId(String accountId) - { + public void setAccountId(String accountId) { this.accountId = accountId; } - public Sleeper withAccountId(String accountId) - { + public Sleeper withAccountId(String accountId) { setAccountId(accountId); return this; } - public String getEmail() - { + public String getEmail() { return email; } - public void setEmail(String email) - { + public void setEmail(String email) { this.email = email; } - public Sleeper withEmail(String email) - { + public Sleeper withEmail(String email) { setEmail(email); return this; } - public String getAvatar() - { + public String getAvatar() { return avatar; } - public void setAvatar(String avatar) - { + public void setAvatar(String avatar) { this.avatar = avatar; } - public Sleeper withAvatar(String avatar) - { + public Sleeper withAvatar(String avatar) { setAvatar(avatar); return this; } - public String getLastLogin() - { + public String getLastLogin() { return lastLogin; } - public void setLastLogin(String lastLogin) - { + public void setLastLogin(String lastLogin) { this.lastLogin = lastLogin; } - public Sleeper withLastLogin(String lastLogin) - { + public Sleeper withLastLogin(String lastLogin) { setLastLogin(lastLogin); return this; } - public Integer getSide() - { + public Side getSide() { return side; } - public void setSide(Integer side) - { + public void setSide(Side side) { this.side = side; } - public Sleeper withSide(Integer side) - { + public Sleeper withSide(Side side) { setSide(side); return this; } @Override - public int hashCode() - { + public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode()); @@ -424,38 +358,29 @@ public class Sleeper } @Override - public boolean equals(Object obj) - { - if (this == obj) - { + public boolean equals(Object obj) { + if (this == obj) { return true; } - if (obj == null) - { + if (obj == null) { return false; } - if (!(obj instanceof Sleeper)) - { + if (!(obj instanceof Sleeper)) { return false; } - Sleeper other = (Sleeper)obj; - if (sleeperId == null) - { - if (other.sleeperId != null) - { + Sleeper other = (Sleeper) obj; + if (sleeperId == null) { + if (other.sleeperId != null) { return false; } - } - else if (!sleeperId.equals(other.sleeperId)) - { + } else if (!sleeperId.equals(other.sleeperId)) { return false; } return true; } @Override - public String toString() - { + public String toString() { StringBuilder builder = new StringBuilder(); builder.append("Sleeper [firstName="); builder.append(firstName); 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 000000000..d482d4712 --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java similarity index 83% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java index c6c870486..3b83451cf 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java +++ b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java @@ -1,19 +1,16 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ -package org.openhab.binding.sleepiq.api.model; +package org.openhab.binding.sleepiq.internal.api.dto; import java.time.Duration; import java.util.Objects; @@ -21,6 +18,11 @@ 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); 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 000000000..51763626b --- /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 000000000..a73f0f696 --- /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 000000000..c806e3ec6 --- /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 000000000..64e99adb2 --- /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 000000000..587ee3085 --- /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 000000000..811618358 --- /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 000000000..655a3d5c4 --- /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 000000000..5019bbf94 --- /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/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java similarity index 52% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java rename to bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java index dcbde82e6..2503eb964 100644 --- 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/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java @@ -1,29 +1,24 @@ -/* - * Copyright (C) 2016 Gson Type Adapter Authors. +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ - -/* - * 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; +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; @@ -32,8 +27,9 @@ import com.google.gson.stream.JsonWriter; /** * Abstract type adapter for jsr310 date-time types. * - * @author Christophe Bornet + * @author Christophe Bornet - Initial contribution */ +@NonNullByDefault abstract class TemporalTypeAdapter extends TypeAdapter { Function parseFunction; @@ -44,7 +40,7 @@ abstract class TemporalTypeAdapter extends TypeAdapter { } @Override - public void write(JsonWriter out, T value) throws IOException { + public void write(JsonWriter out, @Nullable T value) throws IOException { if (value == null) { out.nullValue(); } else { @@ -53,7 +49,7 @@ abstract class TemporalTypeAdapter extends TypeAdapter { } @Override - public T read(JsonReader in) throws IOException { + public @Nullable T read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; 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 000000000..6377feca6 --- /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 000000000..bb3e64b75 --- /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 3d8fcd30d..96e09ea31 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 b9b14a7ab..e60525e22 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; + } + + 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); } - - 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; - } - - 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); } - 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 7ecc33655..aa9c3b073 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 052553692..30f316084 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 HttpClient httpClient; + private final List bedStatusListeners = new CopyOnWriteArrayList<>(); - private ExpiringCache statusCache; + private @Nullable ScheduledFuture statusPollingJob; + private @Nullable ScheduledFuture sleeperPollingJob; - private ScheduledFuture pollingJob; + private @Nullable SleepIQ cloud; - private SleepIQ cloud; + private @Nullable List sleepers; - private ClientBuilder clientBuilder; - - 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,61 +165,103 @@ 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 - } - - @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()); - } - - if (password.isEmpty()) { - configStatusMessages.add(ConfigStatusMessage.Builder.error(PASSWORD) - .withMessageKeySuffix(SleepIQConfigStatusMessage.PASSWORD_MISSING).withArguments(PASSWORD).build()); - } - - return configStatusMessages; - } - /** * Get a list of all beds registered to the cloud service account. * - * @return the list of beds (never null) + * @return the list of beds or null if unable to get list */ - public List getBeds() { - return cloud.getBeds(); + public @Nullable List getBeds() { + try { + return cloud.getBeds(); + } catch (SleepIQException e) { + logger.debug("CloudHandler: Exception getting list of beds", e); + return null; + } } /** - * Get the {@link Bed} corresponding to the given identifier. + * 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 Bed getBed(final String bedId) { - for (Bed bed : getBeds()) { - if (bedId.equals(bed.getBedId())) { - return bed; + public @Nullable Bed getBed(final @Nullable String bedId) { + logger.debug("CloudHandler: Get bed object for bedId={}", bedId); + if (bedId == null) { + return null; + } + List beds = getBeds(); + if (beds != null) { + for (Bed bed : beds) { + if (bedId.equals(bed.getBedId())) { + return bed; + } } } - return null; } + /** + * Get the sleeper associated with the bedId and side + * + * @param bedId the bed identifier + * @param side the side of the bed + * @return the sleeper or null if sleeper not found + */ + 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; + } + + /** + * Set the sleep number of the specified chamber + * + * @param bedId the bed identifier + * @param sleepNumber the sleep number multiple of 5 between 5 and 100 + * @param side the chamber to set + */ + 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); + } + } + + /** + * 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); + } + } + /** * Update the given properties with attributes of the given bed. If no properties are given, a new map will be * created. @@ -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 00a3c0046..b20b6884f 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())); - } - - @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); - } + 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; } - - bedId = null; } @Override - public void onBedStateChanged(final SleepIQ cloud, final BedStatus status) { - if (!status.getBedId().equals(bedId)) { + 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()); + + 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 @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 - - if (command == RefreshType.REFRESH) { - SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) getBridge().getHandler(); - cloudHandler.refreshBedStatus(); + 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); } } + + 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 ebef3f07c..2c91eac63 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/3rdparty/test/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 similarity index 63% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java index 796bd5aeb..8c510540d 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -19,20 +16,23 @@ import static org.junit.jupiter.api.Assertions.*; import java.io.FileReader; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { 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/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java similarity index 62% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java index 331675ba8..83bbf8132 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -19,20 +16,23 @@ import static org.junit.jupiter.api.Assertions.*; import java.io.FileReader; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { 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/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java similarity index 77% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java index 387335101..5bf26e0b7 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -21,20 +18,22 @@ import java.io.FileReader; import java.time.ZoneId; import java.time.ZonedDateTime; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { 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/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java similarity index 58% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java index 5a1f6c407..147613a59 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -21,20 +18,23 @@ import java.io.FileReader; import java.util.Arrays; import java.util.List; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { 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 000000000..6dd01daeb --- /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 000000000..438c05e01 --- /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/3rdparty/test/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 similarity index 76% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java index 8b184b6c3..28cbabfbf 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -19,20 +16,23 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.FileReader; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { @@ -40,7 +40,7 @@ public class SleeperTest extends AbstractTest { .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) + .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)); } @@ -71,7 +71,7 @@ public class SleeperTest extends AbstractTest { 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(Side.RIGHT, sleeper.getSide()); assertEquals("-1111111111111111111", sleeper.getSleeperId()); assertEquals(Integer.valueOf(450), sleeper.getSleepGoal()); assertEquals("US/Pacific", sleeper.getTimezone()); 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/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java similarity index 60% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java index 118a24a4c..6c866222a 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -21,20 +18,23 @@ import java.io.FileReader; import java.util.Arrays; import java.util.List; -import org.junit.jupiter.api.BeforeAll; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.Test; -import org.openhab.binding.sleepiq.api.impl.GsonGenerator; 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; - - @BeforeAll - public static void setUpBeforeClass() { - gson = GsonGenerator.create(true); - } + private static Gson gson = GsonGenerator.create(true); @Test public void testSerializeAllFields() throws Exception { 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/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java similarity index 78% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java index 3e5d3d14b..50f15d3ee 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.model; @@ -19,8 +16,16 @@ 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() { 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/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java similarity index 62% rename from bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java rename to bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java index 955f7e2ef..d3b541a9e 100644 --- a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/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 @@ -1,17 +1,14 @@ -/* - * Copyright 2017 Gregory Moyer +/** + * Copyright (c) 2010-2023 Contributors to the openHAB project * - * 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 + * See the NOTICE file(s) distributed with this work for additional + * information. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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 * - * 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. + * SPDX-License-Identifier: EPL-2.0 */ package org.openhab.binding.sleepiq.api.test; @@ -24,6 +21,14 @@ 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/"; @@ -31,6 +36,7 @@ public abstract class AbstractTest { return getTestDataPath(name).toFile(); } + @SuppressWarnings("null") protected Path getTestDataPath(String name) { String packageName = this.getClass().getPackage().getName();