]> git.basschouten.com Git - openhab-addons.git/commitdiff
[sleepiq] Rework cloud API and other enhancements (#14180)
authorMark Hilbush <mark@hilbush.com>
Sat, 18 Feb 2023 15:26:57 +0000 (10:26 -0500)
committerGitHub <noreply@github.com>
Sat, 18 Feb 2023 15:26:57 +0000 (16:26 +0100)
Signed-off-by: Mark Hilbush <mark@hilbush.com>
110 files changed:
CODEOWNERS
bundles/org.openhab.binding.sleepiq/README.md
bundles/org.openhab.binding.sleepiq/pom.xml
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/BedNotFoundException.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQ.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/SleepIQException.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/UnauthorizedException.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/filter/LoggingFilter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/AbstractClient.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/Endpoints.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/GsonGenerator.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/SleepIQImpl.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DateTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/DurationTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/InstantTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/JSR310TypeAdapters.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalDateTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/LocalTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/MonthDayTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetDateTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/OffsetTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/PeriodTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearMonthTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/YearTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedsResponse.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Error.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Failure.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/FamilyStatus.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/PauseMode.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/PauseModeTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java [deleted file]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQBindingConstants.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQConfigStatusMessage.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/SleepIQHandlerFactory.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/BedNotFoundException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/CommunicationException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/ResponseFormatException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQ.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/SleepIQException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/UnauthorizedException.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedsResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Error.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Failure.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/FamilyStatusResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeRequest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/PauseModeResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataDay.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepDataSession.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepNumberRequest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/SleepDataInterval.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/Endpoints.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/GsonGenerator.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/SleepIQImpl.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/DateTimeTypeAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SideTypeAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/SleepNumberRequestAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/ZonedDateTimeTypeAdapter.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/config/SleepIQBedConfiguration.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/discovery/SleepIQBedDiscoveryService.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/BedStatusListener.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQCloudHandler.java
bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/handler/SleepIQDualBedHandler.java
bundles/org.openhab.binding.sleepiq/src/main/resources/OH-INF/thing/thing-types.xml
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/PauseModeTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java [new file with mode: 0644]
bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java [new file with mode: 0644]

index 0a9c9c64bae39d91734e7409d93d784cbff96e5e..34ff5b5d4b6f437be7768119bff55f3bf1a4bc96 100644 (file)
 /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
index 4e47a9f47a140882ec2f4981bc4e59c1b77a9c87..d56c2a618abdd7cdc5fe1f45e23757efb6c9217d 100644 (file)
@@ -31,13 +31,11 @@ The binding requires no special configuration.
 The bridge requires a username and a password.
 Optionally, you can also specify a polling interval.
 
-To enable verbose logging of HTTP requests and responses regarding the cloud service, enable DEBUG level logging on ```SleepIQCloudHandler```.
-
 | Configuration Parameter | Type    | Description                                            | Default |
 |-------------------------|---------|--------------------------------------------------------|---------|
 | username                | text    | Username of a registered SleepIQ account owner         |         |
 | password                | text    | Password of a registered SleepIQ account owner         |         |
-| pollingInterval         | integer | Seconds between fetching values from the cloud service | 60      |
+| pollingInterval         | integer | Seconds between fetching values from the cloud service | 120     |
 
 ### Dual-Chamber Bed (Thing ID: "dualBed")
 
@@ -50,7 +48,7 @@ Each bed requires a bed ID as defined by the SleepIQ service.
 ### Sample Thing Configuration
 
 ```java
-Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", pollingInterval=60, logging=false ]
+Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", pollingInterval=120 ]
 {
     Thing dualBed master [ bedId="-9999999999999999999" ]
     Thing dualBed guest [ bedId="-8888888888888888888" ]
@@ -68,33 +66,65 @@ Bridge sleepiq:cloud:1 [ username="mail@example.com", password="password", polli
 
 ### Chamber Channel Group
 
-All channels within this group are read-only.
-
-| Channel ID           | Item Type | Description                                                                                                         |
-|----------------------|-----------|---------------------------------------------------------------------------------------------------------------------|
-| inBed                | Switch    | The presence of a person or object on the chamber                                                                   |
-| sleepNumber          | Number    | The Sleep Number setting of the chamber                                                                             |
-| pressure             | Number    | The current pressure inside the chamber                                                                             |
-| lastLink             | String    | The amount of time that has passed since a connection was made from the chamber to the cloud service (D d HH:MM:SS) |
-| alertId              | Number    | Identifier for an alert condition with the chamber                                                                  |
-| alertDetailedMessage | String    | A detailed message describing an alert condition with the chamber                                                   |
+All channels within this group are read-only, except for the sleepNumber and privacyMode channels.
+
+| Channel ID                        | Item Type      | Description  |
+|-----------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------|
+| inBed                             | Switch         | The presence of a person or object on the chamber  |
+| sleepNumber                       | Number         | The Sleep Number setting of the chamber. Set the sleep number of the chamber by sending a command to the sleepNumber channel with a value between 5 and 100. The value must be a multiple of 5  |
+
+| sleepGoalMinutes                  | Number:Time    | The person's sleep goal in minutes |
+| pressure                          | Number         | The current pressure inside the chamber |
+| privacyMode                       | Switch         | Enable or disable privacy mode |
+| lastLink                          | String         | The amount of time that has passed since a connection was made from the chamber to the cloud service (D d HH:MM:SS) |
+| alertId                           | Number         | Identifier for an alert condition with the chamber |
+| alertDetailedMessage              | String         | A detailed message describing an alert condition with the chamber |
+| todaySleepIQ                      | Number         | The Sleep IQ score for the current day |
+| todayAverageHeartRate             | Number         | The average heart rate for the current day |
+| todayAverageRespirationRate       | Number         | The average respiration rate for the current day |
+| todayMessage                      | String         | A description of the sleep quality for the current day |
+| todaySleepDurationSeconds         | Number:Time    | The duration of sleep for the current day |
+| monthlySleepIQ                    | Number         | The average Sleep IQ score for the current month |
+| monthlyAverageHeartRate           | Number         | The average heart rate for the current month |
+| monthlyAverageRespirationRate     | Number         | The average respiration rate for the current month |
 
 ## Items
 
 Here is a sample item configuration:
 
 ```java
-Switch      MasterBedroom_SleepIQ_InBed_Alice          "In Bed [%s]"        { channel="sleepiq:dualBed:1:master:left#inBed" }
-Number      MasterBedroom_SleepIQ_SleepNumber_Alice    "Sleep Number [%s]"  { channel="sleepiq:dualBed:1:master:left#sleepNumber" }
-Number      MasterBedroom_SleepIQ_Pressure_Alice       "Pressure [%s]"      { channel="sleepiq:dualBed:1:master:left#pressure" }
-String      MasterBedroom_SleepIQ_LastLink_Alice       "Last Update [%s]"   { channel="sleepiq:dualBed:1:master:left#lastLink" }
-Number      MasterBedroom_SleepIQ_AlertId_Alice        "Alert ID [%s]"      { channel="sleepiq:dualBed:1:master:left#alertId" }
-String      MasterBedroom_SleepIQ_AlertMessage_Alice   "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:left#alertDetailedMessage" }
-
-Switch      MasterBedroom_SleepIQ_InBed_Bob            "In Bed [%s]"        { channel="sleepiq:dualBed:1:master:right#inBed" }
-Number      MasterBedroom_SleepIQ_SleepNumber_Bob      "Sleep Number [%s]"  { channel="sleepiq:dualBed:1:master:right#sleepNumber" }
-Number      MasterBedroom_SleepIQ_Pressure_Bob         "Pressure [%s]"      { channel="sleepiq:dualBed:1:master:right#pressure" }
-String      MasterBedroom_SleepIQ_LastLink_Bob         "Last Update [%s]"   { channel="sleepiq:dualBed:1:master:right#lastLink" }
-Number      MasterBedroom_SleepIQ_AlertId_Bob          "Alert ID [%s]"      { channel="sleepiq:dualBed:1:master:right#alertId" }
-String      MasterBedroom_SleepIQ_AlertMessage_Bob     "Alert Message [%s]" { channel="sleepiq:dualBed:1:master:right#alertDetailedMessage" }
+Switch      MasterBR_SleepIQ_InBed_Alice             "In Bed [%s]"                     { channel="sleepiq:dualBed:1:master:left#inBed" }
+Number      MasterBR_SleepIQ_SleepNumber_Alice       "Sleep Number [%s]"               { channel="sleepiq:dualBed:1:master:left#sleepNumber" }
+Number:Time MasterBR_SleepIQ_SleepGoal_Alice         "Sleep Goal [%d min]"             { channel="sleepiq:dualBed:1:master:left#sleepGoalMinutes"
+Number      MasterBR_SleepIQ_Pressure_Alice          "Pressure [%s]"                   { channel="sleepiq:dualBed:1:master:left#pressure" }
+Switch      MasterBR_SleepIQ_PrivacyMode_Alice       "Privacy Mode [%s]"               { channel="sleepiq:dualBed:1:master:left#privacyMode" }
+String      MasterBR_SleepIQ_LastLink_Alice          "Last Update [%s]"                { channel="sleepiq:dualBed:1:master:left#lastLink" }
+Number      MasterBR_SleepIQ_AlertId_Alice           "Alert ID [%s]"                   { channel="sleepiq:dualBed:1:master:left#alertId" }
+String      MasterBR_SleepIQ_AlertMessage_Alice      "Alert Message [%s]"              { channel="sleepiq:dualBed:1:master:left#alertDetailedMessage" }
+Number      MasterBR_SleepIQ_DailySleepIQ_Alice      "Daily Sleep IQ [%.0f]"           { channel="sleepiq:dualBed:1:master:left#todaySleepIQ" }
+Number      MasterBR_SleepIQ_DailyHeartRate_Alice    "Daily Heart Rate [%.0f]"         { channel="sleepiq:dualBed:1:master:left#todayAverageHeartRate" }
+Number      MasterBR_SleepIQ_DailyRespRate_Alice     "Daily Respiration Rate [%.0f]"   { channel="sleepiq:dualBed:1:master:left#todayAverageRespirationRate"}
+String      MasterBR_SleepIQ_DailyMessage_Alice      "Daily Message [%s]"              { channel="sleepiq:dualBed:1:master:left#todayMessage"}
+Number      MasterBR_SleepIQ_DailyDuration_Alice     "Daily Sleep Duration [%.0f]"     { channel="sleepiq:dualBed:1:master:left#todaySleepDurationSeconds"}
+Number:Time MasterBR_SleepIQ_MonthlySleepIQ_Alice    "Monthly Sleep IQ [%d s]"         { channel="sleepiq:dualBed:1:master:left#monthlySleepIQ"}
+Number      MasterBR_SleepIQ_MonthlyHeartRate_Alice  "Monthly Heart Rate [%.0f]"       { channel="sleepiq:dualBed:1:master:left#monthlyAverageHeartRate"}
+Number      MasterBR_SleepIQ_MonthlyRespRate_Alice   "Monthly Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:left#monthlyAverageRespirationRate"}
+
+
+Switch      MasterBR_SleepIQ_InBed_Bob               "In Bed [%s]"                     { channel="sleepiq:dualBed:1:master:right#inBed" }
+Number      MasterBR_SleepIQ_SleepNumber_Bob         "Sleep Number [%s]"               { channel="sleepiq:dualBed:1:master:right#sleepNumber" }
+Number      MasterBR_SleepIQ_SleepGoal_Alice         "Sleep Goal [%d min]"             { channel="sleepiq:dualBed:1:master:left#sleepGoalMinutes"
+Number:Time MasterBR_SleepIQ_Pressure_Bob            "Pressure [%s]"                   { channel="sleepiq:dualBed:1:master:right#pressure" }
+Switch      MasterBR_SleepIQ_PrivacyMode_Bob         "Privacy Mode [%s]"               { channel="sleepiq:dualBed:1:master:right#privacyMode" }
+String      MasterBR_SleepIQ_LastLink_Bob            "Last Update [%s]"                { channel="sleepiq:dualBed:1:master:right#lastLink" }
+Number      MasterBR_SleepIQ_AlertId_Bob             "Alert ID [%s]"                   { channel="sleepiq:dualBed:1:master:right#alertId" }
+String      MasterBR_SleepIQ_AlertMessage_Bob        "Alert Message [%s]"              { channel="sleepiq:dualBed:1:master:right#alertDetailedMessage" }
+Number      MasterBR_SleepIQ_DailySleepIQ_Bob        "Daily Sleep IQ [%.0f]"           { channel="sleepiq:dualBed:1:master:right#todaySleepIQ" }
+Number      MasterBR_SleepIQ_DailyHeartRate_Bob      "Daily Heart Rate [%.0f]"         { channel="sleepiq:dualBed:1:master:right#todayAverageHeartRate" }
+Number      MasterBR_SleepIQ_DailyRespRate_Bob       "Daily Respiration Rate [%.0f]"   { channel="sleepiq:dualBed:1:master:right#todayAverageRespirationRate"}
+String      MasterBR_SleepIQ_DailyMessage_Bob        "Daily Message [%s]"              { channel="sleepiq:dualBed:1:master:right#todayMessage"}
+Number:Time MasterBR_SleepIQ_DailyDuration_Bob       "Daily Sleep Duration [%d s]"     { channel="sleepiq:dualBed:1:master:right#todaySleepDurationSeconds"}
+Number      MasterBR_SleepIQ_MonthlySleepIQ_Bob      "Monthly Sleep IQ [%.0f]"         { channel="sleepiq:dualBed:1:master:right#monthlySleepIQ"}
+Number      MasterBR_SleepIQ_MonthlyHeartRate_Bob    "Monthly Heart Rate [%.0f]"       { channel="sleepiq:dualBed:1:master:right#monthlyAverageHeartRate"}
+Number      MasterBR_SleepIQ_MonthlyRespRate_Bob     "Monthly Respiration Rate [%.0f]" { channel="sleepiq:dualBed:1:master:right#monthlyAverageRespirationRate"}
 ```
index 754bf4078aba8b962642206de1d28c946f6bf071..842ada6428b6fc89a4f892e941893050e53702e9 100644 (file)
 
   <name>openHAB Add-ons :: Bundles :: SleepIQ Binding</name>
 
-  <properties>
-    <dep.noembedding>provider-gson</dep.noembedding>
-  </properties>
-
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <version>4.12</version>
-      <scope>test</scope>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>add-source</goal>
-            </goals>
-            <phase>generate-sources</phase>
-            <configuration>
-              <sources>
-                <source>src/3rdparty/java</source>
-              </sources>
-            </configuration>
-          </execution>
-          <execution>
-            <id>add-test-source</id>
-            <phase>generate-sources</phase>
-            <goals>
-              <goal>add-test-source</goal>
-            </goals>
-            <configuration>
-              <sources>
-                <source>src/3rdparty/test</source>
-              </sources>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-
 </project>
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 (file)
index 3eba856..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api;
-
-import org.openhab.binding.sleepiq.api.model.Failure;
-
-public class BedNotFoundException extends SleepIQException
-{
-    private static final long serialVersionUID = 1L;
-
-    public BedNotFoundException(Failure failure)
-    {
-        super(failure);
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/Configuration.java
deleted file mode 100644 (file)
index cb0fd28..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api;
-
-import java.net.URI;
-import java.util.logging.Level;
-
-/**
- * This class represents configuration parameters for using {@link SleepIQ}.
- *
- * @author Gregory Moyer
- */
-public class Configuration
-{
-    private String username;
-    private String password;
-
-    private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com/rest");
-
-    private boolean logging = false;
-
-    /**
-     * Get the username on the account.
-     *
-     * @return the username
-     */
-    public String getUsername()
-    {
-        return username;
-    }
-
-    /**
-     * Set the username on the account. This should be the username used to
-     * register with SleepIQ.
-     *
-     * @param username
-     *            the value to set
-     */
-    public void setUsername(String username)
-    {
-        this.username = username;
-    }
-
-    /**
-     * Set the username on the account. This should be the username used to
-     * register with SleepIQ.
-     *
-     * @param username
-     *            the value to set
-     * @return this configuration instance
-     */
-    public Configuration withUsername(String username)
-    {
-        setUsername(username);
-        return this;
-    }
-
-    /**
-     * Get the password on the account.
-     *
-     * @return the password
-     */
-    public String getPassword()
-    {
-        return password;
-    }
-
-    /**
-     * Set the password on the account. This should be the password used to
-     * register with SleepIQ.
-     *
-     * @param password
-     *            the value to set
-     */
-    public void setPassword(String password)
-    {
-        this.password = password;
-    }
-
-    /**
-     * Set the password on the account. This should be the password used to
-     * register with SleepIQ.
-     *
-     * @param password
-     *            the value to set
-     * @return this configuration instance
-     */
-    public Configuration withPassword(String password)
-    {
-        setPassword(password);
-        return this;
-    }
-
-    /**
-     * Get the base URI of the SleepIQ cloud service.
-     *
-     * @return the base URI
-     */
-    public URI getBaseUri()
-    {
-        return baseUri;
-    }
-
-    /**
-     * Set the base URI of the SleepIQ cloud service. It is unlikely that this
-     * will need to be changed from its default value.
-     *
-     * @param baseUri
-     *            the value to set
-     */
-    public void setBaseUri(URI baseUri)
-    {
-        this.baseUri = baseUri;
-    }
-
-    /**
-     * Set the base URI of the SleepIQ cloud service. It is unlikely that this
-     * will need to be changed from its default value.
-     *
-     * @param baseUri
-     *            the value to set
-     * @return this configuration instance
-     */
-    public Configuration withBaseUri(URI baseUri)
-    {
-        setBaseUri(baseUri);
-        return this;
-    }
-
-    /**
-     * Get the logging flag.
-     *
-     * @return the logging flag
-     */
-    public boolean isLogging()
-    {
-        return logging;
-    }
-
-    /**
-     * Set the logging flag. When this is set to <code>true</code>, all requests
-     * and responses will be logged at the {@link Level#INFO} level. <b>This
-     * includes usernames and passwords!</b>
-     *
-     * @param logging
-     *            the value to set
-     */
-    public void setLogging(boolean logging)
-    {
-        this.logging = logging;
-    }
-
-    /**
-     * Set the logging flag. When this is set to <code>true</code>, all requests
-     * and responses will be logged at the {@link Level#INFO} level. <b>This
-     * includes usernames and passwords!</b>
-     *
-     * @param logging
-     *            the value to set
-     * @return this configuration instance
-     */
-    public Configuration withLogging(boolean logging)
-    {
-        setLogging(logging);
-        return this;
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/LoginException.java
deleted file mode 100644 (file)
index 6480ae4..0000000
+++ /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 (file)
index 5785b24..0000000
+++ /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<Bed> 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<Sleeper> 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 (file)
index 55935c1..0000000
+++ /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 (file)
index 5a80900..0000000
+++ /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 (file)
index 5ce38e5..0000000
+++ /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.
- * <p/>
- * 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<Map.Entry<String, List<String>>> COMPARATOR = new Comparator<Map.Entry<String, List<String>>>() {
-
-        @Override
-        public int compare(final Map.Entry<String, List<String>> o1, final Map.Entry<String, List<String>> 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<String, String> headers) {
-        for (final Map.Entry<String, List<String>> 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<Map.Entry<String, List<String>>> getSortedHeaders(final Set<Map.Entry<String, List<String>>> headers) {
-        final TreeSet<Map.Entry<String, List<String>>> sortedHeaders = new TreeSet<Map.Entry<String, List<String>>>(
-                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.
-     * <p>
-     * 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 (file)
index 7f5e3cb..0000000
+++ /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 (file)
index a1e8f34..0000000
+++ /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 (file)
index fb67e9b..0000000
+++ /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 (file)
index df1b85a..0000000
+++ /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<Object> 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<Bed> getBeds() {
-        return getSessionResponse(this::getBedsResponse).readEntity(BedsResponse.class).getBeds();
-    }
-
-    protected Response getBedsResponse(Map<String, Object> 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<Sleeper> getSleepers() {
-        return getSessionResponse(this::getSleepersResponse).readEntity(SleepersResponse.class).getSleepers();
-    }
-
-    protected Response getSleepersResponse(Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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<Object> 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<String, Object> 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 (file)
index e148736..0000000
+++ /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<T> extends TemporalTypeAdapter<T> {
-
-  DateTimeTypeAdapter(Function<String, T> 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 (file)
index 7651064..0000000
+++ /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<Duration> {
-
-  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 (file)
index 5f4b4f4..0000000
+++ /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<Instant> {
-
-  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 (file)
index 4de838c..0000000
+++ /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 (file)
index 10360c9..0000000
+++ /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<LocalDateTime> {
-
-  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 (file)
index 3ac2762..0000000
+++ /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<LocalDate> {
-
-  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 (file)
index 597301e..0000000
+++ /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<LocalTime> {
-
-    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 (file)
index 5a1ab7f..0000000
+++ /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<MonthDay> {
-
-  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 (file)
index ded37fd..0000000
+++ /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<OffsetDateTime> {
-
-    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 (file)
index e6f49e7..0000000
+++ /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<OffsetTime> {
-
-    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 (file)
index 74ade18..0000000
+++ /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<Period> {
-
-  public PeriodTypeAdapter() {
-    super(Period::parse);
-  }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TemporalTypeAdapter.java
deleted file mode 100644 (file)
index dcbde82..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2016 Gson Type Adapter Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Imported from https://github.com/google-gson/typeadapters/tree/master/jsr310/src
- * and repackaged to avoid the default package.
- */
-package org.openhab.binding.sleepiq.api.impl.typeadapters;
-
-import java.io.IOException;
-import java.util.Objects;
-import java.util.function.Function;
-
-import com.google.gson.TypeAdapter;
-import com.google.gson.stream.JsonReader;
-import com.google.gson.stream.JsonToken;
-import com.google.gson.stream.JsonWriter;
-
-/**
- * Abstract type adapter for jsr310 date-time types.
- *
- * @author Christophe Bornet
- */
-abstract class TemporalTypeAdapter<T> extends TypeAdapter<T> {
-
-    Function<String, T> parseFunction;
-
-    TemporalTypeAdapter(Function<String, T> parseFunction) {
-        Objects.requireNonNull(parseFunction);
-        this.parseFunction = parseFunction;
-    }
-
-    @Override
-    public void write(JsonWriter out, T value) throws IOException {
-        if (value == null) {
-            out.nullValue();
-        } else {
-            out.value(value.toString());
-        }
-    }
-
-    @Override
-    public T read(JsonReader in) throws IOException {
-        if (in.peek() == JsonToken.NULL) {
-            in.nextNull();
-            return null;
-        }
-        String temporalString = preProcess(in.nextString());
-        return parseFunction.apply(temporalString);
-    }
-
-    public String preProcess(String in) {
-        return in;
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/impl/typeadapters/TimeSinceTypeAdapter.java
deleted file mode 100644 (file)
index 3504e1b..0000000
+++ /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<TimeSince>
-{
-    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 (file)
index 5fe0a6e..0000000
+++ /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<YearMonth> {
-
-  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 (file)
index 37f2153..0000000
+++ /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<Year> {
-
-  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 (file)
index 0d31cad..0000000
+++ /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<ZonedDateTime> {
-
-    public ZonedDateTimeTypeAdapter() {
-        super(ZonedDateTime::parse);
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Bed.java
deleted file mode 100644 (file)
index 6bfa86d..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import java.time.ZonedDateTime;
-
-import com.google.gson.annotations.SerializedName;
-
-public class Bed
-{
-    private ZonedDateTime registrationDate;
-    private String sleeperRightId;
-    private String base;
-    private Long returnRequestStatus;
-    private String size;
-    private String name;
-    private String serial;
-    @SerializedName("isKidsBed")
-    private Boolean kidsBed;
-    private Boolean dualSleep;
-    private String bedId;
-    private Long status;
-    private String sleeperLeftId;
-    private String version;
-    private String accountId;
-    private String timezone;
-    private String model;
-    private ZonedDateTime purchaseDate;
-    private String macAddress;
-    private String sku;
-    @SerializedName("zipcode")
-    private String zipCode;
-    private String reference;
-
-    public ZonedDateTime getRegistrationDate()
-    {
-        return registrationDate;
-    }
-
-    public void setRegistrationDate(ZonedDateTime registrationDate)
-    {
-        this.registrationDate = registrationDate;
-    }
-
-    public Bed withRegistrationDate(ZonedDateTime registrationDate)
-    {
-        setRegistrationDate(registrationDate);
-        return this;
-    }
-
-    public String getSleeperRightId()
-    {
-        return sleeperRightId;
-    }
-
-    public void setSleeperRightId(String sleeperRightId)
-    {
-        this.sleeperRightId = sleeperRightId;
-    }
-
-    public Bed withSleeperRightId(String sleeperRightId)
-    {
-        setSleeperRightId(sleeperRightId);
-        return this;
-    }
-
-    public String getBase()
-    {
-        return base;
-    }
-
-    public void setBase(String base)
-    {
-        this.base = base;
-    }
-
-    public Bed withBase(String base)
-    {
-        setBase(base);
-        return this;
-    }
-
-    public Long getReturnRequestStatus()
-    {
-        return returnRequestStatus;
-    }
-
-    public void setReturnRequestStatus(Long returnRequestStatus)
-    {
-        this.returnRequestStatus = returnRequestStatus;
-    }
-
-    public Bed withReturnRequestStatus(Long returnRequestStatus)
-    {
-        setReturnRequestStatus(returnRequestStatus);
-        return this;
-    }
-
-    public String getSize()
-    {
-        return size;
-    }
-
-    public void setSize(String size)
-    {
-        this.size = size;
-    }
-
-    public Bed withSize(String size)
-    {
-        setSize(size);
-        return this;
-    }
-
-    public String getName()
-    {
-        return name;
-    }
-
-    public void setName(String name)
-    {
-        this.name = name;
-    }
-
-    public Bed withName(String name)
-    {
-        setName(name);
-        return this;
-    }
-
-    public String getSerial()
-    {
-        return serial;
-    }
-
-    public void setSerial(String serial)
-    {
-        this.serial = serial;
-    }
-
-    public Bed withSerial(String serial)
-    {
-        setSerial(serial);
-        return this;
-    }
-
-    public Boolean isKidsBed()
-    {
-        return kidsBed;
-    }
-
-    public void setKidsBed(Boolean kidsBed)
-    {
-        this.kidsBed = kidsBed;
-    }
-
-    public Bed withKidsBed(Boolean kidsBed)
-    {
-        setKidsBed(kidsBed);
-        return this;
-    }
-
-    public Boolean isDualSleep()
-    {
-        return dualSleep;
-    }
-
-    public void setDualSleep(Boolean dualSleep)
-    {
-        this.dualSleep = dualSleep;
-    }
-
-    public Bed withDualSleep(Boolean dualSleep)
-    {
-        setDualSleep(dualSleep);
-        return this;
-    }
-
-    public String getBedId()
-    {
-        return bedId;
-    }
-
-    public void setBedId(String bedId)
-    {
-        this.bedId = bedId;
-    }
-
-    public Bed withBedId(String bedId)
-    {
-        setBedId(bedId);
-        return this;
-    }
-
-    public Long getStatus()
-    {
-        return status;
-    }
-
-    public void setStatus(Long status)
-    {
-        this.status = status;
-    }
-
-    public Bed withStatus(Long status)
-    {
-        setStatus(status);
-        return this;
-    }
-
-    public String getSleeperLeftId()
-    {
-        return sleeperLeftId;
-    }
-
-    public void setSleeperLeftId(String sleeperLeftId)
-    {
-        this.sleeperLeftId = sleeperLeftId;
-    }
-
-    public Bed withSleeperLeftId(String sleeperLeftId)
-    {
-        setSleeperLeftId(sleeperLeftId);
-        return this;
-    }
-
-    public String getVersion()
-    {
-        return version;
-    }
-
-    public void setVersion(String version)
-    {
-        this.version = version;
-    }
-
-    public Bed withVersion(String version)
-    {
-        setVersion(version);
-        return this;
-    }
-
-    public String getAccountId()
-    {
-        return accountId;
-    }
-
-    public void setAccountId(String accountId)
-    {
-        this.accountId = accountId;
-    }
-
-    public Bed withAccountId(String accountId)
-    {
-        setAccountId(accountId);
-        return this;
-    }
-
-    public String getTimezone()
-    {
-        return timezone;
-    }
-
-    public void setTimezone(String timezone)
-    {
-        this.timezone = timezone;
-    }
-
-    public Bed withTimezone(String timezone)
-    {
-        setTimezone(timezone);
-        return this;
-    }
-
-    public String getModel()
-    {
-        return model;
-    }
-
-    public void setModel(String model)
-    {
-        this.model = model;
-    }
-
-    public Bed withModel(String model)
-    {
-        setModel(model);
-        return this;
-    }
-
-    public ZonedDateTime getPurchaseDate()
-    {
-        return purchaseDate;
-    }
-
-    public void setPurchaseDate(ZonedDateTime purchaseDate)
-    {
-        this.purchaseDate = purchaseDate;
-    }
-
-    public Bed withPurchaseDate(ZonedDateTime purchaseDate)
-    {
-        setPurchaseDate(purchaseDate);
-        return this;
-    }
-
-    public String getMacAddress()
-    {
-        return macAddress;
-    }
-
-    public void setMacAddress(String macAddress)
-    {
-        this.macAddress = macAddress;
-    }
-
-    public Bed withMacAddress(String macAddress)
-    {
-        setMacAddress(macAddress);
-        return this;
-    }
-
-    public String getSku()
-    {
-        return sku;
-    }
-
-    public void setSku(String sku)
-    {
-        this.sku = sku;
-    }
-
-    public Bed withSku(String sku)
-    {
-        setSku(sku);
-        return this;
-    }
-
-    public String getZipCode()
-    {
-        return zipCode;
-    }
-
-    public void setZipCode(String zipCode)
-    {
-        this.zipCode = zipCode;
-    }
-
-    public Bed withZipCode(String zipCode)
-    {
-        setZipCode(zipCode);
-        return this;
-    }
-
-    public String getReference()
-    {
-        return reference;
-    }
-
-    public void setReference(String reference)
-    {
-        this.reference = reference;
-    }
-
-    public Bed withReference(String reference)
-    {
-        setReference(reference);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((bedId == null) ? 0 : bedId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof Bed))
-        {
-            return false;
-        }
-        Bed other = (Bed)obj;
-        if (bedId == null)
-        {
-            if (other.bedId != null)
-            {
-                return false;
-            }
-        }
-        else if (!bedId.equals(other.bedId))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("Bed [registrationDate=");
-        builder.append(registrationDate);
-        builder.append(", sleeperRightId=");
-        builder.append(sleeperRightId);
-        builder.append(", base=");
-        builder.append(base);
-        builder.append(", returnRequestStatus=");
-        builder.append(returnRequestStatus);
-        builder.append(", size=");
-        builder.append(size);
-        builder.append(", name=");
-        builder.append(name);
-        builder.append(", serial=");
-        builder.append(serial);
-        builder.append(", kidsBed=");
-        builder.append(kidsBed);
-        builder.append(", dualSleep=");
-        builder.append(dualSleep);
-        builder.append(", bedId=");
-        builder.append(bedId);
-        builder.append(", status=");
-        builder.append(status);
-        builder.append(", sleeperLeftId=");
-        builder.append(sleeperLeftId);
-        builder.append(", version=");
-        builder.append(version);
-        builder.append(", accountId=");
-        builder.append(accountId);
-        builder.append(", timezone=");
-        builder.append(timezone);
-        builder.append(", model=");
-        builder.append(model);
-        builder.append(", purchaseDate=");
-        builder.append(purchaseDate);
-        builder.append(", macAddress=");
-        builder.append(macAddress);
-        builder.append(", sku=");
-        builder.append(sku);
-        builder.append(", zipCode=");
-        builder.append(zipCode);
-        builder.append(", reference=");
-        builder.append(reference);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedSideStatus.java
deleted file mode 100644 (file)
index b7e994b..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import com.google.gson.annotations.SerializedName;
-
-public class BedSideStatus
-{
-    @SerializedName("isInBed")
-    private Boolean inBed;
-    private String alertDetailedMessage;
-    private Integer sleepNumber;
-    private Long alertId;
-    private TimeSince lastLink;
-    private Integer pressure; // appears to be in kPa
-
-    public Boolean isInBed()
-    {
-        return inBed;
-    }
-
-    public void setInBed(Boolean inBed)
-    {
-        this.inBed = inBed;
-    }
-
-    public BedSideStatus withInBed(Boolean inBed)
-    {
-        setInBed(inBed);
-        return this;
-    }
-
-    public String getAlertDetailedMessage()
-    {
-        return alertDetailedMessage;
-    }
-
-    public void setAlertDetailedMessage(String alertDetailedMessage)
-    {
-        this.alertDetailedMessage = alertDetailedMessage;
-    }
-
-    public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage)
-    {
-        setAlertDetailedMessage(alertDetailedMessage);
-        return this;
-    }
-
-    public Integer getSleepNumber()
-    {
-        return sleepNumber;
-    }
-
-    public void setSleepNumber(Integer sleepNumber)
-    {
-        this.sleepNumber = sleepNumber;
-    }
-
-    public BedSideStatus withSleepNumber(Integer sleepNumber)
-    {
-        setSleepNumber(sleepNumber);
-        return this;
-    }
-
-    public Long getAlertId()
-    {
-        return alertId;
-    }
-
-    public void setAlertId(Long alertId)
-    {
-        this.alertId = alertId;
-    }
-
-    public BedSideStatus withAlertId(Long alertId)
-    {
-        setAlertId(alertId);
-        return this;
-    }
-
-    public TimeSince getLastLink()
-    {
-        return lastLink;
-    }
-
-    public void setLastLink(TimeSince lastLink)
-    {
-        this.lastLink = lastLink;
-    }
-
-    public BedSideStatus withLastLink(TimeSince lastLink)
-    {
-        setLastLink(lastLink);
-        return this;
-    }
-
-    public Integer getPressure()
-    {
-        return pressure;
-    }
-
-    public void setPressure(Integer pressure)
-    {
-        this.pressure = pressure;
-    }
-
-    public BedSideStatus withPressure(Integer pressure)
-    {
-        setPressure(pressure);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result
-                 + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode());
-        result = prime * result + ((alertId == null) ? 0 : alertId.hashCode());
-        result = prime * result + ((inBed == null) ? 0 : inBed.hashCode());
-        result = prime * result + ((lastLink == null) ? 0 : lastLink.hashCode());
-        result = prime * result + ((pressure == null) ? 0 : pressure.hashCode());
-        result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof BedSideStatus))
-        {
-            return false;
-        }
-        BedSideStatus other = (BedSideStatus)obj;
-        if (alertDetailedMessage == null)
-        {
-            if (other.alertDetailedMessage != null)
-            {
-                return false;
-            }
-        }
-        else if (!alertDetailedMessage.equals(other.alertDetailedMessage))
-        {
-            return false;
-        }
-        if (alertId == null)
-        {
-            if (other.alertId != null)
-            {
-                return false;
-            }
-        }
-        else if (!alertId.equals(other.alertId))
-        {
-            return false;
-        }
-        if (inBed == null)
-        {
-            if (other.inBed != null)
-            {
-                return false;
-            }
-        }
-        else if (!inBed.equals(other.inBed))
-        {
-            return false;
-        }
-        if (lastLink == null)
-        {
-            if (other.lastLink != null)
-            {
-                return false;
-            }
-        }
-        else if (!lastLink.equals(other.lastLink))
-        {
-            return false;
-        }
-        if (pressure == null)
-        {
-            if (other.pressure != null)
-            {
-                return false;
-            }
-        }
-        else if (!pressure.equals(other.pressure))
-        {
-            return false;
-        }
-        if (sleepNumber == null)
-        {
-            if (other.sleepNumber != null)
-            {
-                return false;
-            }
-        }
-        else if (!sleepNumber.equals(other.sleepNumber))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("BedSideStatus [inBed=");
-        builder.append(inBed);
-        builder.append(", alertDetailedMessage=");
-        builder.append(alertDetailedMessage);
-        builder.append(", sleepNumber=");
-        builder.append(sleepNumber);
-        builder.append(", alertId=");
-        builder.append(alertId);
-        builder.append(", lastLink=");
-        builder.append(lastLink);
-        builder.append(", pressure=");
-        builder.append(pressure);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/BedStatus.java
deleted file mode 100644 (file)
index c07fbd8..0000000
+++ /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 (file)
index 3b3deee..0000000
+++ /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<Bed> beds;
-
-    public List<Bed> getBeds()
-    {
-        return beds;
-    }
-
-    public void setBeds(List<Bed> beds)
-    {
-        this.beds = beds;
-    }
-
-    public BedsResponse withBeds(List<Bed> 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 (file)
index 5593b59..0000000
+++ /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 (file)
index 4ab0481..0000000
+++ /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 (file)
index cddea5a..0000000
+++ /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<BedStatus> beds;
-
-    public List<BedStatus> getBeds()
-    {
-        return beds;
-    }
-
-    public void setBeds(List<BedStatus> beds)
-    {
-        this.beds = beds;
-    }
-
-    public FamilyStatus withBeds(List<BedStatus> beds)
-    {
-        setBeds(beds);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((beds == null) ? 0 : beds.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof FamilyStatus))
-        {
-            return false;
-        }
-        FamilyStatus other = (FamilyStatus)obj;
-        if (beds == null)
-        {
-            if (other.beds != null)
-            {
-                return false;
-            }
-        }
-        else if (!beds.equals(other.beds))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("FamilyStatus [beds=");
-        builder.append(beds);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginInfo.java
deleted file mode 100644 (file)
index 7cc3509..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-public class LoginInfo
-{
-    private String userId;
-    private String key;
-    private Long registrationState;
-    private Long edpLoginStatus;
-    private String edpLoginMessage;
-
-    public String getUserId()
-    {
-        return userId;
-    }
-
-    public void setUserId(String userId)
-    {
-        this.userId = userId;
-    }
-
-    public LoginInfo withUserId(String userId)
-    {
-        setUserId(userId);
-        return this;
-    }
-
-    public String getKey()
-    {
-        return key;
-    }
-
-    public void setKey(String key)
-    {
-        this.key = key;
-    }
-
-    public LoginInfo withKey(String key)
-    {
-        setKey(key);
-        return this;
-    }
-
-    public Long getRegistrationState()
-    {
-        return registrationState;
-    }
-
-    public void setRegistrationState(Long registrationState)
-    {
-        this.registrationState = registrationState;
-    }
-
-    public LoginInfo withRegistrationState(Long registrationState)
-    {
-        setRegistrationState(registrationState);
-        return this;
-    }
-
-    public Long getEdpLoginStatus()
-    {
-        return edpLoginStatus;
-    }
-
-    public void setEdpLoginStatus(Long edpLoginStatus)
-    {
-        this.edpLoginStatus = edpLoginStatus;
-    }
-
-    public LoginInfo withEdpLoginStatus(Long edpLoginStatus)
-    {
-        setEdpLoginStatus(edpLoginStatus);
-        return this;
-    }
-
-    public String getEdpLoginMessage()
-    {
-        return edpLoginMessage;
-    }
-
-    public void setEdpLoginMessage(String edpLoginMessage)
-    {
-        this.edpLoginMessage = edpLoginMessage;
-    }
-
-    public LoginInfo withEdpLoginMessage(String edpLoginMessage)
-    {
-        setEdpLoginMessage(edpLoginMessage);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((key == null) ? 0 : key.hashCode());
-        result = prime * result + (int)(registrationState ^ (registrationState >>> 32));
-        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof LoginInfo))
-        {
-            return false;
-        }
-        LoginInfo other = (LoginInfo)obj;
-        if (key == null)
-        {
-            if (other.key != null)
-            {
-                return false;
-            }
-        }
-        else if (!key.equals(other.key))
-        {
-            return false;
-        }
-        if (!registrationState.equals(other.registrationState))
-        {
-            return false;
-        }
-        if (userId == null)
-        {
-            if (other.userId != null)
-            {
-                return false;
-            }
-        }
-        else if (!userId.equals(other.userId))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("LoginInfo [userId=");
-        builder.append(userId);
-        builder.append(", key=");
-        builder.append(key);
-        builder.append(", registrationState=");
-        builder.append(registrationState);
-        builder.append(", edpLoginStatus=");
-        builder.append(edpLoginStatus);
-        builder.append(", edpLoginMessage=");
-        builder.append(edpLoginMessage);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/LoginRequest.java
deleted file mode 100644 (file)
index 07835f0..0000000
+++ /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 (file)
index 5627886..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-public class PauseMode
-{
-    private String accountId;
-    private String bedId;
-    private String pauseMode;
-
-    public String getAccountId()
-    {
-        return accountId;
-    }
-
-    public void setAccountId(String accountId)
-    {
-        this.accountId = accountId;
-    }
-
-    public PauseMode withAccountId(String accountId)
-    {
-        setAccountId(accountId);
-        return this;
-    }
-
-    public String getBedId()
-    {
-        return bedId;
-    }
-
-    public void setBedId(String bedId)
-    {
-        this.bedId = bedId;
-    }
-
-    public PauseMode withBedId(String bedId)
-    {
-        setBedId(bedId);
-        return this;
-    }
-
-    public String getPauseMode()
-    {
-        return pauseMode;
-    }
-
-    public void setPauseMode(String pauseMode)
-    {
-        this.pauseMode = pauseMode;
-    }
-
-    public PauseMode withPauseMode(String pauseMode)
-    {
-        setPauseMode(pauseMode);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((accountId == null) ? 0 : accountId.hashCode());
-        result = prime * result + ((bedId == null) ? 0 : bedId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof PauseMode))
-        {
-            return false;
-        }
-        PauseMode other = (PauseMode)obj;
-        if (accountId == null)
-        {
-            if (other.accountId != null)
-            {
-                return false;
-            }
-        }
-        else if (!accountId.equals(other.accountId))
-        {
-            return false;
-        }
-        if (bedId == null)
-        {
-            if (other.bedId != null)
-            {
-                return false;
-            }
-        }
-        else if (!bedId.equals(other.bedId))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("PauseMode [accountId=");
-        builder.append(accountId);
-        builder.append(", bedId=");
-        builder.append(bedId);
-        builder.append(", pauseMode=");
-        builder.append(pauseMode);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/Sleeper.java
deleted file mode 100644 (file)
index 8a9ff0a..0000000
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import com.google.gson.annotations.SerializedName;
-
-public class Sleeper
-{
-    private String firstName;
-    private Boolean active;
-    private Boolean emailValidated;
-    @SerializedName("isChild")
-    private Boolean child;
-    private String bedId;
-    private String birthYear;
-    private String zipCode;
-    private String timezone;
-    @SerializedName("isMale")
-    private Boolean male;
-    private Integer weight; // lbs
-    private String duration;
-    private String sleeperId;
-    private Integer height; // inches
-    private Long licenseVersion;
-    private String username;
-    private Integer birthMonth; // 0-based; 12 means not entered?
-    private Integer sleepGoal;
-    @SerializedName("isAccountOwner")
-    private Boolean accountOwner;
-    private String accountId;
-    private String email;
-    private String avatar;
-    private String lastLogin; // should be ZonedDateTime but provider passes string "null" when missing
-    private Integer side; // 0=left; 1=right
-
-    public String getFirstName()
-    {
-        return firstName;
-    }
-
-    public void setFirstName(String firstName)
-    {
-        this.firstName = firstName;
-    }
-
-    public Sleeper withFirstName(String firstName)
-    {
-        setFirstName(firstName);
-        return this;
-    }
-
-    public Boolean isActive()
-    {
-        return active;
-    }
-
-    public void setActive(Boolean active)
-    {
-        this.active = active;
-    }
-
-    public Sleeper withActive(Boolean active)
-    {
-        setActive(active);
-        return this;
-    }
-
-    public Boolean isEmailValidated()
-    {
-        return emailValidated;
-    }
-
-    public void setEmailValidated(Boolean emailValidated)
-    {
-        this.emailValidated = emailValidated;
-    }
-
-    public Sleeper withEmailValidated(Boolean emailValidated)
-    {
-        setEmailValidated(emailValidated);
-        return this;
-    }
-
-    public Boolean isChild()
-    {
-        return child;
-    }
-
-    public void setChild(Boolean child)
-    {
-        this.child = child;
-    }
-
-    public Sleeper withChild(Boolean child)
-    {
-        setChild(child);
-        return this;
-    }
-
-    public String getBedId()
-    {
-        return bedId;
-    }
-
-    public void setBedId(String bedId)
-    {
-        this.bedId = bedId;
-    }
-
-    public Sleeper withBedId(String bedId)
-    {
-        setBedId(bedId);
-        return this;
-    }
-
-    public String getBirthYear()
-    {
-        return birthYear;
-    }
-
-    public void setBirthYear(String birthYear)
-    {
-        this.birthYear = birthYear;
-    }
-
-    public Sleeper withBirthYear(String birthYear)
-    {
-        setBirthYear(birthYear);
-        return this;
-    }
-
-    public String getZipCode()
-    {
-        return zipCode;
-    }
-
-    public void setZipCode(String zipCode)
-    {
-        this.zipCode = zipCode;
-    }
-
-    public Sleeper withZipCode(String zipCode)
-    {
-        setZipCode(zipCode);
-        return this;
-    }
-
-    public String getTimezone()
-    {
-        return timezone;
-    }
-
-    public void setTimezone(String timezone)
-    {
-        this.timezone = timezone;
-    }
-
-    public Sleeper withTimezone(String timezone)
-    {
-        setTimezone(timezone);
-        return this;
-    }
-
-    public Boolean isMale()
-    {
-        return male;
-    }
-
-    public void setMale(Boolean male)
-    {
-        this.male = male;
-    }
-
-    public Sleeper withMale(Boolean male)
-    {
-        setMale(male);
-        return this;
-    }
-
-    public Integer getWeight()
-    {
-        return weight;
-    }
-
-    public void setWeight(Integer weight)
-    {
-        this.weight = weight;
-    }
-
-    public Sleeper withWeight(Integer weight)
-    {
-        setWeight(weight);
-        return this;
-    }
-
-    public String getDuration()
-    {
-        return duration;
-    }
-
-    public void setDuration(String duration)
-    {
-        this.duration = duration;
-    }
-
-    public Sleeper withDuration(String duration)
-    {
-        setDuration(duration);
-        return this;
-    }
-
-    public String getSleeperId()
-    {
-        return sleeperId;
-    }
-
-    public void setSleeperId(String sleeperId)
-    {
-        this.sleeperId = sleeperId;
-    }
-
-    public Sleeper withSleeperId(String sleeperId)
-    {
-        setSleeperId(sleeperId);
-        return this;
-    }
-
-    public Integer getHeight()
-    {
-        return height;
-    }
-
-    public void setHeight(Integer height)
-    {
-        this.height = height;
-    }
-
-    public Sleeper withHeight(Integer height)
-    {
-        setHeight(height);
-        return this;
-    }
-
-    public Long getLicenseVersion()
-    {
-        return licenseVersion;
-    }
-
-    public void setLicenseVersion(Long licenseVersion)
-    {
-        this.licenseVersion = licenseVersion;
-    }
-
-    public Sleeper withLicenseVersion(Long licenseVersion)
-    {
-        setLicenseVersion(licenseVersion);
-        return this;
-    }
-
-    public String getUsername()
-    {
-        return username;
-    }
-
-    public void setUsername(String username)
-    {
-        this.username = username;
-    }
-
-    public Sleeper withUsername(String username)
-    {
-        setUsername(username);
-        return this;
-    }
-
-    public Integer getBirthMonth()
-    {
-        return birthMonth;
-    }
-
-    public void setBirthMonth(Integer birthMonth)
-    {
-        this.birthMonth = birthMonth;
-    }
-
-    public Sleeper withBirthMonth(Integer birthMonth)
-    {
-        setBirthMonth(birthMonth);
-        return this;
-    }
-
-    public Integer getSleepGoal()
-    {
-        return sleepGoal;
-    }
-
-    public void setSleepGoal(Integer sleepGoal)
-    {
-        this.sleepGoal = sleepGoal;
-    }
-
-    public Sleeper withSleepGoal(Integer sleepGoal)
-    {
-        setSleepGoal(sleepGoal);
-        return this;
-    }
-
-    public Boolean isAccountOwner()
-    {
-        return accountOwner;
-    }
-
-    public void setAccountOwner(Boolean accountOwner)
-    {
-        this.accountOwner = accountOwner;
-    }
-
-    public Sleeper withAccountOwner(Boolean accountOwner)
-    {
-        setAccountOwner(accountOwner);
-        return this;
-    }
-
-    public String getAccountId()
-    {
-        return accountId;
-    }
-
-    public void setAccountId(String accountId)
-    {
-        this.accountId = accountId;
-    }
-
-    public Sleeper withAccountId(String accountId)
-    {
-        setAccountId(accountId);
-        return this;
-    }
-
-    public String getEmail()
-    {
-        return email;
-    }
-
-    public void setEmail(String email)
-    {
-        this.email = email;
-    }
-
-    public Sleeper withEmail(String email)
-    {
-        setEmail(email);
-        return this;
-    }
-
-    public String getAvatar()
-    {
-        return avatar;
-    }
-
-    public void setAvatar(String avatar)
-    {
-        this.avatar = avatar;
-    }
-
-    public Sleeper withAvatar(String avatar)
-    {
-        setAvatar(avatar);
-        return this;
-    }
-
-    public String getLastLogin()
-    {
-        return lastLogin;
-    }
-
-    public void setLastLogin(String lastLogin)
-    {
-        this.lastLogin = lastLogin;
-    }
-
-    public Sleeper withLastLogin(String lastLogin)
-    {
-        setLastLogin(lastLogin);
-        return this;
-    }
-
-    public Integer getSide()
-    {
-        return side;
-    }
-
-    public void setSide(Integer side)
-    {
-        this.side = side;
-    }
-
-    public Sleeper withSide(Integer side)
-    {
-        setSide(side);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof Sleeper))
-        {
-            return false;
-        }
-        Sleeper other = (Sleeper)obj;
-        if (sleeperId == null)
-        {
-            if (other.sleeperId != null)
-            {
-                return false;
-            }
-        }
-        else if (!sleeperId.equals(other.sleeperId))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("Sleeper [firstName=");
-        builder.append(firstName);
-        builder.append(", active=");
-        builder.append(active);
-        builder.append(", emailValidated=");
-        builder.append(emailValidated);
-        builder.append(", child=");
-        builder.append(child);
-        builder.append(", bedId=");
-        builder.append(bedId);
-        builder.append(", birthYear=");
-        builder.append(birthYear);
-        builder.append(", zipCode=");
-        builder.append(zipCode);
-        builder.append(", timezone=");
-        builder.append(timezone);
-        builder.append(", male=");
-        builder.append(male);
-        builder.append(", weight=");
-        builder.append(weight);
-        builder.append(", duration=");
-        builder.append(duration);
-        builder.append(", sleeperId=");
-        builder.append(sleeperId);
-        builder.append(", height=");
-        builder.append(height);
-        builder.append(", licenseVersion=");
-        builder.append(licenseVersion);
-        builder.append(", username=");
-        builder.append(username);
-        builder.append(", birthMonth=");
-        builder.append(birthMonth);
-        builder.append(", sleepGoal=");
-        builder.append(sleepGoal);
-        builder.append(", accountOwner=");
-        builder.append(accountOwner);
-        builder.append(", accountId=");
-        builder.append(accountId);
-        builder.append(", email=");
-        builder.append(email);
-        builder.append(", avatar=");
-        builder.append(avatar);
-        builder.append(", lastLogin=");
-        builder.append(lastLogin);
-        builder.append(", side=");
-        builder.append(side);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/SleepersResponse.java
deleted file mode 100644 (file)
index 4c793ef..0000000
+++ /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<Sleeper> sleepers;
-
-    public List<Sleeper> getSleepers()
-    {
-        return sleepers;
-    }
-
-    public void setSleepers(List<Sleeper> sleepers)
-    {
-        this.sleepers = sleepers;
-    }
-
-    public SleepersResponse withSleepers(List<Sleeper> sleepers)
-    {
-        setSleepers(sleepers);
-        return this;
-    }
-
-    @Override
-    public int hashCode()
-    {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((sleepers == null) ? 0 : sleepers.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj)
-    {
-        if (this == obj)
-        {
-            return true;
-        }
-        if (obj == null)
-        {
-            return false;
-        }
-        if (!(obj instanceof SleepersResponse))
-        {
-            return false;
-        }
-        SleepersResponse other = (SleepersResponse)obj;
-        if (sleepers == null)
-        {
-            if (other.sleepers != null)
-            {
-                return false;
-            }
-        }
-        else if (!sleepers.equals(other.sleepers))
-        {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-        builder.append("SleepersResponse [sleepers=");
-        builder.append(sleepers);
-        builder.append("]");
-        return builder.toString();
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/java/org/openhab/binding/sleepiq/api/model/TimeSince.java
deleted file mode 100644 (file)
index c6c8704..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import java.time.Duration;
-import java.util.Objects;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class TimeSince {
-    private static final Pattern PATTERN = Pattern.compile("(([0-9]+) d )?([0-9]{2}):([0-9]{2}):([0-9]{2})",
-            Pattern.CASE_INSENSITIVE);
-
-    private Duration duration;
-
-    public Duration getDuration() {
-        return duration;
-    }
-
-    public void setDuration(Duration duration) {
-        this.duration = duration == null ? null : duration.abs();
-    }
-
-    public TimeSince withDuration(long days, long hours, long minutes, long seconds) {
-        return withDuration(Duration.ofSeconds(TimeUnit.DAYS.toSeconds(days) + TimeUnit.HOURS.toSeconds(hours)
-                + TimeUnit.MINUTES.toSeconds(minutes) + seconds));
-    }
-
-    public TimeSince withDuration(Duration duration) {
-        setDuration(duration);
-        return this;
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + ((duration == null) ? 0 : duration.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof TimeSince)) {
-            return false;
-        }
-        TimeSince other = (TimeSince) obj;
-        if (duration == null) {
-            if (other.duration != null) {
-                return false;
-            }
-        } else if (!duration.equals(other.duration)) {
-            return false;
-        }
-        return true;
-    }
-
-    @Override
-    public String toString() {
-        long totalDays = duration.toDays();
-        long totalHours = duration.toHours();
-        long totalMinutes = duration.toMinutes();
-        long totalSeconds = duration.getSeconds();
-
-        long hours = totalHours - TimeUnit.DAYS.toHours(totalDays);
-        long minutes = totalMinutes - TimeUnit.HOURS.toMinutes(totalHours);
-        long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(totalMinutes);
-
-        if (totalDays > 0) {
-            return String.format("%d d %02d:%02d:%02d", totalDays, hours, minutes, seconds);
-        }
-
-        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
-    }
-
-    public static TimeSince parse(CharSequence text) {
-        Objects.requireNonNull(text, "text");
-
-        Matcher matcher = PATTERN.matcher(text);
-        if (!matcher.matches()) {
-            return new TimeSince().withDuration(Duration.ZERO);
-        }
-
-        String dayMatch = matcher.group(2);
-        String hourMatch = matcher.group(3);
-        String minuteMatch = matcher.group(4);
-        String secondMatch = matcher.group(5);
-
-        StringBuilder sb = new StringBuilder("P");
-        if (dayMatch != null) {
-            sb.append(dayMatch).append('D');
-        }
-        sb.append('T').append(hourMatch).append('H').append(minuteMatch).append('M').append(secondMatch).append('S');
-
-        return new TimeSince().withDuration(Duration.parse(sb.toString()));
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java
deleted file mode 100644 (file)
index 796bd5a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.FileReader;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class BedSideStatusTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        BedSideStatus bedSideStatus = new BedSideStatus().withAlertDetailedMessage("No Alert").withAlertId(0L)
-                .withInBed(false).withLastLink(new TimeSince().withDuration(3, 5, 4, 38)).withPressure(573)
-                .withSleepNumber(55);
-        assertEquals(readJson("bed-side-status.json"), gson.toJson(bedSideStatus));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("bed-side-status.json"))) {
-            BedSideStatus bedSideStatus = gson.fromJson(reader, BedSideStatus.class);
-            assertEquals("No Alert", bedSideStatus.getAlertDetailedMessage());
-            assertEquals(Long.valueOf(0L), bedSideStatus.getAlertId());
-            assertFalse(bedSideStatus.isInBed());
-            assertEquals(new TimeSince().withDuration(3, 5, 4, 38), bedSideStatus.getLastLink());
-            assertEquals(Integer.valueOf(573), bedSideStatus.getPressure());
-            assertEquals(Integer.valueOf(55), bedSideStatus.getSleepNumber());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedStatusTest.java
deleted file mode 100644 (file)
index 331675b..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.FileReader;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class BedStatusTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        BedStatus bedStatus = new BedStatus().withBedId("-9999999999999999999")
-                .withLeftSide(new BedSideStatus().withInBed(true)).withRightSide(new BedSideStatus().withInBed(false))
-                .withStatus(1L);
-        assertEquals(readJson("bed-status.json"), gson.toJson(bedStatus));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("bed-status.json"))) {
-            BedStatus bedStatus = gson.fromJson(reader, BedStatus.class);
-            assertEquals("-9999999999999999999", bedStatus.getBedId());
-            assertEquals(Long.valueOf(1L), bedStatus.getStatus());
-
-            BedSideStatus leftSide = bedStatus.getLeftSide();
-            assertNotNull(leftSide);
-            assertTrue(leftSide.isInBed());
-
-            BedSideStatus rightSide = bedStatus.getRightSide();
-            assertNotNull(rightSide);
-            assertFalse(rightSide.isInBed());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedTest.java
deleted file mode 100644 (file)
index 3873351..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.FileReader;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class BedTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        Bed bed = new Bed().withAccountId("-8888888888888888888").withBase("MODULAR").withBedId("-9999999999999999999")
-                .withDualSleep(true).withKidsBed(false).withMacAddress("AABBCCDDEEFF").withModel("P5").withName("Bed")
-                .withPurchaseDate(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()))
-                .withReference("55555555555-5")
-                .withRegistrationDate(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()))
-                .withReturnRequestStatus(0L).withSerial("").withSize("QUEEN").withSku("QP5")
-                .withSleeperLeftId("-2222222222222222222").withSleeperRightId("-1111111111111111111").withStatus(1L)
-                .withTimezone("US/Pacific").withVersion("").withZipCode("90210");
-        assertEquals(readJson("bed.json"), gson.toJson(bed));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("bed.json"))) {
-            Bed bed = gson.fromJson(reader, Bed.class);
-            assertEquals("-8888888888888888888", bed.getAccountId());
-            assertEquals("MODULAR", bed.getBase());
-            assertEquals("-9999999999999999999", bed.getBedId());
-            assertEquals(true, bed.isDualSleep());
-            assertEquals(false, bed.isKidsBed());
-            assertEquals("AABBCCDDEEFF", bed.getMacAddress());
-            assertEquals("P5", bed.getModel());
-            assertEquals("Bed", bed.getName());
-            assertEquals(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()), bed.getPurchaseDate());
-            assertEquals("55555555555-5", bed.getReference());
-            assertEquals(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()),
-                    bed.getRegistrationDate());
-            assertEquals(Long.valueOf(0L), bed.getReturnRequestStatus());
-            assertEquals("", bed.getSerial());
-            assertEquals("QUEEN", bed.getSize());
-            assertEquals("QP5", bed.getSku());
-            assertEquals("-2222222222222222222", bed.getSleeperLeftId());
-            assertEquals("-1111111111111111111", bed.getSleeperRightId());
-            assertEquals(Long.valueOf(1L), bed.getStatus());
-            assertEquals("US/Pacific", bed.getTimezone());
-            assertEquals("", bed.getVersion());
-            assertEquals("90210", bed.getZipCode());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java
deleted file mode 100644 (file)
index 5a1f6c4..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.FileReader;
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class BedsResponseTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        BedsResponse bedsResponse = new BedsResponse()
-                .withBeds(Arrays.asList(new Bed().withName("Bed1"), new Bed().withName("Bed2")));
-        assertEquals(readJson("beds-response.json"), gson.toJson(bedsResponse));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("beds-response.json"))) {
-            BedsResponse bedsResponse = gson.fromJson(reader, BedsResponse.class);
-
-            List<Bed> beds = bedsResponse.getBeds();
-            assertNotNull(beds);
-            assertEquals(2, beds.size());
-            assertEquals("Bed1", beds.get(0).getName());
-            assertEquals("Bed2", beds.get(1).getName());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java
deleted file mode 100644 (file)
index 2fa2016..0000000
+++ /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<BedStatus> 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 (file)
index d36bd3a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.FileReader;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class PauseModeTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        PauseMode pauseMode = new PauseMode().withAccountId("-8888888888888888888").withBedId("-9999999999999999999")
-                .withPauseMode("off");
-        assertEquals(readJson("pause-mode.json"), gson.toJson(pauseMode));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("pause-mode.json"))) {
-            PauseMode pauseMode = gson.fromJson(reader, PauseMode.class);
-            assertEquals("-8888888888888888888", pauseMode.getAccountId());
-            assertEquals("-9999999999999999999", pauseMode.getBedId());
-            assertEquals("off", pauseMode.getPauseMode());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleeperTest.java
deleted file mode 100644 (file)
index 8b184b6..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.io.FileReader;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class SleeperTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        Sleeper sleeper = new Sleeper().withAccountId("-5555555555555555555").withAccountOwner(true).withActive(true)
-                .withAvatar("").withBedId("-9999999999999999999").withBirthMonth(6).withBirthYear("1970")
-                .withChild(false).withDuration("").withEmail("alice@domain.com").withEmailValidated(true)
-                .withFirstName("Alice").withHeight(64).withLastLogin("2017-02-17 20:19:36 CST").withLicenseVersion(6L)
-                .withMale(false).withSide(1).withSleeperId("-1111111111111111111").withSleepGoal(450)
-                .withTimezone("US/Pacific").withUsername("alice@domain.com").withWeight(110).withZipCode("90210");
-        assertEquals(readJson("sleeper.json"), gson.toJson(sleeper));
-    }
-
-    @Test
-    public void testSerializeLastLoginNull() throws Exception {
-        Sleeper sleeper = new Sleeper().withLastLogin("null");
-        assertEquals(readJson("sleeper-lastlogin-null.json"), gson.toJson(sleeper));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("sleeper.json"))) {
-            Sleeper sleeper = gson.fromJson(reader, Sleeper.class);
-            assertEquals("-5555555555555555555", sleeper.getAccountId());
-            assertEquals(true, sleeper.isAccountOwner());
-            assertEquals(true, sleeper.isActive());
-            assertEquals("", sleeper.getAvatar());
-            assertEquals("-9999999999999999999", sleeper.getBedId());
-            assertEquals(Integer.valueOf(6), sleeper.getBirthMonth());
-            assertEquals("1970", sleeper.getBirthYear());
-            assertEquals(false, sleeper.isChild());
-            assertEquals("", sleeper.getDuration());
-            assertEquals("alice@domain.com", sleeper.getEmail());
-            assertEquals(true, sleeper.isEmailValidated());
-            assertEquals("Alice", sleeper.getFirstName());
-            assertEquals(Integer.valueOf(64), sleeper.getHeight());
-            assertEquals("2017-02-17 20:19:36 CST", sleeper.getLastLogin());
-            assertEquals(Long.valueOf(6L), sleeper.getLicenseVersion());
-            assertEquals(false, sleeper.isMale());
-            assertEquals(Integer.valueOf(1), sleeper.getSide());
-            assertEquals("-1111111111111111111", sleeper.getSleeperId());
-            assertEquals(Integer.valueOf(450), sleeper.getSleepGoal());
-            assertEquals("US/Pacific", sleeper.getTimezone());
-            assertEquals("alice@domain.com", sleeper.getUsername());
-            assertEquals(Integer.valueOf(110), sleeper.getWeight());
-            assertEquals("90210", sleeper.getZipCode());
-        }
-    }
-
-    @Test
-    public void testDeserializeLastLoginNull() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("sleeper-lastlogin-null.json"))) {
-            Sleeper sleeper = gson.fromJson(reader, Sleeper.class);
-            assertEquals("null", sleeper.getLastLogin());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java
deleted file mode 100644 (file)
index 118a24a..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.io.FileReader;
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.openhab.binding.sleepiq.api.impl.GsonGenerator;
-import org.openhab.binding.sleepiq.api.test.AbstractTest;
-
-import com.google.gson.Gson;
-
-public class SleepersResponseTest extends AbstractTest {
-    private static Gson gson;
-
-    @BeforeAll
-    public static void setUpBeforeClass() {
-        gson = GsonGenerator.create(true);
-    }
-
-    @Test
-    public void testSerializeAllFields() throws Exception {
-        SleepersResponse sleepersResponse = new SleepersResponse()
-                .withSleepers(Arrays.asList(new Sleeper().withFirstName("Alice"), new Sleeper().withFirstName("Bob")));
-        assertEquals(readJson("sleepers-response.json"), gson.toJson(sleepersResponse));
-    }
-
-    @Test
-    public void testDeserializeAllFields() throws Exception {
-        try (FileReader reader = new FileReader(getTestDataFile("sleepers-response.json"))) {
-            SleepersResponse sleepersResponse = gson.fromJson(reader, SleepersResponse.class);
-
-            List<Sleeper> sleepers = sleepersResponse.getSleepers();
-            assertNotNull(sleepers);
-            assertEquals(2, sleepers.size());
-            assertEquals("Alice", sleepers.get(0).getFirstName());
-            assertEquals("Bob", sleepers.get(1).getFirstName());
-        }
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java
deleted file mode 100644 (file)
index 3e5d3d1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.model;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import java.time.Duration;
-
-import org.junit.jupiter.api.Test;
-
-public class TimeSinceTest {
-    @Test
-    public void testWithDuration() {
-        assertEquals(new TimeSince().withDuration(0, 0, 0, 0).getDuration(),
-                new TimeSince().withDuration(Duration.parse("PT00H00M00S")).getDuration());
-        assertEquals(new TimeSince().withDuration(0, 2, 3, 4).getDuration(),
-                new TimeSince().withDuration(Duration.parse("PT02H03M04S")).getDuration());
-        assertEquals(new TimeSince().withDuration(0, 12, 34, 56).getDuration(),
-                new TimeSince().withDuration(Duration.parse("PT12H34M56S")).getDuration());
-        assertEquals(new TimeSince().withDuration(1, 2, 3, 4).getDuration(),
-                new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).getDuration());
-        assertEquals(new TimeSince().withDuration(12, 23, 34, 45).getDuration(),
-                new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).getDuration());
-    }
-
-    @Test
-    public void testToString() {
-        assertEquals("00:00:00", new TimeSince().withDuration(Duration.parse("PT00H00M00S")).toString());
-        assertEquals("02:03:04", new TimeSince().withDuration(Duration.parse("PT02H03M04S")).toString());
-        assertEquals("12:34:56", new TimeSince().withDuration(Duration.parse("PT12H34M56S")).toString());
-        assertEquals("1 d 02:03:04", new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).toString());
-        assertEquals("12 d 23:34:45", new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).toString());
-    }
-
-    @Test
-    public void testParse() {
-        assertEquals(Duration.parse("PT00H00M00S"), TimeSince.parse("00:00:00").getDuration());
-        assertEquals(Duration.parse("PT2H3M4S"), TimeSince.parse("02:03:04").getDuration());
-        assertEquals(Duration.parse("PT12H34M56S"), TimeSince.parse("12:34:56").getDuration());
-        assertEquals(Duration.parse("P1DT2H3M4S"), TimeSince.parse("1 d 02:03:04").getDuration());
-        assertEquals(Duration.parse("P12DT23H34M45S"), TimeSince.parse("12 d 23:34:45").getDuration());
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java b/bundles/org.openhab.binding.sleepiq/src/3rdparty/test/org/openhab/binding/sleepiq/api/test/AbstractTest.java
deleted file mode 100644 (file)
index 955f7e2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2017 Gregory Moyer
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.openhab.binding.sleepiq.api.test;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public abstract class AbstractTest {
-    private static final String RESOURCES_PATH = "src/test/resources/";
-
-    protected File getTestDataFile(String name) {
-        return getTestDataPath(name).toFile();
-    }
-
-    protected Path getTestDataPath(String name) {
-        String packageName = this.getClass().getPackage().getName();
-
-        List<String> paths = new ArrayList<>();
-        paths.addAll(Arrays.asList(packageName.split("\\.")));
-        paths.add(name);
-
-        return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()]));
-    }
-
-    protected String readJson(String jsonFileName) throws IOException {
-        return String.join("\n", Files.readAllLines(getTestDataPath(jsonFileName)));
-    }
-}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/GsonProvider.java
deleted file mode 100644 (file)
index 1438a5e..0000000
+++ /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 <T>
- */
-@Provider
-@Produces(MediaType.APPLICATION_JSON)
-@Consumes(MediaType.APPLICATION_JSON)
-public class GsonProvider<T> implements MessageBodyReader<T>, MessageBodyWriter<T> {
-
-    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<String, Object> 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<T> type, Type genericType, Annotation[] annotations, MediaType mediaType,
-            MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
-            throws IOException, WebApplicationException {
-        try (InputStreamReader reader = new InputStreamReader(entityStream, StandardCharsets.UTF_8)) {
-            return gson.fromJson(reader, type);
-        }
-    }
-}
index f5eb4642a87e1f9c880a669f7526e2eae17f3cf4..63023921adc26df9dd5827f15ce5c496bcb2a0ff 100644 (file)
@@ -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
-    }
 }
index e4fc45aed01d4665119ddf234b1148308ae8eb73..a599b1a7b813a9b8afa315f155a462385a63ea91 100644 (file)
  */
 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";
index 318974b299069f6fecce951c94c2b7fe45d410d5..7bda6c0002ba6e320bfc6a9d460d76302ebb1308 100644 (file)
@@ -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<ThingTypeUID> 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<ThingUID, ServiceRegistration<?>> 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 (file)
index 0000000..de653f6
--- /dev/null
@@ -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 (file)
index 0000000..f25f94a
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link CommunicationException} is thrown when there's an error communicating with
+ * the sleepiq service.
+ *
+ * @author Mark Hilbush - Initial contribution
+ */
+@NonNullByDefault
+public class CommunicationException extends SleepIQException {
+    private static final long serialVersionUID = 1L;
+
+    public CommunicationException(String message) {
+        super(message);
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/Configuration.java
new file mode 100644 (file)
index 0000000..861b4a1
--- /dev/null
@@ -0,0 +1,166 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api;
+
+import java.net.URI;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * This class represents configuration parameters for using {@link SleepIQ}.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class Configuration {
+    private String username = "";
+    private String password = "";
+
+    private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com");
+
+    private boolean logging = false;
+
+    /**
+     * Get the username on the account.
+     *
+     * @return the username
+     */
+    public String getUsername() {
+        return username;
+    }
+
+    /**
+     * Set the username on the account. This should be the username used to
+     * register with SleepIQ.
+     *
+     * @param username
+     *            the value to set
+     */
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    /**
+     * Set the username on the account. This should be the username used to
+     * register with SleepIQ.
+     *
+     * @param username
+     *            the value to set
+     * @return this configuration instance
+     */
+    public Configuration withUsername(String username) {
+        setUsername(username);
+        return this;
+    }
+
+    /**
+     * Get the password on the account.
+     *
+     * @return the password
+     */
+    public String getPassword() {
+        return password;
+    }
+
+    /**
+     * Set the password on the account. This should be the password used to
+     * register with SleepIQ.
+     *
+     * @param password
+     *            the value to set
+     */
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    /**
+     * Set the password on the account. This should be the password used to
+     * register with SleepIQ.
+     *
+     * @param password
+     *            the value to set
+     * @return this configuration instance
+     */
+    public Configuration withPassword(String password) {
+        setPassword(password);
+        return this;
+    }
+
+    /**
+     * Get the base URI of the SleepIQ cloud service.
+     *
+     * @return the base URI
+     */
+    public URI getBaseUri() {
+        return baseUri;
+    }
+
+    /**
+     * Set the base URI of the SleepIQ cloud service. It is unlikely that this
+     * will need to be changed from its default value.
+     *
+     * @param baseUri
+     *            the value to set
+     */
+    public void setBaseUri(URI baseUri) {
+        this.baseUri = baseUri;
+    }
+
+    /**
+     * Set the base URI of the SleepIQ cloud service. It is unlikely that this
+     * will need to be changed from its default value.
+     *
+     * @param baseUri
+     *            the value to set
+     * @return this configuration instance
+     */
+    public Configuration withBaseUri(URI baseUri) {
+        setBaseUri(baseUri);
+        return this;
+    }
+
+    /**
+     * Get the logging flag.
+     *
+     * @return the logging flag
+     */
+    public boolean isLogging() {
+        return logging;
+    }
+
+    /**
+     * Set the logging flag. When this is set to <code>true</code>, all requests
+     * and responses will be logged at the {@link Level#INFO} level. <b>This
+     * includes usernames and passwords!</b>
+     *
+     * @param logging
+     *            the value to set
+     */
+    public void setLogging(boolean logging) {
+        this.logging = logging;
+    }
+
+    /**
+     * Set the logging flag. When this is set to <code>true</code>, all requests
+     * and responses will be logged at the {@link Level#INFO} level. <b>This
+     * includes usernames and passwords!</b>
+     *
+     * @param logging
+     *            the value to set
+     * @return this configuration instance
+     */
+    public Configuration withLogging(boolean logging) {
+        setLogging(logging);
+        return this;
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/LoginException.java
new file mode 100644 (file)
index 0000000..fcd957c
--- /dev/null
@@ -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 (file)
index 0000000..07a18b8
--- /dev/null
@@ -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 (file)
index 0000000..ca6a9bf
--- /dev/null
@@ -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<Bed> 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<Sleeper> 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 (file)
index 0000000..bf463e4
--- /dev/null
@@ -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 (file)
index 0000000..98a4778
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link UnauthorizedException} is thrown when a login to the sleepiq service
+ * is unauthorized to use the API.
+ *
+ * @author Mark Hilbush - Initial contribution
+ */
+@NonNullByDefault
+public class UnauthorizedException extends LoginException {
+    private static final long serialVersionUID = 1L;
+
+    public UnauthorizedException(String message) {
+        super(message);
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Bed.java
new file mode 100644 (file)
index 0000000..c8342cc
--- /dev/null
@@ -0,0 +1,400 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+import java.time.ZonedDateTime;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link Bed} holds the bed response from the sleepiq API.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class Bed {
+    private ZonedDateTime registrationDate;
+    private String sleeperRightId;
+    private String base;
+    private Long returnRequestStatus;
+    private String size;
+    private String name;
+    private String serial;
+    @SerializedName("isKidsBed")
+    private Boolean kidsBed;
+    private Boolean dualSleep;
+    private String bedId;
+    private Long status;
+    private String sleeperLeftId;
+    private String version;
+    private String accountId;
+    private String timezone;
+    private String model;
+    private ZonedDateTime purchaseDate;
+    private String macAddress;
+    private String sku;
+    @SerializedName("zipcode")
+    private String zipCode;
+    private String reference;
+
+    public ZonedDateTime getRegistrationDate() {
+        return registrationDate;
+    }
+
+    public void setRegistrationDate(ZonedDateTime registrationDate) {
+        this.registrationDate = registrationDate;
+    }
+
+    public Bed withRegistrationDate(ZonedDateTime registrationDate) {
+        setRegistrationDate(registrationDate);
+        return this;
+    }
+
+    public String getSleeperRightId() {
+        return sleeperRightId;
+    }
+
+    public void setSleeperRightId(String sleeperRightId) {
+        this.sleeperRightId = sleeperRightId;
+    }
+
+    public Bed withSleeperRightId(String sleeperRightId) {
+        setSleeperRightId(sleeperRightId);
+        return this;
+    }
+
+    public String getBase() {
+        return base;
+    }
+
+    public void setBase(String base) {
+        this.base = base;
+    }
+
+    public Bed withBase(String base) {
+        setBase(base);
+        return this;
+    }
+
+    public Long getReturnRequestStatus() {
+        return returnRequestStatus;
+    }
+
+    public void setReturnRequestStatus(Long returnRequestStatus) {
+        this.returnRequestStatus = returnRequestStatus;
+    }
+
+    public Bed withReturnRequestStatus(Long returnRequestStatus) {
+        setReturnRequestStatus(returnRequestStatus);
+        return this;
+    }
+
+    public String getSize() {
+        return size;
+    }
+
+    public void setSize(String size) {
+        this.size = size;
+    }
+
+    public Bed withSize(String size) {
+        setSize(size);
+        return this;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Bed withName(String name) {
+        setName(name);
+        return this;
+    }
+
+    public String getSerial() {
+        return serial;
+    }
+
+    public void setSerial(String serial) {
+        this.serial = serial;
+    }
+
+    public Bed withSerial(String serial) {
+        setSerial(serial);
+        return this;
+    }
+
+    public Boolean isKidsBed() {
+        return kidsBed;
+    }
+
+    public void setKidsBed(Boolean kidsBed) {
+        this.kidsBed = kidsBed;
+    }
+
+    public Bed withKidsBed(Boolean kidsBed) {
+        setKidsBed(kidsBed);
+        return this;
+    }
+
+    public Boolean isDualSleep() {
+        return dualSleep;
+    }
+
+    public void setDualSleep(Boolean dualSleep) {
+        this.dualSleep = dualSleep;
+    }
+
+    public Bed withDualSleep(Boolean dualSleep) {
+        setDualSleep(dualSleep);
+        return this;
+    }
+
+    public String getBedId() {
+        return bedId;
+    }
+
+    public void setBedId(String bedId) {
+        this.bedId = bedId;
+    }
+
+    public Bed withBedId(String bedId) {
+        setBedId(bedId);
+        return this;
+    }
+
+    public Long getStatus() {
+        return status;
+    }
+
+    public void setStatus(Long status) {
+        this.status = status;
+    }
+
+    public Bed withStatus(Long status) {
+        setStatus(status);
+        return this;
+    }
+
+    public String getSleeperLeftId() {
+        return sleeperLeftId;
+    }
+
+    public void setSleeperLeftId(String sleeperLeftId) {
+        this.sleeperLeftId = sleeperLeftId;
+    }
+
+    public Bed withSleeperLeftId(String sleeperLeftId) {
+        setSleeperLeftId(sleeperLeftId);
+        return this;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public Bed withVersion(String version) {
+        setVersion(version);
+        return this;
+    }
+
+    public String getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(String accountId) {
+        this.accountId = accountId;
+    }
+
+    public Bed withAccountId(String accountId) {
+        setAccountId(accountId);
+        return this;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(String timezone) {
+        this.timezone = timezone;
+    }
+
+    public Bed withTimezone(String timezone) {
+        setTimezone(timezone);
+        return this;
+    }
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public Bed withModel(String model) {
+        setModel(model);
+        return this;
+    }
+
+    public ZonedDateTime getPurchaseDate() {
+        return purchaseDate;
+    }
+
+    public void setPurchaseDate(ZonedDateTime purchaseDate) {
+        this.purchaseDate = purchaseDate;
+    }
+
+    public Bed withPurchaseDate(ZonedDateTime purchaseDate) {
+        setPurchaseDate(purchaseDate);
+        return this;
+    }
+
+    public String getMacAddress() {
+        return macAddress;
+    }
+
+    public void setMacAddress(String macAddress) {
+        this.macAddress = macAddress;
+    }
+
+    public Bed withMacAddress(String macAddress) {
+        setMacAddress(macAddress);
+        return this;
+    }
+
+    public String getSku() {
+        return sku;
+    }
+
+    public void setSku(String sku) {
+        this.sku = sku;
+    }
+
+    public Bed withSku(String sku) {
+        setSku(sku);
+        return this;
+    }
+
+    public String getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(String zipCode) {
+        this.zipCode = zipCode;
+    }
+
+    public Bed withZipCode(String zipCode) {
+        setZipCode(zipCode);
+        return this;
+    }
+
+    public String getReference() {
+        return reference;
+    }
+
+    public void setReference(String reference) {
+        this.reference = reference;
+    }
+
+    public Bed withReference(String reference) {
+        setReference(reference);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((bedId == null) ? 0 : bedId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof Bed)) {
+            return false;
+        }
+        Bed other = (Bed) obj;
+        if (bedId == null) {
+            if (other.bedId != null) {
+                return false;
+            }
+        } else if (!bedId.equals(other.bedId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Bed [registrationDate=");
+        builder.append(registrationDate);
+        builder.append(", sleeperRightId=");
+        builder.append(sleeperRightId);
+        builder.append(", base=");
+        builder.append(base);
+        builder.append(", returnRequestStatus=");
+        builder.append(returnRequestStatus);
+        builder.append(", size=");
+        builder.append(size);
+        builder.append(", name=");
+        builder.append(name);
+        builder.append(", serial=");
+        builder.append(serial);
+        builder.append(", kidsBed=");
+        builder.append(kidsBed);
+        builder.append(", dualSleep=");
+        builder.append(dualSleep);
+        builder.append(", bedId=");
+        builder.append(bedId);
+        builder.append(", status=");
+        builder.append(status);
+        builder.append(", sleeperLeftId=");
+        builder.append(sleeperLeftId);
+        builder.append(", version=");
+        builder.append(version);
+        builder.append(", accountId=");
+        builder.append(accountId);
+        builder.append(", timezone=");
+        builder.append(timezone);
+        builder.append(", model=");
+        builder.append(model);
+        builder.append(", purchaseDate=");
+        builder.append(purchaseDate);
+        builder.append(", macAddress=");
+        builder.append(macAddress);
+        builder.append(", sku=");
+        builder.append(sku);
+        builder.append(", zipCode=");
+        builder.append(zipCode);
+        builder.append(", reference=");
+        builder.append(reference);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedSideStatus.java
new file mode 100644 (file)
index 0000000..72844ff
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link BedSideStatus} holds the BedSideStatus response from the sleepiq API.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class BedSideStatus {
+    @SerializedName("isInBed")
+    private Boolean inBed;
+    private String alertDetailedMessage;
+    private Integer sleepNumber;
+    private Long alertId;
+    private TimeSince lastLink;
+    private Integer pressure; // appears to be in kPa
+
+    public Boolean isInBed() {
+        return inBed;
+    }
+
+    public void setInBed(Boolean inBed) {
+        this.inBed = inBed;
+    }
+
+    public BedSideStatus withInBed(Boolean inBed) {
+        setInBed(inBed);
+        return this;
+    }
+
+    public String getAlertDetailedMessage() {
+        return alertDetailedMessage;
+    }
+
+    public void setAlertDetailedMessage(String alertDetailedMessage) {
+        this.alertDetailedMessage = alertDetailedMessage;
+    }
+
+    public BedSideStatus withAlertDetailedMessage(String alertDetailedMessage) {
+        setAlertDetailedMessage(alertDetailedMessage);
+        return this;
+    }
+
+    public Integer getSleepNumber() {
+        return sleepNumber;
+    }
+
+    public void setSleepNumber(Integer sleepNumber) {
+        this.sleepNumber = sleepNumber;
+    }
+
+    public BedSideStatus withSleepNumber(Integer sleepNumber) {
+        setSleepNumber(sleepNumber);
+        return this;
+    }
+
+    public Long getAlertId() {
+        return alertId;
+    }
+
+    public void setAlertId(Long alertId) {
+        this.alertId = alertId;
+    }
+
+    public BedSideStatus withAlertId(Long alertId) {
+        setAlertId(alertId);
+        return this;
+    }
+
+    public TimeSince getLastLink() {
+        return lastLink;
+    }
+
+    public void setLastLink(TimeSince lastLink) {
+        this.lastLink = lastLink;
+    }
+
+    public BedSideStatus withLastLink(TimeSince lastLink) {
+        setLastLink(lastLink);
+        return this;
+    }
+
+    public Integer getPressure() {
+        return pressure;
+    }
+
+    public void setPressure(Integer pressure) {
+        this.pressure = pressure;
+    }
+
+    public BedSideStatus withPressure(Integer pressure) {
+        setPressure(pressure);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((alertDetailedMessage == null) ? 0 : alertDetailedMessage.hashCode());
+        result = prime * result + ((alertId == null) ? 0 : alertId.hashCode());
+        result = prime * result + ((inBed == null) ? 0 : inBed.hashCode());
+        result = prime * result + ((lastLink == null) ? 0 : lastLink.hashCode());
+        result = prime * result + ((pressure == null) ? 0 : pressure.hashCode());
+        result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof BedSideStatus)) {
+            return false;
+        }
+        BedSideStatus other = (BedSideStatus) obj;
+        if (alertDetailedMessage == null) {
+            if (other.alertDetailedMessage != null) {
+                return false;
+            }
+        } else if (!alertDetailedMessage.equals(other.alertDetailedMessage)) {
+            return false;
+        }
+        if (alertId == null) {
+            if (other.alertId != null) {
+                return false;
+            }
+        } else if (!alertId.equals(other.alertId)) {
+            return false;
+        }
+        if (inBed == null) {
+            if (other.inBed != null) {
+                return false;
+            }
+        } else if (!inBed.equals(other.inBed)) {
+            return false;
+        }
+        if (lastLink == null) {
+            if (other.lastLink != null) {
+                return false;
+            }
+        } else if (!lastLink.equals(other.lastLink)) {
+            return false;
+        }
+        if (pressure == null) {
+            if (other.pressure != null) {
+                return false;
+            }
+        } else if (!pressure.equals(other.pressure)) {
+            return false;
+        }
+        if (sleepNumber == null) {
+            if (other.sleepNumber != null) {
+                return false;
+            }
+        } else if (!sleepNumber.equals(other.sleepNumber)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("BedSideStatus [inBed=");
+        builder.append(inBed);
+        builder.append(", alertDetailedMessage=");
+        builder.append(alertDetailedMessage);
+        builder.append(", sleepNumber=");
+        builder.append(sleepNumber);
+        builder.append(", alertId=");
+        builder.append(alertId);
+        builder.append(", lastLink=");
+        builder.append(lastLink);
+        builder.append(", pressure=");
+        builder.append(pressure);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/BedStatus.java
new file mode 100644 (file)
index 0000000..c5f25ab
--- /dev/null
@@ -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 (file)
index 0000000..9cdaa4d
--- /dev/null
@@ -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<Bed> beds;
+
+    public List<Bed> getBeds() {
+        return beds;
+    }
+
+    public void setBeds(List<Bed> beds) {
+        this.beds = beds;
+    }
+
+    public BedsResponse withBeds(List<Bed> 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 (file)
index 0000000..6865067
--- /dev/null
@@ -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 (file)
index 0000000..028055c
--- /dev/null
@@ -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 (file)
index 0000000..b0f90c1
--- /dev/null
@@ -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<BedStatus> beds;
+
+    public List<BedStatus> getBeds() {
+        return beds;
+    }
+
+    public void setBeds(List<BedStatus> beds) {
+        this.beds = beds;
+    }
+
+    public FamilyStatusResponse withBeds(List<BedStatus> beds) {
+        setBeds(beds);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((beds == null) ? 0 : beds.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof FamilyStatusResponse)) {
+            return false;
+        }
+        FamilyStatusResponse other = (FamilyStatusResponse) obj;
+        if (beds == null) {
+            if (other.beds != null) {
+                return false;
+            }
+        } else if (!beds.equals(other.beds)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("FamilyStatus [beds=");
+        builder.append(beds);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginInfo.java
new file mode 100644 (file)
index 0000000..9f51fc9
--- /dev/null
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+/**
+ * The {@link LoginInfo} holds the LoginInfo response from the sleepiq API.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class LoginInfo {
+    private String userId;
+    private String key;
+    private Long registrationState;
+    private Long edpLoginStatus;
+    private String edpLoginMessage;
+
+    public String getUserId() {
+        return userId;
+    }
+
+    public void setUserId(String userId) {
+        this.userId = userId;
+    }
+
+    public LoginInfo withUserId(String userId) {
+        setUserId(userId);
+        return this;
+    }
+
+    public String getKey() {
+        return key;
+    }
+
+    public void setKey(String key) {
+        this.key = key;
+    }
+
+    public LoginInfo withKey(String key) {
+        setKey(key);
+        return this;
+    }
+
+    public Long getRegistrationState() {
+        return registrationState;
+    }
+
+    public void setRegistrationState(Long registrationState) {
+        this.registrationState = registrationState;
+    }
+
+    public LoginInfo withRegistrationState(Long registrationState) {
+        setRegistrationState(registrationState);
+        return this;
+    }
+
+    public Long getEdpLoginStatus() {
+        return edpLoginStatus;
+    }
+
+    public void setEdpLoginStatus(Long edpLoginStatus) {
+        this.edpLoginStatus = edpLoginStatus;
+    }
+
+    public LoginInfo withEdpLoginStatus(Long edpLoginStatus) {
+        setEdpLoginStatus(edpLoginStatus);
+        return this;
+    }
+
+    public String getEdpLoginMessage() {
+        return edpLoginMessage;
+    }
+
+    public void setEdpLoginMessage(String edpLoginMessage) {
+        this.edpLoginMessage = edpLoginMessage;
+    }
+
+    public LoginInfo withEdpLoginMessage(String edpLoginMessage) {
+        setEdpLoginMessage(edpLoginMessage);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((key == null) ? 0 : key.hashCode());
+        result = prime * result + (int) (registrationState ^ (registrationState >>> 32));
+        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof LoginInfo)) {
+            return false;
+        }
+        LoginInfo other = (LoginInfo) obj;
+        if (key == null) {
+            if (other.key != null) {
+                return false;
+            }
+        } else if (!key.equals(other.key)) {
+            return false;
+        }
+        if (!registrationState.equals(other.registrationState)) {
+            return false;
+        }
+        if (userId == null) {
+            if (other.userId != null) {
+                return false;
+            }
+        } else if (!userId.equals(other.userId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("LoginInfo [userId=");
+        builder.append(userId);
+        builder.append(", key=");
+        builder.append(key);
+        builder.append(", registrationState=");
+        builder.append(registrationState);
+        builder.append(", edpLoginStatus=");
+        builder.append(edpLoginStatus);
+        builder.append(", edpLoginMessage=");
+        builder.append(edpLoginMessage);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/LoginRequest.java
new file mode 100644 (file)
index 0000000..6cbe4d1
--- /dev/null
@@ -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 (file)
index 0000000..f536d80
--- /dev/null
@@ -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 (file)
index 0000000..966093b
--- /dev/null
@@ -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 (file)
index 0000000..72ee26f
--- /dev/null
@@ -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<SleepDataSession> dailySessions;
+
+    public LocalDate getDate() {
+        return date;
+    }
+
+    public String getMessage() {
+        return dailyMessage;
+    }
+
+    public List<SleepDataSession> 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 (file)
index 0000000..c8a36e7
--- /dev/null
@@ -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<SleepDataDay> 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<SleepDataDay> 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 (file)
index 0000000..be6cd94
--- /dev/null
@@ -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 (file)
index 0000000..b07a2ff
--- /dev/null
@@ -0,0 +1,125 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+import org.openhab.binding.sleepiq.internal.api.enums.Side;
+
+/**
+ * The {@link SleepNumberRequest} holds the information used to set the sleep number
+ * for a bed side.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class SleepNumberRequest {
+    private String bedId;
+    private Integer sleepNumber;
+    private Side side;
+
+    public String getBedId() {
+        return bedId;
+    }
+
+    public void setBedId(String bedId) {
+        this.bedId = bedId;
+    }
+
+    public SleepNumberRequest withBedId(String bedId) {
+        setBedId(bedId);
+        return this;
+    }
+
+    public Integer getSleepNumber() {
+        return sleepNumber;
+    }
+
+    public void setSleepNumber(Integer sleepNumber) {
+        this.sleepNumber = sleepNumber;
+    }
+
+    public SleepNumberRequest withSleepNumber(Integer sleepNumber) {
+        setSleepNumber(sleepNumber);
+        return this;
+    }
+
+    public Side getSide() {
+        return side;
+    }
+
+    public void setSide(Side side) {
+        this.side = side;
+    }
+
+    public SleepNumberRequest withSide(Side side) {
+        setSide(side);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((bedId == null) ? 0 : bedId.hashCode());
+        result = prime * result + ((sleepNumber == null) ? 0 : sleepNumber.hashCode());
+        result = prime * result + ((side == null) ? 0 : side.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof SleepNumberRequest)) {
+            return false;
+        }
+        SleepNumberRequest other = (SleepNumberRequest) obj;
+        if (bedId == null) {
+            if (other.bedId != null) {
+                return false;
+            }
+        } else if (!bedId.equals(other.bedId)) {
+            return false;
+        }
+        if (sleepNumber == null) {
+            if (other.sleepNumber != null) {
+                return false;
+            }
+        } else if (sleepNumber.equals(other.sleepNumber)) {
+            return false;
+        }
+        if (side == null) {
+            if (other.side != null) {
+                return false;
+            }
+        } else if (!side.equals(other.side)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("SleepNumberRequest [bedId=");
+        builder.append(bedId);
+        builder.append(", sleepNumber=");
+        builder.append(sleepNumber);
+        builder.append(", side=");
+        builder.append(side);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/Sleeper.java
new file mode 100644 (file)
index 0000000..d10b6c4
--- /dev/null
@@ -0,0 +1,434 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+import org.openhab.binding.sleepiq.internal.api.enums.Side;
+
+import com.google.gson.annotations.SerializedName;
+
+/**
+ * The {@link Sleeper} holds the information about the sleeper that's
+ * associated with a bed side.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class Sleeper {
+    private String firstName;
+    private Boolean active;
+    private Boolean emailValidated;
+    @SerializedName("isChild")
+    private Boolean child;
+    private String bedId;
+    private String birthYear;
+    private String zipCode;
+    private String timezone;
+    @SerializedName("isMale")
+    private Boolean male;
+    private Integer weight; // lbs
+    private String duration;
+    private String sleeperId;
+    private Integer height; // inches
+    private Long licenseVersion;
+    private String username;
+    private Integer birthMonth; // 0-based; 12 means not entered?
+    private Integer sleepGoal;
+    @SerializedName("isAccountOwner")
+    private Boolean accountOwner;
+    private String accountId;
+    private String email;
+    private String avatar;
+    private String lastLogin; // should be ZonedDateTime but provider passes string "null" when missing
+    private Side side; // 0=left; 1=right
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public Sleeper withFirstName(String firstName) {
+        setFirstName(firstName);
+        return this;
+    }
+
+    public Boolean isActive() {
+        return active;
+    }
+
+    public void setActive(Boolean active) {
+        this.active = active;
+    }
+
+    public Sleeper withActive(Boolean active) {
+        setActive(active);
+        return this;
+    }
+
+    public Boolean isEmailValidated() {
+        return emailValidated;
+    }
+
+    public void setEmailValidated(Boolean emailValidated) {
+        this.emailValidated = emailValidated;
+    }
+
+    public Sleeper withEmailValidated(Boolean emailValidated) {
+        setEmailValidated(emailValidated);
+        return this;
+    }
+
+    public Boolean isChild() {
+        return child;
+    }
+
+    public void setChild(Boolean child) {
+        this.child = child;
+    }
+
+    public Sleeper withChild(Boolean child) {
+        setChild(child);
+        return this;
+    }
+
+    public String getBedId() {
+        return bedId;
+    }
+
+    public void setBedId(String bedId) {
+        this.bedId = bedId;
+    }
+
+    public Sleeper withBedId(String bedId) {
+        setBedId(bedId);
+        return this;
+    }
+
+    public String getBirthYear() {
+        return birthYear;
+    }
+
+    public void setBirthYear(String birthYear) {
+        this.birthYear = birthYear;
+    }
+
+    public Sleeper withBirthYear(String birthYear) {
+        setBirthYear(birthYear);
+        return this;
+    }
+
+    public String getZipCode() {
+        return zipCode;
+    }
+
+    public void setZipCode(String zipCode) {
+        this.zipCode = zipCode;
+    }
+
+    public Sleeper withZipCode(String zipCode) {
+        setZipCode(zipCode);
+        return this;
+    }
+
+    public String getTimezone() {
+        return timezone;
+    }
+
+    public void setTimezone(String timezone) {
+        this.timezone = timezone;
+    }
+
+    public Sleeper withTimezone(String timezone) {
+        setTimezone(timezone);
+        return this;
+    }
+
+    public Boolean isMale() {
+        return male;
+    }
+
+    public void setMale(Boolean male) {
+        this.male = male;
+    }
+
+    public Sleeper withMale(Boolean male) {
+        setMale(male);
+        return this;
+    }
+
+    public Integer getWeight() {
+        return weight;
+    }
+
+    public void setWeight(Integer weight) {
+        this.weight = weight;
+    }
+
+    public Sleeper withWeight(Integer weight) {
+        setWeight(weight);
+        return this;
+    }
+
+    public String getDuration() {
+        return duration;
+    }
+
+    public void setDuration(String duration) {
+        this.duration = duration;
+    }
+
+    public Sleeper withDuration(String duration) {
+        setDuration(duration);
+        return this;
+    }
+
+    public String getSleeperId() {
+        return sleeperId;
+    }
+
+    public void setSleeperId(String sleeperId) {
+        this.sleeperId = sleeperId;
+    }
+
+    public Sleeper withSleeperId(String sleeperId) {
+        setSleeperId(sleeperId);
+        return this;
+    }
+
+    public Integer getHeight() {
+        return height;
+    }
+
+    public void setHeight(Integer height) {
+        this.height = height;
+    }
+
+    public Sleeper withHeight(Integer height) {
+        setHeight(height);
+        return this;
+    }
+
+    public Long getLicenseVersion() {
+        return licenseVersion;
+    }
+
+    public void setLicenseVersion(Long licenseVersion) {
+        this.licenseVersion = licenseVersion;
+    }
+
+    public Sleeper withLicenseVersion(Long licenseVersion) {
+        setLicenseVersion(licenseVersion);
+        return this;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public Sleeper withUsername(String username) {
+        setUsername(username);
+        return this;
+    }
+
+    public Integer getBirthMonth() {
+        return birthMonth;
+    }
+
+    public void setBirthMonth(Integer birthMonth) {
+        this.birthMonth = birthMonth;
+    }
+
+    public Sleeper withBirthMonth(Integer birthMonth) {
+        setBirthMonth(birthMonth);
+        return this;
+    }
+
+    public Integer getSleepGoal() {
+        return sleepGoal;
+    }
+
+    public void setSleepGoal(Integer sleepGoal) {
+        this.sleepGoal = sleepGoal;
+    }
+
+    public Sleeper withSleepGoal(Integer sleepGoal) {
+        setSleepGoal(sleepGoal);
+        return this;
+    }
+
+    public Boolean isAccountOwner() {
+        return accountOwner;
+    }
+
+    public void setAccountOwner(Boolean accountOwner) {
+        this.accountOwner = accountOwner;
+    }
+
+    public Sleeper withAccountOwner(Boolean accountOwner) {
+        setAccountOwner(accountOwner);
+        return this;
+    }
+
+    public String getAccountId() {
+        return accountId;
+    }
+
+    public void setAccountId(String accountId) {
+        this.accountId = accountId;
+    }
+
+    public Sleeper withAccountId(String accountId) {
+        setAccountId(accountId);
+        return this;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public Sleeper withEmail(String email) {
+        setEmail(email);
+        return this;
+    }
+
+    public String getAvatar() {
+        return avatar;
+    }
+
+    public void setAvatar(String avatar) {
+        this.avatar = avatar;
+    }
+
+    public Sleeper withAvatar(String avatar) {
+        setAvatar(avatar);
+        return this;
+    }
+
+    public String getLastLogin() {
+        return lastLogin;
+    }
+
+    public void setLastLogin(String lastLogin) {
+        this.lastLogin = lastLogin;
+    }
+
+    public Sleeper withLastLogin(String lastLogin) {
+        setLastLogin(lastLogin);
+        return this;
+    }
+
+    public Side getSide() {
+        return side;
+    }
+
+    public void setSide(Side side) {
+        this.side = side;
+    }
+
+    public Sleeper withSide(Side side) {
+        setSide(side);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((sleeperId == null) ? 0 : sleeperId.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof Sleeper)) {
+            return false;
+        }
+        Sleeper other = (Sleeper) obj;
+        if (sleeperId == null) {
+            if (other.sleeperId != null) {
+                return false;
+            }
+        } else if (!sleeperId.equals(other.sleeperId)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Sleeper [firstName=");
+        builder.append(firstName);
+        builder.append(", active=");
+        builder.append(active);
+        builder.append(", emailValidated=");
+        builder.append(emailValidated);
+        builder.append(", child=");
+        builder.append(child);
+        builder.append(", bedId=");
+        builder.append(bedId);
+        builder.append(", birthYear=");
+        builder.append(birthYear);
+        builder.append(", zipCode=");
+        builder.append(zipCode);
+        builder.append(", timezone=");
+        builder.append(timezone);
+        builder.append(", male=");
+        builder.append(male);
+        builder.append(", weight=");
+        builder.append(weight);
+        builder.append(", duration=");
+        builder.append(duration);
+        builder.append(", sleeperId=");
+        builder.append(sleeperId);
+        builder.append(", height=");
+        builder.append(height);
+        builder.append(", licenseVersion=");
+        builder.append(licenseVersion);
+        builder.append(", username=");
+        builder.append(username);
+        builder.append(", birthMonth=");
+        builder.append(birthMonth);
+        builder.append(", sleepGoal=");
+        builder.append(sleepGoal);
+        builder.append(", accountOwner=");
+        builder.append(accountOwner);
+        builder.append(", accountId=");
+        builder.append(accountId);
+        builder.append(", email=");
+        builder.append(email);
+        builder.append(", avatar=");
+        builder.append(avatar);
+        builder.append(", lastLogin=");
+        builder.append(lastLogin);
+        builder.append(", side=");
+        builder.append(side);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/SleepersResponse.java
new file mode 100644 (file)
index 0000000..d482d47
--- /dev/null
@@ -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<Sleeper> sleepers;
+
+    public List<Sleeper> getSleepers() {
+        return sleepers;
+    }
+
+    public void setSleepers(List<Sleeper> sleepers) {
+        this.sleepers = sleepers;
+    }
+
+    public SleepersResponse withSleepers(List<Sleeper> sleepers) {
+        setSleepers(sleepers);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((sleepers == null) ? 0 : sleepers.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof SleepersResponse)) {
+            return false;
+        }
+        SleepersResponse other = (SleepersResponse) obj;
+        if (sleepers == null) {
+            if (other.sleepers != null) {
+                return false;
+            }
+        } else if (!sleepers.equals(other.sleepers)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("SleepersResponse [sleepers=");
+        builder.append(sleepers);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/dto/TimeSince.java
new file mode 100644 (file)
index 0000000..3b83451
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.dto;
+
+import java.time.Duration;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * The {@link TimeSince} converts from "nn d hh:mm:ss" to Duration
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+public class TimeSince {
+    private static final Pattern PATTERN = Pattern.compile("(([0-9]+) d )?([0-9]{2}):([0-9]{2}):([0-9]{2})",
+            Pattern.CASE_INSENSITIVE);
+
+    private Duration duration;
+
+    public Duration getDuration() {
+        return duration;
+    }
+
+    public void setDuration(Duration duration) {
+        this.duration = duration == null ? null : duration.abs();
+    }
+
+    public TimeSince withDuration(long days, long hours, long minutes, long seconds) {
+        return withDuration(Duration.ofSeconds(TimeUnit.DAYS.toSeconds(days) + TimeUnit.HOURS.toSeconds(hours)
+                + TimeUnit.MINUTES.toSeconds(minutes) + seconds));
+    }
+
+    public TimeSince withDuration(Duration duration) {
+        setDuration(duration);
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((duration == null) ? 0 : duration.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof TimeSince)) {
+            return false;
+        }
+        TimeSince other = (TimeSince) obj;
+        if (duration == null) {
+            if (other.duration != null) {
+                return false;
+            }
+        } else if (!duration.equals(other.duration)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        long totalDays = duration.toDays();
+        long totalHours = duration.toHours();
+        long totalMinutes = duration.toMinutes();
+        long totalSeconds = duration.getSeconds();
+
+        long hours = totalHours - TimeUnit.DAYS.toHours(totalDays);
+        long minutes = totalMinutes - TimeUnit.HOURS.toMinutes(totalHours);
+        long seconds = totalSeconds - TimeUnit.MINUTES.toSeconds(totalMinutes);
+
+        if (totalDays > 0) {
+            return String.format("%d d %02d:%02d:%02d", totalDays, hours, minutes, seconds);
+        }
+
+        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
+    }
+
+    public static TimeSince parse(CharSequence text) {
+        Objects.requireNonNull(text, "text");
+
+        Matcher matcher = PATTERN.matcher(text);
+        if (!matcher.matches()) {
+            return new TimeSince().withDuration(Duration.ZERO);
+        }
+
+        String dayMatch = matcher.group(2);
+        String hourMatch = matcher.group(3);
+        String minuteMatch = matcher.group(4);
+        String secondMatch = matcher.group(5);
+
+        StringBuilder sb = new StringBuilder("P");
+        if (dayMatch != null) {
+            sb.append(dayMatch).append('D');
+        }
+        sb.append('T').append(hourMatch).append('H').append(minuteMatch).append('M').append(secondMatch).append('S');
+
+        return new TimeSince().withDuration(Duration.parse(sb.toString()));
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/enums/Side.java
new file mode 100644 (file)
index 0000000..5176362
--- /dev/null
@@ -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 (file)
index 0000000..a73f0f6
--- /dev/null
@@ -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 (file)
index 0000000..c806e3e
--- /dev/null
@@ -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 (file)
index 0000000..64e99ad
--- /dev/null
@@ -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 (file)
index 0000000..587ee30
--- /dev/null
@@ -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<Bed> 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<Sleeper> 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<String, String> 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<String, String> 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<String, String> parameters)
+            throws LoginException, ResponseFormatException, CommunicationException {
+        return cloudRequest(endpoint, parameters, null);
+    }
+
+    private String cloudRequest(String endpoint, @Nullable Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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 (file)
index 0000000..8116183
--- /dev/null
@@ -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<T> extends TemporalTypeAdapter<T> {
+
+    DateTimeTypeAdapter(Function<String, T> 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 (file)
index 0000000..655a3d5
--- /dev/null
@@ -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<Side>, JsonSerializer<Side> {
+
+    @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 (file)
index 0000000..5019bbf
--- /dev/null
@@ -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<SleepNumberRequest> {
+
+    @Override
+    public JsonElement serialize(SleepNumberRequest src, Type typeOfSrc, JsonSerializationContext context) {
+        // Sleep number must be >= 5 and <= 100, and be a multiple of 5
+        int sleepNumber = src.getSleepNumber();
+        sleepNumber = Math.min(100, sleepNumber);
+        sleepNumber = Math.max(5, sleepNumber);
+        sleepNumber = 5 * (int) (Math.round(sleepNumber / 5.0));
+
+        JsonObject obj = new JsonObject();
+        obj.addProperty("bedId", src.getBedId());
+        obj.addProperty("sleepNumber", sleepNumber);
+        obj.addProperty("side", src.getSide().equals(Side.LEFT) ? "L" : "R");
+        return obj;
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TemporalTypeAdapter.java
new file mode 100644 (file)
index 0000000..2503eb9
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.internal.api.impl.typeadapters;
+
+import java.io.IOException;
+import java.util.Objects;
+import java.util.function.Function;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import com.google.gson.stream.JsonWriter;
+
+/**
+ * Abstract type adapter for jsr310 date-time types.
+ *
+ * @author Christophe Bornet - Initial contribution
+ */
+@NonNullByDefault
+abstract class TemporalTypeAdapter<T> extends TypeAdapter<T> {
+
+    Function<String, T> parseFunction;
+
+    TemporalTypeAdapter(Function<String, T> parseFunction) {
+        Objects.requireNonNull(parseFunction);
+        this.parseFunction = parseFunction;
+    }
+
+    @Override
+    public void write(JsonWriter out, @Nullable T value) throws IOException {
+        if (value == null) {
+            out.nullValue();
+        } else {
+            out.value(value.toString());
+        }
+    }
+
+    @Override
+    public @Nullable T read(JsonReader in) throws IOException {
+        if (in.peek() == JsonToken.NULL) {
+            in.nextNull();
+            return null;
+        }
+        String temporalString = preProcess(in.nextString());
+        return parseFunction.apply(temporalString);
+    }
+
+    public String preProcess(String in) {
+        return in;
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java b/bundles/org.openhab.binding.sleepiq/src/main/java/org/openhab/binding/sleepiq/internal/api/impl/typeadapters/TimeSinceTypeAdapter.java
new file mode 100644 (file)
index 0000000..6377fec
--- /dev/null
@@ -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<TimeSince> {
+    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 (file)
index 0000000..bb3e64b
--- /dev/null
@@ -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<ZonedDateTime> {
+
+    public ZonedDateTimeTypeAdapter() {
+        super(ZonedDateTime::parse);
+    }
+}
index 3d8fcd30deb367c3920daa44604c8f61172daf37..96e09ea316104b08a23129ce3c5d039a401f7e23 100644 (file)
  */
 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;
 }
index b9b14a7abe0c5ca1ffd92b1d9f8aa8a09d0c945b..e60525e220bc2977b4bc497699044256f194a049 100644 (file)
 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<Bed> beds = cloudHandler.getBeds();
+        if (beds != null) {
+            for (Bed bed : beds) {
+                // only dual chamber beds are supported currently
+                if (!bed.isDualSleep()) {
+                    logger.info("Found a bed that is not dual chamber - currently unsupported");
+                    continue;
+                }
 
-        for (Bed bed : cloudHandler.getBeds()) {
-            // only dual chamber beds are supported currently
-            if (!bed.isDualSleep()) {
-                logger.info("Found a bed that is not dual chamber - currently unsupported");
-                continue;
-            }
-
-            ThingUID bridgeUID = cloudHandler.getThing().getUID();
-            ThingUID thingUID = new ThingUID(SleepIQBindingConstants.THING_TYPE_DUAL_BED, bridgeUID,
-                    bed.getMacAddress());
-
-            // thing already exists
-            if (cloudHandler.getThing().getThing(thingUID) != null) {
-                continue;
-            }
+                ThingUID bridgeUID = cloudHandler.getThing().getUID();
+                ThingUID thingUID = new ThingUID(SleepIQBindingConstants.THING_TYPE_DUAL_BED, bridgeUID,
+                        bed.getMacAddress());
 
-            logger.debug("New bed found with MAC address {}", bed.getMacAddress());
+                // thing already exists
+                if (cloudHandler.getThing().getThing(thingUID) != null) {
+                    continue;
+                }
 
-            @SuppressWarnings({ "unchecked", "rawtypes" })
-            Map<String, Object> properties = (Map) cloudHandler.updateProperties(bed, new HashMap<>());
-            properties.put(SleepIQBedConfiguration.BED_ID, bed.getBedId());
+                logger.debug("New bed found with MAC address {}", bed.getMacAddress());
+                @SuppressWarnings({ "unchecked", "rawtypes" })
+                Map<String, Object> properties = (Map) cloudHandler.updateProperties(bed, new HashMap<>());
+                properties.put(SleepIQBedConfiguration.BED_ID, bed.getBedId());
 
-            DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
-                    .withBridge(bridgeUID).withLabel(bed.getName() + " - " + bed.getModel()).build();
-            thingDiscovered(discoveryResult);
+                DiscoveryResult discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
+                        .withBridge(bridgeUID).withLabel(bed.getName() + " - " + bed.getModel()).build();
+                thingDiscovered(discoveryResult);
+            }
         }
-
         stopScan();
     }
 }
index 7ecc3365503566024dcc631e76d758fa4350a52e..aa9c3b0734179671a4744d0a68248b871ec04ef3 100644 (file)
  */
 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);
 }
index 052553692f9be25c0b14df023870742456ba492d..30f316084476a52842a56ab7fe4ac1b09df28cf8 100644 (file)
@@ -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<ThingTypeUID> SUPPORTED_THING_TYPE_UIDS = Collections.singleton(THING_TYPE_CLOUD);
 
+    private static final int SLEEPER_POLLING_INTERVAL_HOURS = 12;
+
     private final Logger logger = LoggerFactory.getLogger(SleepIQCloudHandler.class);
 
-    private final List<BedStatusListener> bedStatusListeners = new CopyOnWriteArrayList<>();
+    private final HttpClient httpClient;
 
-    private ExpiringCache<FamilyStatus> statusCache;
+    private final List<BedStatusListener> bedStatusListeners = new CopyOnWriteArrayList<>();
 
-    private ScheduledFuture<?> pollingJob;
+    private @Nullable ScheduledFuture<?> statusPollingJob;
+    private @Nullable ScheduledFuture<?> sleeperPollingJob;
 
-    private SleepIQ cloud;
+    private @Nullable SleepIQ cloud;
 
-    private ClientBuilder clientBuilder;
+    private @Nullable List<Sleeper> sleepers;
 
-    public SleepIQCloudHandler(final Bridge bridge, ClientBuilder clientBuilder) {
+    public SleepIQCloudHandler(final Bridge bridge, HttpClient httpClient) {
         super(bridge);
-        this.clientBuilder = clientBuilder;
+        this.httpClient = httpClient;
     }
 
     @Override
     public void initialize() {
-        try {
-            logger.debug("Configuring bed status cache");
-            statusCache = new ExpiringCache<>(TimeUnit.SECONDS.toMillis(getPollingInterval() / 2),
-                    () -> cloud.getFamilyStatus());
-
-            createCloudConnection();
-
-            logger.debug("Setting SleepIQ cloud online");
-            updateListenerManagement();
-            updateStatus(ThingStatus.ONLINE);
-        } catch (UnauthorizedException e) {
-            logger.debug("SleepIQ cloud authentication failed", e);
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid SleepIQ credentials");
-        } catch (LoginException e) {
-            logger.debug("SleepIQ cloud login failed", e);
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "SleepIQ cloud login failed: " + e.getMessage());
-        } catch (Exception e) {
-            logger.debug("Unexpected error while communicating with SleepIQ cloud", e);
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "Unable to connect to SleepIQ cloud: " + e.getMessage());
-        }
-    }
-
-    /**
-     * Create a new SleepIQ cloud service connection. If a connection already exists, it will be lost.
-     *
-     * @param clientBuilder2
-     *
-     * @throws LoginException if there is an error while authenticating to the service
-     */
-    private void createCloudConnection() throws LoginException {
-        logger.debug("Reading SleepIQ cloud binding configuration");
-        SleepIQCloudConfiguration bindingConfig = getConfigAs(SleepIQCloudConfiguration.class);
-
-        logger.debug("Creating SleepIQ client");
-        Configuration cloudConfig = new Configuration().withUsername(bindingConfig.username)
-                .withPassword(bindingConfig.password).withLogging(logger.isDebugEnabled());
-        cloud = SleepIQ.create(cloudConfig, clientBuilder);
-
-        logger.debug("Authenticating at the SleepIQ cloud service");
-        cloud.login();
-
-        logger.info("Successfully authenticated at the SleepIQ cloud service");
+        scheduler.execute(() -> {
+            try {
+                createCloudConnection();
+                updateListenerManagement();
+                updateStatus(ThingStatus.ONLINE);
+            } catch (UnauthorizedException e) {
+                logger.debug("CloudHandler: SleepIQ cloud authentication failed", e);
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid SleepIQ credentials");
+            } catch (LoginException e) {
+                logger.debug("CloudHandler: SleepIQ cloud login failed", e);
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
+                        "SleepIQ cloud login failed: " + e.getMessage());
+            }
+        });
     }
 
     @Override
     public synchronized void dispose() {
-        logger.debug("Disposing SleepIQ cloud handler");
-
-        if (pollingJob != null && !pollingJob.isCancelled()) {
-            pollingJob.cancel(true);
-            pollingJob = null;
+        stopSleeperPollingJob();
+        stopStatusPollingJob();
+        if (cloud != null) {
+            cloud.shutdown();
         }
     }
 
-    /**
-     * Start or stop a background polling job to look for bed status updates based on whether or not there are any
-     * listeners to notify.
-     */
-    private synchronized void updateListenerManagement() {
-        if (!bedStatusListeners.isEmpty() && (pollingJob == null || pollingJob.isCancelled())) {
-            int pollingInterval = getPollingInterval();
-            pollingJob = scheduler.scheduleWithFixedDelay(this::refreshBedStatus, pollingInterval, pollingInterval,
-                    TimeUnit.SECONDS);
-        } else if (bedStatusListeners.isEmpty() && pollingJob != null && !pollingJob.isCancelled()) {
-            pollingJob.cancel(true);
-            pollingJob = null;
-        }
+    @Override
+    public void handleCommand(final ChannelUID channelUID, final Command command) {
+        // cloud handler has no channels
     }
 
     /**
-     * Retrieve the polling interval for updating bed status.
+     * Validate the config from openHAB
      *
-     * @return the polling interval in seconds
+     * @return validity status of config parameters
      */
-    private int getPollingInterval() {
-        return getConfigAs(SleepIQCloudConfiguration.class).pollingInterval;
-    }
-
-    /**
-     * Retrieve the latest status on all beds and update all registered listeners.
-     */
-    public void refreshBedStatus() {
-        try {
-            FamilyStatus status = statusCache.getValue();
-            updateStatus(ThingStatus.ONLINE);
-
-            for (BedStatus bedStatus : status.getBeds()) {
-                bedStatusListeners.stream().forEach(l -> l.onBedStateChanged(cloud, bedStatus));
-            }
-        } catch (Exception e) {
-            logger.debug("Unexpected error while communicating with SleepIQ cloud", e);
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
-                    "Unable to connect to SleepIQ cloud: " + e.getMessage());
+    @Override
+    public Collection<ConfigStatusMessage> getConfigStatus() {
+        Collection<ConfigStatusMessage> configStatusMessages = new ArrayList<>();
+        SleepIQCloudConfiguration config = getConfigAs(SleepIQCloudConfiguration.class);
+        String username = config.username;
+        String password = config.password;
+        if (username.isBlank()) {
+            configStatusMessages.add(ConfigStatusMessage.Builder.error(USERNAME)
+                    .withMessageKeySuffix(SleepIQConfigStatusMessage.USERNAME_MISSING).withArguments(USERNAME).build());
         }
+        if (password.isBlank()) {
+            configStatusMessages.add(ConfigStatusMessage.Builder.error(PASSWORD)
+                    .withMessageKeySuffix(SleepIQConfigStatusMessage.PASSWORD_MISSING).withArguments(PASSWORD).build());
+        }
+        return configStatusMessages;
     }
 
     /**
@@ -182,13 +145,12 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
      * @param listener the listener to register
      */
     public void registerBedStatusListener(final BedStatusListener listener) {
-        if (listener == null) {
-            return;
-        }
-
         bedStatusListeners.add(listener);
-        refreshBedStatus();
-        updateListenerManagement();
+        scheduler.execute(() -> {
+            refreshSleepers();
+            refreshBedStatus();
+            updateListenerManagement();
+        });
     }
 
     /**
@@ -203,59 +165,101 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
         if (result) {
             updateListenerManagement();
         }
-
         return result;
     }
 
-    @Override
-    public void handleCommand(final ChannelUID channelUID, final Command command) {
-        // cloud handler has no channels
+    /**
+     * Get a list of all beds registered to the cloud service account.
+     *
+     * @return the list of beds or null if unable to get list
+     */
+    public @Nullable List<Bed> getBeds() {
+        try {
+            return cloud.getBeds();
+        } catch (SleepIQException e) {
+            logger.debug("CloudHandler: Exception getting list of beds", e);
+            return null;
+        }
     }
 
-    @Override
-    public Collection<ConfigStatusMessage> getConfigStatus() {
-        Collection<ConfigStatusMessage> configStatusMessages = new ArrayList<>();
-
-        SleepIQCloudConfiguration config = getConfigAs(SleepIQCloudConfiguration.class);
-        String username = config.username;
-        String password = config.password;
-
-        if (username.isEmpty()) {
-            configStatusMessages.add(ConfigStatusMessage.Builder.error(USERNAME)
-                    .withMessageKeySuffix(SleepIQConfigStatusMessage.USERNAME_MISSING).withArguments(USERNAME).build());
+    /**
+     * Get the bed corresponding to the given bed id
+     *
+     * @param bedId the bed identifier
+     * @return the identified {@link Bed} or <code>null</code> if no such bed exists
+     */
+    public @Nullable Bed getBed(final @Nullable String bedId) {
+        logger.debug("CloudHandler: Get bed object for bedId={}", bedId);
+        if (bedId == null) {
+            return null;
         }
-
-        if (password.isEmpty()) {
-            configStatusMessages.add(ConfigStatusMessage.Builder.error(PASSWORD)
-                    .withMessageKeySuffix(SleepIQConfigStatusMessage.PASSWORD_MISSING).withArguments(PASSWORD).build());
+        List<Bed> beds = getBeds();
+        if (beds != null) {
+            for (Bed bed : beds) {
+                if (bedId.equals(bed.getBedId())) {
+                    return bed;
+                }
+            }
         }
-
-        return configStatusMessages;
+        return null;
     }
 
     /**
-     * Get a list of all beds registered to the cloud service account.
+     * Get the sleeper associated with the bedId and side
      *
-     * @return the list of beds (never <code>null</code>)
+     * @param bedId the bed identifier
+     * @param side the side of the bed
+     * @return the sleeper or null if sleeper not found
      */
-    public List<Bed> getBeds() {
-        return cloud.getBeds();
+    public @Nullable Sleeper getSleeper(@Nullable String bedId, Side side) {
+        logger.debug("CloudHandler: Get sleeper object for bedId={}, side={}", bedId, side);
+        if (bedId == null) {
+            return null;
+        }
+        List<Sleeper> localSleepers = sleepers;
+        if (localSleepers != null) {
+            for (Sleeper sleeper : localSleepers) {
+                if (bedId.equals(sleeper.getBedId()) && side.equals(sleeper.getSide())) {
+                    return sleeper;
+                }
+            }
+        }
+        return null;
     }
 
     /**
-     * Get the {@link Bed} corresponding to the given identifier.
+     * Set the sleep number of the specified chamber
      *
      * @param bedId the bed identifier
-     * @return the identified {@link Bed} or <code>null</code> if no such bed exists
+     * @param sleepNumber the sleep number multiple of 5 between 5 and 100
+     * @param side the chamber to set
      */
-    public Bed getBed(final String bedId) {
-        for (Bed bed : getBeds()) {
-            if (bedId.equals(bed.getBedId())) {
-                return bed;
-            }
+    public void setSleepNumber(@Nullable String bedId, Side side, int sleepNumber) {
+        if (bedId == null) {
+            return;
         }
+        try {
+            cloud.setSleepNumber(bedId, side, sleepNumber);
+        } catch (SleepIQException e) {
+            logger.debug("CloudHandler: Exception setting sleep number of bed={}", bedId, e);
+        }
+    }
 
-        return null;
+    /**
+     * Set the pause mode of the specified bed
+     *
+     * @param bedId the bed identifier
+     * @param mode turn pause mode on or off
+     */
+    public void setPauseMode(@Nullable String bedId, boolean mode) {
+        if (bedId == null) {
+            return;
+        }
+        try {
+            cloud.setPauseMode(bedId, mode);
+        } catch (SleepIQException e) {
+            logger.debug("CloudHandler: Exception setting pause mode of bed={}", bedId, e);
+        }
     }
 
     /**
@@ -266,8 +270,9 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
      * @param properties the properties to update (this may be <code>null</code>)
      * @return the given map (or a new map if no map was given) with updated/set properties from the supplied bed
      */
-    public Map<String, String> updateProperties(final Bed bed, Map<String, String> properties) {
+    public Map<String, String> updateProperties(final @Nullable Bed bed, Map<String, String> 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<Sleeper> 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;
+        }
+    }
 }
index 00a3c0046be2c462996ef78a20e33e14891c59a8..b20b6884f086581bc6cf1d49e83774187034cfd0 100644 (file)
@@ -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<ThingTypeUID> SUPPORTED_THING_TYPE_UIDS = Collections.singleton(THING_TYPE_DUAL_BED);
 
+    private static final long GET_SLEEP_DATA_DELAY_MINUTES = 5;
+
     private final Logger logger = LoggerFactory.getLogger(SleepIQDualBedHandler.class);
 
-    private volatile String bedId;
+    private volatile @Nullable String bedId;
+
+    private @Nullable Sleeper sleeperLeft;
+    private @Nullable Sleeper sleeperRight;
+
+    private @Nullable BedStatus previousStatus;
 
     public SleepIQDualBedHandler(final Thing thing) {
         super(thing);
@@ -58,80 +73,113 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
 
     @Override
     public void initialize() {
-        logger.debug("Verifying SleepIQ cloud/bridge configuration");
-
         Bridge bridge = getBridge();
         if (bridge == null) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
                     "No cloud service bridge has been configured");
             return;
         }
-
         ThingHandler handler = bridge.getHandler();
         if (!(handler instanceof SleepIQCloudHandler)) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect bridge thing found");
             return;
         }
-
-        logger.debug("Reading SleepIQ bed binding configuration");
         bedId = getConfigAs(SleepIQBedConfiguration.class).bedId;
+        if (bedId == null) {
+            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                    "Bed id not found in configuration");
+            return;
+        }
 
-        logger.debug("Registering SleepIQ bed status listener");
+        logger.debug("BedHandler: Registering SleepIQ bed status listener for bedId={}", bedId);
         SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) handler;
         cloudHandler.registerBedStatusListener(this);
 
         if (ThingStatus.ONLINE != bridge.getStatus()) {
             updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
         } else {
-            updateProperties();
             updateStatus(ThingStatus.ONLINE);
+            scheduler.execute(() -> {
+                updateProperties();
+            });
+        }
+    }
+
+    @Override
+    public void dispose() {
+        SleepIQCloudHandler cloudHandler = getCloudHandler();
+        if (cloudHandler != null) {
+            cloudHandler.unregisterBedStatusListener(this);
         }
+        bedId = null;
     }
 
     @Override
     public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
         super.bridgeStatusChanged(bridgeStatusInfo);
-
         if (bridgeStatusInfo.getStatus() == ThingStatus.ONLINE) {
             updateProperties();
         }
     }
 
-    private void updateProperties() {
-        logger.debug("Updating SleepIQ bed properties for bed {}", bedId);
-
-        SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) getBridge().getHandler();
-        Bed bed = cloudHandler.getBed(bedId);
-        if (bed == null) {
-            updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "No bed found with ID " + bedId);
+    @Override
+    public void handleCommand(final ChannelUID channelUID, final Command command) {
+        if (command == RefreshType.REFRESH) {
+            // Channels will be refreshed automatically by cloud handler
             return;
         }
 
-        updateProperties(cloudHandler.updateProperties(bed, editProperties()));
+        switch (channelUID.getId()) {
+            case CHANNEL_LEFT_SLEEP_NUMBER:
+            case CHANNEL_RIGHT_SLEEP_NUMBER:
+                if (command instanceof DecimalType) {
+                    Side side = Side.convertFromGroup(channelUID.getGroupId());
+                    logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side);
+                    SleepIQCloudHandler cloudHandler = getCloudHandler();
+                    if (cloudHandler != null) {
+                        cloudHandler.setSleepNumber(bedId, side, ((DecimalType) command).intValue());
+                    }
+                }
+                break;
+            case CHANNEL_LEFT_PRIVACY_MODE:
+            case CHANNEL_RIGHT_PRIVACY_MODE:
+                if (command instanceof OnOffType) {
+                    Side side = Side.convertFromGroup(channelUID.getGroupId());
+                    logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side);
+                    SleepIQCloudHandler cloudHandler = getCloudHandler();
+                    if (cloudHandler != null) {
+                        cloudHandler.setPauseMode(bedId, command == OnOffType.ON ? true : false);
+                    }
+                }
+                break;
+        }
     }
 
     @Override
-    public void dispose() {
-        logger.debug("Disposing bed handler for bed {}", bedId);
-
-        Bridge bridge = getBridge();
-        if (bridge != null) {
-            BridgeHandler bridgeHandler = bridge.getHandler();
-            if (bridgeHandler instanceof SleepIQCloudHandler) {
-                ((SleepIQCloudHandler) bridgeHandler).unregisterBedStatusListener(this);
-            }
+    public void onSleeperChanged(final @Nullable Sleeper sleeper) {
+        if (sleeper == null || !sleeper.getBedId().equals(bedId)) {
+            return;
         }
+        logger.debug("BedHandler: Updating sleeper information channels for bed={}, side={}", bedId, sleeper.getSide());
 
-        bedId = null;
+        if (sleeper.getSide().equals(Side.LEFT)) {
+            sleeperLeft = sleeper;
+            updateState(CHANNEL_LEFT_FIRST_NAME, new StringType(sleeper.getFirstName()));
+            updateState(CHANNEL_LEFT_SLEEP_GOAL_MINUTES, new QuantityType<>(sleeper.getSleepGoal(), Units.MINUTE));
+        } else {
+            sleeperRight = sleeper;
+            updateState(CHANNEL_RIGHT_FIRST_NAME, new StringType(sleeper.getFirstName()));
+            updateState(CHANNEL_RIGHT_SLEEP_GOAL_MINUTES, new QuantityType<>(sleeper.getSleepGoal(), Units.MINUTE));
+        }
     }
 
     @Override
-    public void onBedStateChanged(final SleepIQ cloud, final BedStatus status) {
-        if (!status.getBedId().equals(bedId)) {
+    public void onBedStateChanged(final @Nullable BedStatus status) {
+        if (status == null || !status.getBedId().equals(bedId)) {
             return;
         }
+        logger.debug("BedHandler: Updating bed status channels for bed {}", bedId);
 
-        logger.debug("Updating left side status for bed {}", bedId);
         BedSideStatus left = status.getLeftSide();
         updateState(CHANNEL_LEFT_IN_BED, left.isInBed() ? OnOffType.ON : OnOffType.OFF);
         updateState(CHANNEL_LEFT_SLEEP_NUMBER, new DecimalType(left.getSleepNumber()));
@@ -139,8 +187,10 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
         updateState(CHANNEL_LEFT_LAST_LINK, new StringType(left.getLastLink().toString()));
         updateState(CHANNEL_LEFT_ALERT_ID, new DecimalType(left.getAlertId()));
         updateState(CHANNEL_LEFT_ALERT_DETAILED_MESSAGE, new StringType(left.getAlertDetailedMessage()));
+        if (previousStatus != null) {
+            updateSleepDataChannels(previousStatus.getLeftSide(), left, sleeperLeft);
+        }
 
-        logger.debug("Updating right side status for bed {}", bedId);
         BedSideStatus right = status.getRightSide();
         updateState(CHANNEL_RIGHT_IN_BED, right.isInBed() ? OnOffType.ON : OnOffType.OFF);
         updateState(CHANNEL_RIGHT_SLEEP_NUMBER, new DecimalType(right.getSleepNumber()));
@@ -148,15 +198,123 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
         updateState(CHANNEL_RIGHT_LAST_LINK, new StringType(right.getLastLink().toString()));
         updateState(CHANNEL_RIGHT_ALERT_ID, new DecimalType(right.getAlertId()));
         updateState(CHANNEL_RIGHT_ALERT_DETAILED_MESSAGE, new StringType(right.getAlertDetailedMessage()));
+        if (previousStatus != null) {
+            updateSleepDataChannels(previousStatus.getRightSide(), right, sleeperRight);
+        }
+
+        previousStatus = status;
     }
 
-    @Override
-    public void handleCommand(final ChannelUID channelUID, final Command command) {
-        // all channels are read-only
+    private void updateSleepDataChannels(BedSideStatus previousSideStatus, BedSideStatus currentSideStatus,
+            @Nullable Sleeper sleeper) {
+        if (sleeper == null) {
+            logger.debug("BedHandler: Can't update sleep data channels because sleeper is null");
+            return;
+        }
+        if (previousSideStatus.isInBed() && !currentSideStatus.isInBed()) {
+            logger.debug("BedHandler: Bed status changed from IN BED to OUT OF BED for {}, side {}", bedId,
+                    sleeper.getSide());
+            scheduler.schedule(() -> {
+                updateDailySleepDataChannels(sleeper);
+                updateMonthlySleepDataChannels(sleeper);
+            }, GET_SLEEP_DATA_DELAY_MINUTES, TimeUnit.MINUTES);
+        }
+    }
 
-        if (command == RefreshType.REFRESH) {
-            SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) getBridge().getHandler();
-            cloudHandler.refreshBedStatus();
+    public void updateDailySleepDataChannels(final @Nullable Sleeper sleeper) {
+        SleepIQCloudHandler cloudHandler = getCloudHandler();
+        if (cloudHandler == null || sleeper == null) {
+            return;
+        }
+        SleepDataResponse sleepData = cloudHandler.getDailySleepData(sleeper.getSleeperId());
+        if (sleepData == null) {
+            logger.debug("BedHandler: Received no daily sleep data for bedId={}, sleeperId={}", sleeper.getBedId(),
+                    sleeper.getSleeperId());
+            return;
+        }
+
+        logger.debug("BedHandler: UPDATING DAILY SLEEP DATA CHANNELS for bedId={}, sleeperId={}", sleeper.getBedId(),
+                sleeper.getSleeperId());
+        if (sleepData.getSleepDataDays() == null || sleepData.getSleepDataDays().size() != 1) {
+            if (sleeper.getSide().equals(Side.LEFT)) {
+                updateState(CHANNEL_LEFT_TODAY_SLEEP_IQ, UnDefType.UNDEF);
+                updateState(CHANNEL_LEFT_TODAY_AVG_HEART_RATE, UnDefType.UNDEF);
+                updateState(CHANNEL_LEFT_TODAY_AVG_RESPIRATION_RATE, UnDefType.UNDEF);
+                updateState(CHANNEL_LEFT_TODAY_MESSAGE, UnDefType.UNDEF);
+                updateState(CHANNEL_LEFT_TODAY_SLEEP_DURATION_SECONDS, UnDefType.UNDEF);
+            } else {
+                updateState(CHANNEL_RIGHT_TODAY_SLEEP_IQ, UnDefType.UNDEF);
+                updateState(CHANNEL_RIGHT_TODAY_AVG_HEART_RATE, UnDefType.UNDEF);
+                updateState(CHANNEL_RIGHT_TODAY_AVG_RESPIRATION_RATE, UnDefType.UNDEF);
+                updateState(CHANNEL_RIGHT_TODAY_MESSAGE, UnDefType.UNDEF);
+                updateState(CHANNEL_RIGHT_TODAY_SLEEP_DURATION_SECONDS, UnDefType.UNDEF);
+            }
+            return;
+        } else if (sleeper.getSide().equals(Side.LEFT)) {
+            updateState(CHANNEL_LEFT_TODAY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ()));
+            updateState(CHANNEL_LEFT_TODAY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate()));
+            updateState(CHANNEL_LEFT_TODAY_AVG_RESPIRATION_RATE,
+                    new DecimalType(sleepData.getAverageRespirationRate()));
+            updateState(CHANNEL_LEFT_TODAY_MESSAGE, new StringType(sleepData.getSleepDataDays().get(0).getMessage()));
+            updateState(CHANNEL_LEFT_TODAY_SLEEP_DURATION_SECONDS,
+                    new QuantityType<>(sleepData.getTotalSleepSessionTime(), Units.SECOND));
+        } else if (sleeper.getSide().equals(Side.RIGHT)) {
+            updateState(CHANNEL_RIGHT_TODAY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ()));
+            updateState(CHANNEL_RIGHT_TODAY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate()));
+            updateState(CHANNEL_RIGHT_TODAY_AVG_RESPIRATION_RATE,
+                    new DecimalType(sleepData.getAverageRespirationRate()));
+            updateState(CHANNEL_RIGHT_TODAY_MESSAGE, new StringType(sleepData.getSleepDataDays().get(0).getMessage()));
+            updateState(CHANNEL_RIGHT_TODAY_SLEEP_DURATION_SECONDS,
+                    new QuantityType<>(sleepData.getTotalSleepSessionTime(), Units.SECOND));
+        }
+    }
+
+    public void updateMonthlySleepDataChannels(final @Nullable Sleeper sleeper) {
+        SleepIQCloudHandler cloudHandler = getCloudHandler();
+        if (cloudHandler == null || sleeper == null) {
+            return;
+        }
+        SleepDataResponse sleepData = cloudHandler.getMonthlySleepData(sleeper.getSleeperId());
+        if (sleepData == null) {
+            logger.debug("BedHandler: Received no monthly sleep data for bedId={}, sleeperId={}", sleeper.getBedId(),
+                    sleeper.getSleeperId());
+            return;
+        }
+
+        logger.debug("BedHandler: UPDATING MONTHLY SLEEP DATA CHANNELS for bedId={}, sleeperId={}", sleeper.getBedId(),
+                sleeper.getSleeperId());
+        if (sleeper.getSide().equals(Side.LEFT)) {
+            updateState(CHANNEL_LEFT_MONTHLY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ()));
+            updateState(CHANNEL_LEFT_MONTHLY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate()));
+            updateState(CHANNEL_LEFT_MONTHLY_AVG_RESPIRATION_RATE,
+                    new DecimalType(sleepData.getAverageRespirationRate()));
+        } else {
+            updateState(CHANNEL_RIGHT_MONTHLY_SLEEP_IQ, new DecimalType(sleepData.getAverageSleepIQ()));
+            updateState(CHANNEL_RIGHT_MONTHLY_AVG_HEART_RATE, new DecimalType(sleepData.getAverageHeartRate()));
+            updateState(CHANNEL_RIGHT_MONTHLY_AVG_RESPIRATION_RATE,
+                    new DecimalType(sleepData.getAverageRespirationRate()));
+        }
+    }
+
+    private void updateProperties() {
+        logger.debug("BedHandler: Updating bed properties for bedId={}", bedId);
+        SleepIQCloudHandler cloudHandler = getCloudHandler();
+        if (cloudHandler != null) {
+            Bed bed = cloudHandler.getBed(bedId);
+            if (bed == null) {
+                updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
+                        "No bed found with ID " + bedId);
+                return;
+            }
+            updateProperties(cloudHandler.updateProperties(bed, editProperties()));
+        }
+    }
+
+    private @Nullable SleepIQCloudHandler getCloudHandler() {
+        Bridge bridge = getBridge();
+        if (bridge != null) {
+            return (SleepIQCloudHandler) bridge.getHandler();
         }
+        return null;
     }
 }
index ebef3f07c6f143bf03f3ce34499ef4e9c1bbfb35..2c91eac6301a2e1f1607c91dbbf6d78ecec60eef 100644 (file)
                                <description>Username of a registered SleepIQ account owner</description>
                        </parameter>
                        <parameter name="password" type="text" required="false">
-                               <context>password</context>
                                <label>Password</label>
                                <description>Password of a registered SleepIQ account owner</description>
+                               <context>password</context>
                        </parameter>
                        <parameter name="pollingInterval" type="integer" min="30" step="30" required="true">
                                <label>Polling Interval</label>
                                <description>Seconds between fetching values from the cloud service</description>
-                               <default>60</default>
+                               <default>120</default>
                        </parameter>
                </config-description>
        </bridge-type>
                        <channel id="lastLink" typeId="lastLinkType"/>
                        <channel id="alertId" typeId="alertIdType"/>
                        <channel id="alertDetailedMessage" typeId="alertDetailedMessageType"/>
+                       <channel id="firstName" typeId="firstNameType"/>
+                       <channel id="sleepGoalMinutes" typeId="sleepGoalMinutesType"/>
+                       <channel id="privacyMode" typeId="privacyMode"/>
+                       <channel id="todaySleepIQ" typeId="todaySleepIQType"/>
+                       <channel id="todayAverageHeartRate" typeId="todayAverageHeartRateType"/>
+                       <channel id="todayAverageRespirationRate" typeId="todayAverageRespirationRateType"/>
+                       <channel id="todayMessage" typeId="todayMessageType"/>
+                       <channel id="todaySleepDurationSeconds" typeId="todaySleepDurationSecondsType"/>
+                       <channel id="monthlySleepIQ" typeId="monthlySleepIQType"/>
+                       <channel id="monthlyAverageHeartRate" typeId="monthlyAverageHeartRateType"/>
+                       <channel id="monthlyAverageRespirationRate" typeId="monthlyAverageRespirationRateType"/>
                </channels>
        </channel-group-type>
 
                <item-type>Number</item-type>
                <label>Sleep Number</label>
                <description>The Sleep Number setting of the chamber</description>
-               <state readOnly="true"/>
+               <state readOnly="false" min="5" max="100" step="5" pattern="%d"/>
        </channel-type>
        <channel-type id="pressureType">
                <item-type>Number</item-type>
                <description>A detailed message describing an alert condition with the chamber</description>
                <state readOnly="true"/>
        </channel-type>
+       <channel-type id="firstNameType">
+               <item-type>String</item-type>
+               <label>First Name</label>
+               <description>The first name of the sleeper</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="sleepGoalMinutesType">
+               <item-type>Number:Time</item-type>
+               <label>Sleep Goal</label>
+               <description>The goal for the amount of sleep per night (in minutes)</description>
+               <state readOnly="true" pattern="%d %unit%"/>
+       </channel-type>
+       <channel-type id="privacyMode">
+               <item-type>Switch</item-type>
+               <label>Privacy Mode</label>
+               <description>Enable/disable privacy mode</description>
+               <state readOnly="false"/>
+       </channel-type>
+       <channel-type id="todaySleepIQType">
+               <item-type>Number</item-type>
+               <label>Today's Sleep IQ</label>
+               <description>The Sleep Quotient for today</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="todayAverageHeartRateType">
+               <item-type>Number</item-type>
+               <label>Today's Avg Heart Rate</label>
+               <description>The average heart rate for today</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="todayAverageRespirationRateType">
+               <item-type>Number</item-type>
+               <label>Today's Avg Respiration Rate</label>
+               <description>The average respiration rate for today</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="todayMessageType">
+               <item-type>String</item-type>
+               <label>Today's Message</label>
+               <description>The description of today's sleep quality</description>
+               <state readOnly="true"/>
+       </channel-type>
+       <channel-type id="todaySleepDurationSecondsType">
+               <item-type>Number:Time</item-type>
+               <label>Today's Sleep Duration</label>
+               <description>The total duration of sleep for today in seconds</description>
+               <state readOnly="true" pattern="%d %unit%"/>
+       </channel-type>
+       <channel-type id="monthlySleepIQType">
+               <item-type>Number</item-type>
+               <label>Monthly Sleep IQ</label>
+               <description>The overall Sleep Quotient for the past month</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="monthlyAverageHeartRateType">
+               <item-type>Number</item-type>
+               <label>Monthly Avg Heart Rate</label>
+               <description>The average heart rate for the past month</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
+       <channel-type id="monthlyAverageRespirationRateType">
+               <item-type>Number</item-type>
+               <label>Monthly Avg Respiration Rate</label>
+               <description>The average respiration rate for the past month</description>
+               <state readOnly="true" pattern="%d"/>
+       </channel-type>
 
 </thing:thing-descriptions>
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedSideStatusTest.java
new file mode 100644 (file)
index 0000000..8c51054
--- /dev/null
@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.FileReader;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.BedSideStatus;
+import org.openhab.binding.sleepiq.internal.api.dto.TimeSince;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link BedSideStatusTest} tests deserialization of a bed side status object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class BedSideStatusTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        BedSideStatus bedSideStatus = new BedSideStatus().withAlertDetailedMessage("No Alert").withAlertId(0L)
+                .withInBed(false).withLastLink(new TimeSince().withDuration(3, 5, 4, 38)).withPressure(573)
+                .withSleepNumber(55);
+        assertEquals(readJson("bed-side-status.json"), gson.toJson(bedSideStatus));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("bed-side-status.json"))) {
+            BedSideStatus bedSideStatus = gson.fromJson(reader, BedSideStatus.class);
+            assertEquals("No Alert", bedSideStatus.getAlertDetailedMessage());
+            assertEquals(Long.valueOf(0L), bedSideStatus.getAlertId());
+            assertFalse(bedSideStatus.isInBed());
+            assertEquals(new TimeSince().withDuration(3, 5, 4, 38), bedSideStatus.getLastLink());
+            assertEquals(Integer.valueOf(573), bedSideStatus.getPressure());
+            assertEquals(Integer.valueOf(55), bedSideStatus.getSleepNumber());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedStatusTest.java
new file mode 100644 (file)
index 0000000..83bbf81
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.FileReader;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.BedSideStatus;
+import org.openhab.binding.sleepiq.internal.api.dto.BedStatus;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link BedStatusText} tests deserialization of a bed status object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class BedStatusTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        BedStatus bedStatus = new BedStatus().withBedId("-9999999999999999999")
+                .withLeftSide(new BedSideStatus().withInBed(true)).withRightSide(new BedSideStatus().withInBed(false))
+                .withStatus(1L);
+        assertEquals(readJson("bed-status.json"), gson.toJson(bedStatus));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("bed-status.json"))) {
+            BedStatus bedStatus = gson.fromJson(reader, BedStatus.class);
+            assertEquals("-9999999999999999999", bedStatus.getBedId());
+            assertEquals(Long.valueOf(1L), bedStatus.getStatus());
+
+            BedSideStatus leftSide = bedStatus.getLeftSide();
+            assertNotNull(leftSide);
+            assertTrue(leftSide.isInBed());
+
+            BedSideStatus rightSide = bedStatus.getRightSide();
+            assertNotNull(rightSide);
+            assertFalse(rightSide.isInBed());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedTest.java
new file mode 100644 (file)
index 0000000..5bf26e0
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.FileReader;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.Bed;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link BedTest} tests deserialization of a bed object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class BedTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        Bed bed = new Bed().withAccountId("-8888888888888888888").withBase("MODULAR").withBedId("-9999999999999999999")
+                .withDualSleep(true).withKidsBed(false).withMacAddress("AABBCCDDEEFF").withModel("P5").withName("Bed")
+                .withPurchaseDate(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()))
+                .withReference("55555555555-5")
+                .withRegistrationDate(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()))
+                .withReturnRequestStatus(0L).withSerial("").withSize("QUEEN").withSku("QP5")
+                .withSleeperLeftId("-2222222222222222222").withSleeperRightId("-1111111111111111111").withStatus(1L)
+                .withTimezone("US/Pacific").withVersion("").withZipCode("90210");
+        assertEquals(readJson("bed.json"), gson.toJson(bed));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("bed.json"))) {
+            Bed bed = gson.fromJson(reader, Bed.class);
+            assertEquals("-8888888888888888888", bed.getAccountId());
+            assertEquals("MODULAR", bed.getBase());
+            assertEquals("-9999999999999999999", bed.getBedId());
+            assertEquals(true, bed.isDualSleep());
+            assertEquals(false, bed.isKidsBed());
+            assertEquals("AABBCCDDEEFF", bed.getMacAddress());
+            assertEquals("P5", bed.getModel());
+            assertEquals("Bed", bed.getName());
+            assertEquals(ZonedDateTime.of(2017, 2, 2, 0, 0, 1, 0, ZoneId.of("Z").normalized()), bed.getPurchaseDate());
+            assertEquals("55555555555-5", bed.getReference());
+            assertEquals(ZonedDateTime.of(2017, 2, 17, 2, 14, 10, 0, ZoneId.of("Z").normalized()),
+                    bed.getRegistrationDate());
+            assertEquals(Long.valueOf(0L), bed.getReturnRequestStatus());
+            assertEquals("", bed.getSerial());
+            assertEquals("QUEEN", bed.getSize());
+            assertEquals("QP5", bed.getSku());
+            assertEquals("-2222222222222222222", bed.getSleeperLeftId());
+            assertEquals("-1111111111111111111", bed.getSleeperRightId());
+            assertEquals(Long.valueOf(1L), bed.getStatus());
+            assertEquals("US/Pacific", bed.getTimezone());
+            assertEquals("", bed.getVersion());
+            assertEquals("90210", bed.getZipCode());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/BedsResponseTest.java
new file mode 100644 (file)
index 0000000..147613a
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.FileReader;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.Bed;
+import org.openhab.binding.sleepiq.internal.api.dto.BedsResponse;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link BedsResponseTest} tests deserialization of a beds response object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class BedsResponseTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        BedsResponse bedsResponse = new BedsResponse()
+                .withBeds(Arrays.asList(new Bed().withName("Bed1"), new Bed().withName("Bed2")));
+        assertEquals(readJson("beds-response.json"), gson.toJson(bedsResponse));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("beds-response.json"))) {
+            BedsResponse bedsResponse = gson.fromJson(reader, BedsResponse.class);
+
+            List<Bed> beds = bedsResponse.getBeds();
+            assertNotNull(beds);
+            assertEquals(2, beds.size());
+            assertEquals("Bed1", beds.get(0).getName());
+            assertEquals("Bed2", beds.get(1).getName());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/FamilyStatusTest.java
new file mode 100644 (file)
index 0000000..6dd01da
--- /dev/null
@@ -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<BedStatus> 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 (file)
index 0000000..438c05e
--- /dev/null
@@ -0,0 +1,52 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.FileReader;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.PauseModeResponse;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link PauseModeTest} tests deserialization of a pause mode object.
+ *
+ * @author Mark Hilbush - Initial contribution
+ */
+@NonNullByDefault
+public class PauseModeTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        PauseModeResponse pauseMode = new PauseModeResponse().withAccountId("-8888888888888888888")
+                .withBedId("-9999999999999999999").withPauseMode("off");
+        assertEquals(readJson("pause-mode.json"), gson.toJson(pauseMode));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("pause-mode.json"))) {
+            PauseModeResponse pauseMode = gson.fromJson(reader, PauseModeResponse.class);
+            assertEquals("-8888888888888888888", pauseMode.getAccountId());
+            assertEquals("-9999999999999999999", pauseMode.getBedId());
+            assertEquals("off", pauseMode.getPauseMode());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleeperTest.java
new file mode 100644 (file)
index 0000000..28cbabf
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.FileReader;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.Sleeper;
+import org.openhab.binding.sleepiq.internal.api.enums.Side;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link SleeperTest} tests deserialization of a sleeper object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class SleeperTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        Sleeper sleeper = new Sleeper().withAccountId("-5555555555555555555").withAccountOwner(true).withActive(true)
+                .withAvatar("").withBedId("-9999999999999999999").withBirthMonth(6).withBirthYear("1970")
+                .withChild(false).withDuration("").withEmail("alice@domain.com").withEmailValidated(true)
+                .withFirstName("Alice").withHeight(64).withLastLogin("2017-02-17 20:19:36 CST").withLicenseVersion(6L)
+                .withMale(false).withSide(Side.RIGHT).withSleeperId("-1111111111111111111").withSleepGoal(450)
+                .withTimezone("US/Pacific").withUsername("alice@domain.com").withWeight(110).withZipCode("90210");
+        assertEquals(readJson("sleeper.json"), gson.toJson(sleeper));
+    }
+
+    @Test
+    public void testSerializeLastLoginNull() throws Exception {
+        Sleeper sleeper = new Sleeper().withLastLogin("null");
+        assertEquals(readJson("sleeper-lastlogin-null.json"), gson.toJson(sleeper));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("sleeper.json"))) {
+            Sleeper sleeper = gson.fromJson(reader, Sleeper.class);
+            assertEquals("-5555555555555555555", sleeper.getAccountId());
+            assertEquals(true, sleeper.isAccountOwner());
+            assertEquals(true, sleeper.isActive());
+            assertEquals("", sleeper.getAvatar());
+            assertEquals("-9999999999999999999", sleeper.getBedId());
+            assertEquals(Integer.valueOf(6), sleeper.getBirthMonth());
+            assertEquals("1970", sleeper.getBirthYear());
+            assertEquals(false, sleeper.isChild());
+            assertEquals("", sleeper.getDuration());
+            assertEquals("alice@domain.com", sleeper.getEmail());
+            assertEquals(true, sleeper.isEmailValidated());
+            assertEquals("Alice", sleeper.getFirstName());
+            assertEquals(Integer.valueOf(64), sleeper.getHeight());
+            assertEquals("2017-02-17 20:19:36 CST", sleeper.getLastLogin());
+            assertEquals(Long.valueOf(6L), sleeper.getLicenseVersion());
+            assertEquals(false, sleeper.isMale());
+            assertEquals(Side.RIGHT, sleeper.getSide());
+            assertEquals("-1111111111111111111", sleeper.getSleeperId());
+            assertEquals(Integer.valueOf(450), sleeper.getSleepGoal());
+            assertEquals("US/Pacific", sleeper.getTimezone());
+            assertEquals("alice@domain.com", sleeper.getUsername());
+            assertEquals(Integer.valueOf(110), sleeper.getWeight());
+            assertEquals("90210", sleeper.getZipCode());
+        }
+    }
+
+    @Test
+    public void testDeserializeLastLoginNull() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("sleeper-lastlogin-null.json"))) {
+            Sleeper sleeper = gson.fromJson(reader, Sleeper.class);
+            assertEquals("null", sleeper.getLastLogin());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/SleepersResponseTest.java
new file mode 100644 (file)
index 0000000..6c86622
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.io.FileReader;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.api.test.AbstractTest;
+import org.openhab.binding.sleepiq.internal.api.dto.Sleeper;
+import org.openhab.binding.sleepiq.internal.api.dto.SleepersResponse;
+import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
+
+import com.google.gson.Gson;
+
+/**
+ * The {@link SleepersResponseTest} tests deserialization of a sleepers response object.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class SleepersResponseTest extends AbstractTest {
+    private static Gson gson = GsonGenerator.create(true);
+
+    @Test
+    public void testSerializeAllFields() throws Exception {
+        SleepersResponse sleepersResponse = new SleepersResponse()
+                .withSleepers(Arrays.asList(new Sleeper().withFirstName("Alice"), new Sleeper().withFirstName("Bob")));
+        assertEquals(readJson("sleepers-response.json"), gson.toJson(sleepersResponse));
+    }
+
+    @Test
+    public void testDeserializeAllFields() throws Exception {
+        try (FileReader reader = new FileReader(getTestDataFile("sleepers-response.json"))) {
+            SleepersResponse sleepersResponse = gson.fromJson(reader, SleepersResponse.class);
+
+            List<Sleeper> sleepers = sleepersResponse.getSleepers();
+            assertNotNull(sleepers);
+            assertEquals(2, sleepers.size());
+            assertEquals("Alice", sleepers.get(0).getFirstName());
+            assertEquals("Bob", sleepers.get(1).getFirstName());
+        }
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/model/TimeSinceTest.java
new file mode 100644 (file)
index 0000000..50f15d3
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.model;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.time.Duration;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.junit.jupiter.api.Test;
+import org.openhab.binding.sleepiq.internal.api.dto.TimeSince;
+
+/**
+ * The {@link TimeSinceText} tests TimeSince.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public class TimeSinceTest {
+    @Test
+    public void testWithDuration() {
+        assertEquals(new TimeSince().withDuration(0, 0, 0, 0).getDuration(),
+                new TimeSince().withDuration(Duration.parse("PT00H00M00S")).getDuration());
+        assertEquals(new TimeSince().withDuration(0, 2, 3, 4).getDuration(),
+                new TimeSince().withDuration(Duration.parse("PT02H03M04S")).getDuration());
+        assertEquals(new TimeSince().withDuration(0, 12, 34, 56).getDuration(),
+                new TimeSince().withDuration(Duration.parse("PT12H34M56S")).getDuration());
+        assertEquals(new TimeSince().withDuration(1, 2, 3, 4).getDuration(),
+                new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).getDuration());
+        assertEquals(new TimeSince().withDuration(12, 23, 34, 45).getDuration(),
+                new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).getDuration());
+    }
+
+    @Test
+    public void testToString() {
+        assertEquals("00:00:00", new TimeSince().withDuration(Duration.parse("PT00H00M00S")).toString());
+        assertEquals("02:03:04", new TimeSince().withDuration(Duration.parse("PT02H03M04S")).toString());
+        assertEquals("12:34:56", new TimeSince().withDuration(Duration.parse("PT12H34M56S")).toString());
+        assertEquals("1 d 02:03:04", new TimeSince().withDuration(Duration.parse("P1DT02H03M04S")).toString());
+        assertEquals("12 d 23:34:45", new TimeSince().withDuration(Duration.parse("P12DT23H34M45S")).toString());
+    }
+
+    @Test
+    public void testParse() {
+        assertEquals(Duration.parse("PT00H00M00S"), TimeSince.parse("00:00:00").getDuration());
+        assertEquals(Duration.parse("PT2H3M4S"), TimeSince.parse("02:03:04").getDuration());
+        assertEquals(Duration.parse("PT12H34M56S"), TimeSince.parse("12:34:56").getDuration());
+        assertEquals(Duration.parse("P1DT2H3M4S"), TimeSince.parse("1 d 02:03:04").getDuration());
+        assertEquals(Duration.parse("P12DT23H34M45S"), TimeSince.parse("12 d 23:34:45").getDuration());
+    }
+}
diff --git a/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java b/bundles/org.openhab.binding.sleepiq/src/test/java/org/openhab/binding/sleepiq/api/test/AbstractTest.java
new file mode 100644 (file)
index 0000000..d3b541a
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright (c) 2010-2023 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.binding.sleepiq.api.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+
+/**
+ * The {@link AbstractTest} tests deserialization of a sleepiq API objects.
+ *
+ * @author Gregory Moyer - Initial contribution
+ */
+@NonNullByDefault
+public abstract class AbstractTest {
+    private static final String RESOURCES_PATH = "src/test/resources/";
+
+    protected File getTestDataFile(String name) {
+        return getTestDataPath(name).toFile();
+    }
+
+    @SuppressWarnings("null")
+    protected Path getTestDataPath(String name) {
+        String packageName = this.getClass().getPackage().getName();
+
+        List<String> paths = new ArrayList<>();
+        paths.addAll(Arrays.asList(packageName.split("\\.")));
+        paths.add(name);
+
+        return Paths.get(RESOURCES_PATH, paths.toArray(new String[paths.size()]));
+    }
+
+    protected String readJson(String jsonFileName) throws IOException {
+        return String.join("\n", Files.readAllLines(getTestDataPath(jsonFileName)));
+    }
+}