mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[sleepiq] Add functionality to control the bed foundation (#14714)
* Add foundation functionality Signed-off-by: Mark Hilbush <mark@hilbush.com>
This commit is contained in:
parent
1983bc36f1
commit
0a3d9ece3c
@ -19,6 +19,9 @@ Currently, only dual-chamber beds are supported by this binding.
|
||||
|
||||
The SleepIQ cloud thing must be added manually with the username and password used to register with the service.
|
||||
After that, beds are discovered automatically by querying the service.
|
||||
If the bed has a foundation, it will be auto-discovered by the binding.
|
||||
If a foundation is discovered, the channels for controlling presets, position and outlets can be operated.
|
||||
The thing properties will show whether or not a foundation is installed.
|
||||
|
||||
## Binding Configuration
|
||||
|
||||
@ -72,7 +75,6 @@ All channels within this group are read-only, except for the sleepNumber and pri
|
||||
|-----------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------|
|
||||
| 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 |
|
||||
@ -91,6 +93,11 @@ All channels within this group are read-only, except for the sleepNumber and pri
|
||||
| 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 |
|
||||
| foundationPreset | Number | Sets the head and foot position to one of the 6 available presets (1-6) (foundation required) |
|
||||
| foundationPositionHead | Dimmer | Sets the head position (foundation required) |
|
||||
| foundationPositionFoot | Dimmer | Sets the foot position (foundation required) |
|
||||
| nightStandOutlet | Switch | Turn on/off the night stand outlet (foundation required) |
|
||||
| underBedLight | Switch | Turn on/off the under bed light (foundation required) |
|
||||
|
||||
## Items
|
||||
|
||||
@ -117,11 +124,15 @@ Number:Time MasterBR_SleepIQ_DailyRestless_Alice "Daily Sleep Restless [%.0f
|
||||
Number 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"}
|
||||
|
||||
Number MasterBR_SleepIQ_FoundationPreset_Alice "Foundation Preset [%d]" { channel="sleepiq:dualBed:1:master:left#foundationPreset"}
|
||||
Dimmer MasterBR_SleepIQ_FoundationHead_Alice "Head Position [%d]" { channel="sleepiq:dualBed:1:master:left#foundationPositionHead"}
|
||||
Dimmer MasterBR_SleepIQ_FoundationFoot_Alice "Foot Position [%d]" { channel="sleepiq:dualBed:1:master:left#foundationPositionFoot"}
|
||||
Switch MasterBR_SleepIQ_FoundationNightStand_Alice "Night Stand [%d]" { channel="sleepiq:dualBed:1:master:left#nightStandOutlet"}
|
||||
Switch MasterBR_SleepIQ_FoundationNightLight_Alice "Night Light [%d]" { channel="sleepiq:dualBed:1:master:left#nightLightOutlet"}
|
||||
|
||||
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 MasterBR_SleepIQ_SleepGoal_Bob "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" }
|
||||
@ -139,4 +150,9 @@ Number:Time MasterBR_SleepIQ_DailyRestless_Bob "Daily Sleep Restless [%.0f
|
||||
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"}
|
||||
Number MasterBR_SleepIQ_FoundationPreset_Bob "Foundation Preset [%d]" { channel="sleepiq:dualBed:1:master:right#foundationPreset"}
|
||||
Dimmer MasterBR_SleepIQ_FoundationHead_Bob "Head Position [%d]" { channel="sleepiq:dualBed:1:master:right#foundationPositionHead"}
|
||||
Dimmer MasterBR_SleepIQ_FoundationFoot_Bob "Foot Position [%d]" { channel="sleepiq:dualBed:1:master:right#foundationPositionFoot"}
|
||||
Switch MasterBR_SleepIQ_FoundationNightStand_Bob "Night Stand [%d]" { channel="sleepiq:dualBed:1:master:right#nightStandOutlet"}
|
||||
Switch MasterBR_SleepIQ_FoundationNightLight_Bob "Night Light [%d]" { channel="sleepiq:dualBed:1:master:right#nightLightOutlet"}
|
||||
```
|
||||
|
@ -97,6 +97,21 @@ public class SleepIQBindingConstants {
|
||||
public static final String CHANNEL_LEFT_MONTHLY_AVG_RESPIRATION_RATE = "left#monthlyAverageRespirationRate";
|
||||
public static final String CHANNEL_RIGHT_MONTHLY_AVG_RESPIRATION_RATE = "right#monthlyAverageRespirationRate";
|
||||
|
||||
public static final String CHANNEL_LEFT_FOUNDATION_PRESET = "left#foundationPreset";
|
||||
public static final String CHANNEL_RIGHT_FOUNDATION_PRESET = "right#foundationPreset";
|
||||
|
||||
public static final String CHANNEL_LEFT_POSITION_HEAD = "left#foundationPositionHead";
|
||||
public static final String CHANNEL_RIGHT_POSITION_HEAD = "right#foundationPositionHead";
|
||||
|
||||
public static final String CHANNEL_LEFT_POSITION_FOOT = "left#foundationPositionFoot";
|
||||
public static final String CHANNEL_RIGHT_POSITION_FOOT = "right#foundationPositionFoot";
|
||||
|
||||
public static final String CHANNEL_LEFT_NIGHT_STAND_OUTLET = "left#nightStandOutlet";
|
||||
public static final String CHANNEL_RIGHT_NIGHT_STAND_OUTLET = "right#nightStandOutlet";
|
||||
|
||||
public static final String CHANNEL_LEFT_UNDER_BED_LIGHT = "left#underBedLight";
|
||||
public static final String CHANNEL_RIGHT_UNDER_BED_LIGHT = "right#underBedLight";
|
||||
|
||||
// List of non-standard Properties
|
||||
public static final String PROPERTY_BASE = "base";
|
||||
public static final String PROPERTY_KIDS_BED = "kidsBed";
|
||||
@ -105,4 +120,11 @@ 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";
|
||||
public static final String PROPERTY_FOUNDATION = "foundation";
|
||||
public static final String PROPERTY_FOUNDATION_IS_BOARD_AS_SINGLE = "foundationIsBoardAsSingle";
|
||||
public static final String PROPERTY_FOUNDATION_HAS_MASSAGE_AND_LIGHT = "foundationHasMasssageAndLight";
|
||||
public static final String PROPERTY_FOUNDATION_HAS_FOOT_CONTROL = "foundationHasFootControl";
|
||||
public static final String PROPERTY_FOUNDATION_HAS_FOOT_WARMER = "foundationHasFootWarmer";
|
||||
public static final String PROPERTY_FOUNDATION_HAS_UNDER_BED_LIGHT = "foundationHasUnderBedLight";
|
||||
public static final String PROPERTY_FOUNDATION_HW_REV = "foundationHwRev";
|
||||
}
|
||||
|
@ -28,8 +28,6 @@ public class Configuration {
|
||||
|
||||
private URI baseUri = URI.create("https://api.sleepiq.sleepnumber.com");
|
||||
|
||||
private boolean logging = false;
|
||||
|
||||
/**
|
||||
* Get the username on the account.
|
||||
*
|
||||
@ -128,39 +126,4 @@ public class Configuration {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,17 @@ 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.FoundationFeaturesResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationStatusResponse;
|
||||
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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
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;
|
||||
@ -31,6 +38,7 @@ 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
|
||||
* @author Mark Hilbush - Added foundation functionality
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public interface SleepIQ {
|
||||
@ -133,6 +141,68 @@ public interface SleepIQ {
|
||||
*/
|
||||
public void setPauseMode(String bedId, boolean command) throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Get the foundation features for a bed
|
||||
*
|
||||
* @param bedId the unique identifier of the bed
|
||||
*
|
||||
* @throws LoginException
|
||||
* @throws SleepIQException
|
||||
*/
|
||||
public FoundationFeaturesResponse getFoundationFeatures(String bedId) throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Get the foundation status for a bed
|
||||
*
|
||||
* @param bedId the unique identifier of the bed
|
||||
*
|
||||
* @throws LoginException
|
||||
* @throws SleepIQException
|
||||
*/
|
||||
public FoundationStatusResponse getFoundationStatus(String bedId) throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Set a foundation preset for the side of a bed
|
||||
*
|
||||
* @param bedId the unique identifier of the bed
|
||||
* @param side the chamber of the bed
|
||||
* @param preset the foundation preset
|
||||
* @param speed the speed with which the adjustment is made
|
||||
*
|
||||
* @throws LoginException
|
||||
* @throws SleepIQException
|
||||
*/
|
||||
public void setFoundationPreset(String bedId, Side side, FoundationPreset preset, FoundationActuatorSpeed speed)
|
||||
throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Set a foundation position for the side of a bed
|
||||
*
|
||||
* @param bedId the unique identifier of the bed
|
||||
* @param side the chamber of the bed
|
||||
* @param actuator the head or foot of the bed
|
||||
* @param position the new position of the actuator
|
||||
* @param speed the speed with which the adjustment is made
|
||||
*
|
||||
* @throws LoginException
|
||||
* @throws SleepIQException
|
||||
*/
|
||||
public void setFoundationPosition(String bedId, Side side, FoundationActuator actuator, int position,
|
||||
FoundationActuatorSpeed speed) throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Turn a foundation outlet on or off
|
||||
*
|
||||
* @param bedId the unique identifier of the bed
|
||||
* @param outlet the foundation outlet to control
|
||||
* @param operation set the outlet on or off
|
||||
*
|
||||
* @throws LoginException
|
||||
* @throws SleepIQException
|
||||
*/
|
||||
public void setFoundationOutlet(String bedId, FoundationOutlet outlet, FoundationOutletOperation operation)
|
||||
throws LoginException, SleepIQException;
|
||||
|
||||
/**
|
||||
* Create a default implementation instance of this interface. Each call to
|
||||
* this method will create a new object.
|
||||
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationAdjustmentRequest} is used control the actuator
|
||||
* on the side of a bed.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationAdjustmentRequest {
|
||||
@SerializedName("side")
|
||||
private Side side;
|
||||
|
||||
@SerializedName("actuator")
|
||||
private FoundationActuator actuator;
|
||||
|
||||
@SerializedName("position")
|
||||
private int position;
|
||||
|
||||
@SerializedName("speed")
|
||||
private FoundationActuatorSpeed speed;
|
||||
|
||||
public Side getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public void setSide(Side side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public FoundationAdjustmentRequest withSide(Side side) {
|
||||
setSide(side);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationActuator getFoundationActuator() {
|
||||
return actuator;
|
||||
}
|
||||
|
||||
public void setFoundationActuator(FoundationActuator actuator) {
|
||||
this.actuator = actuator;
|
||||
}
|
||||
|
||||
public FoundationAdjustmentRequest withFoundationActuator(FoundationActuator actuator) {
|
||||
setFoundationActuator(actuator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getFoundationPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setFoundationPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public FoundationAdjustmentRequest withFoundationPosition(int position) {
|
||||
setFoundationPosition(position);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationActuatorSpeed getFoundationActuartorSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public FoundationAdjustmentRequest withFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
setFoundationActuatorSpeed(speed);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SleepNumberRequest [side=");
|
||||
builder.append(side);
|
||||
builder.append(", actuator=");
|
||||
builder.append(actuator);
|
||||
builder.append(", position=");
|
||||
builder.append(position);
|
||||
builder.append(", speed=");
|
||||
builder.append(speed);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* 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 FoundationFeaturesResponse} holds the features of the foundation
|
||||
* returned from the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationFeaturesResponse {
|
||||
private static final int BOARD_AS_SINGLE = 0x01;
|
||||
private static final int MASSAGE_AND_LIGHT = 0x02;
|
||||
private static final int FOOT_CONTROL = 0x04;
|
||||
private static final int FOOT_WARMING = 0x08;
|
||||
private static final int UNDER_BED_LIGHT = 0x10;
|
||||
|
||||
@SerializedName("fsBedType")
|
||||
private int bedType;
|
||||
|
||||
@SerializedName("fsBoardFaults")
|
||||
private int boardFaults;
|
||||
|
||||
@SerializedName("fsBoardFeatures")
|
||||
private int boardFeatures;
|
||||
|
||||
@SerializedName("fsBoardHWRevisionCode")
|
||||
private int boardHWRev;
|
||||
|
||||
@SerializedName("fsBoardStatus")
|
||||
private int boardStatus;
|
||||
|
||||
@SerializedName("fsLeftUnderbedLightPWM")
|
||||
private int leftUnderbedLightPWM;
|
||||
|
||||
@SerializedName("fsRightUnderbedLightPWM")
|
||||
private int rightUnderbedLightPWM;
|
||||
|
||||
public int getBedType() {
|
||||
return bedType;
|
||||
}
|
||||
|
||||
public int getBoardFaults() {
|
||||
return boardFaults;
|
||||
}
|
||||
|
||||
public int getBoardFeatures() {
|
||||
return boardFeatures;
|
||||
}
|
||||
|
||||
public boolean isBoardAsSingle() {
|
||||
return (boardFeatures & BOARD_AS_SINGLE) > 0;
|
||||
}
|
||||
|
||||
public boolean hasMassageAndLight() {
|
||||
return (boardFeatures & MASSAGE_AND_LIGHT) > 0;
|
||||
}
|
||||
|
||||
public boolean hasFootControl() {
|
||||
return (boardFeatures & FOOT_CONTROL) > 0;
|
||||
}
|
||||
|
||||
public boolean hasFootWarming() {
|
||||
return (boardFeatures & FOOT_WARMING) > 0;
|
||||
}
|
||||
|
||||
public boolean hasUnderBedLight() {
|
||||
return (boardFeatures & UNDER_BED_LIGHT) > 0;
|
||||
}
|
||||
|
||||
public int getBoardHWRev() {
|
||||
return boardHWRev;
|
||||
}
|
||||
|
||||
public int getBoardStatus() {
|
||||
return boardStatus;
|
||||
}
|
||||
|
||||
public int getLeftUnderbedLightPWM() {
|
||||
return leftUnderbedLightPWM;
|
||||
}
|
||||
|
||||
public int getRightUnderbedLightPWM() {
|
||||
return rightUnderbedLightPWM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("FoundationFeaturesResponse [");
|
||||
builder.append("bedType=");
|
||||
builder.append(bedType);
|
||||
builder.append(", boardFaults=");
|
||||
builder.append(boardFaults);
|
||||
builder.append(", boardFeatures=");
|
||||
builder.append(boardFeatures);
|
||||
builder.append(", boardHWRevisionCode=");
|
||||
builder.append(boardHWRev);
|
||||
builder.append(", boardStatus=");
|
||||
builder.append(boardStatus);
|
||||
builder.append(", leftUnderbedLightPWM=");
|
||||
builder.append(leftUnderbedLightPWM);
|
||||
builder.append(", rightUnderbedLightPWM=");
|
||||
builder.append(rightUnderbedLightPWM);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationOutletRequest} is used to control an outlet on the bed foundation.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationOutletRequest {
|
||||
@SerializedName("outletId")
|
||||
private FoundationOutlet outlet;
|
||||
|
||||
@SerializedName("setting")
|
||||
private FoundationOutletOperation operation;
|
||||
|
||||
public FoundationOutlet getFoundationOutlet() {
|
||||
return outlet;
|
||||
}
|
||||
|
||||
public void setFoundationOutlet(FoundationOutlet outlet) {
|
||||
this.outlet = outlet;
|
||||
}
|
||||
|
||||
public FoundationOutletRequest withFoundationOutlet(FoundationOutlet outlet) {
|
||||
setFoundationOutlet(outlet);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationOutletOperation getFoundationOutletOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setFoundationOutletOperation(FoundationOutletOperation operation) {
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public FoundationOutletRequest withFoundationOutletOperation(FoundationOutletOperation operation) {
|
||||
setFoundationOutletOperation(operation);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SleepNumberRequest [outlet=");
|
||||
builder.append(outlet);
|
||||
builder.append(", operation=");
|
||||
builder.append(operation);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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 FoundationPosition} holds the head or foot position of a bed side.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationPosition {
|
||||
private Integer foundationPosition;
|
||||
|
||||
public Integer getFoundationPosition() {
|
||||
return foundationPosition;
|
||||
}
|
||||
|
||||
public void setFoundationPosition(Integer foundationPosition) {
|
||||
this.foundationPosition = foundationPosition;
|
||||
}
|
||||
|
||||
public FoundationPosition withFoundationPosition(Integer foundationPosition) {
|
||||
setFoundationPosition(foundationPosition);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("FoundationPosition [foundationPosition=");
|
||||
builder.append(foundationPosition);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationPositionRequest} is used to set the position of the head or foot
|
||||
* of a side of a bed..
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationPositionRequest {
|
||||
@SerializedName("side")
|
||||
private Side side;
|
||||
|
||||
@SerializedName("position")
|
||||
private int position;
|
||||
|
||||
@SerializedName("actuator")
|
||||
private FoundationActuator actuator;
|
||||
|
||||
@SerializedName("speed")
|
||||
private FoundationActuatorSpeed speed;
|
||||
|
||||
public Side getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public void setSide(Side side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public FoundationPositionRequest withSide(Side side) {
|
||||
setSide(side);
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public FoundationPositionRequest withPosition(int position) {
|
||||
setPosition(position);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationActuator getFoundationActuartor() {
|
||||
return actuator;
|
||||
}
|
||||
|
||||
public void setFoundationActuator(FoundationActuator actuator) {
|
||||
this.actuator = actuator;
|
||||
}
|
||||
|
||||
public FoundationPositionRequest withFoundationActuator(FoundationActuator actuator) {
|
||||
setFoundationActuator(actuator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationActuatorSpeed getFoundationActuartorSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public FoundationPositionRequest withFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
setFoundationActuatorSpeed(speed);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SleepNumberRequest [side=");
|
||||
builder.append(side);
|
||||
builder.append(", position=");
|
||||
builder.append(position);
|
||||
builder.append(", actuator=");
|
||||
builder.append(actuator);
|
||||
builder.append(", speed=");
|
||||
builder.append(speed);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* 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.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationPresetRequest} is used to set a preset for a bed side.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationPresetRequest {
|
||||
@SerializedName("side")
|
||||
private Side side;
|
||||
|
||||
@SerializedName("preset")
|
||||
private FoundationPreset preset;
|
||||
|
||||
@SerializedName("speed")
|
||||
private FoundationActuatorSpeed speed;
|
||||
|
||||
public Side getSide() {
|
||||
return side;
|
||||
}
|
||||
|
||||
public void setSide(Side side) {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
public FoundationPresetRequest withSide(Side side) {
|
||||
setSide(side);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationPreset getFoundationPreset() {
|
||||
return preset;
|
||||
}
|
||||
|
||||
public void setFoundationPreset(FoundationPreset preset) {
|
||||
this.preset = preset;
|
||||
}
|
||||
|
||||
public FoundationPresetRequest withFoundationPreset(FoundationPreset preset) {
|
||||
setFoundationPreset(preset);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FoundationActuatorSpeed getFoundationActuartorSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public void setFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public FoundationPresetRequest withFoundationActuatorSpeed(FoundationActuatorSpeed speed) {
|
||||
setFoundationActuatorSpeed(speed);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("SleepNumberRequest [side=");
|
||||
builder.append(side);
|
||||
builder.append(", preset=");
|
||||
builder.append(preset);
|
||||
builder.append(", speed=");
|
||||
builder.append(speed);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.FoundationPreset;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationStatusResponse} holds the status of the foundation
|
||||
* returned from the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
public class FoundationStatusResponse {
|
||||
@SerializedName("fsType")
|
||||
private String type;
|
||||
|
||||
@SerializedName("fsRightHeadPosition")
|
||||
private FoundationPosition rightHeadPosition;
|
||||
|
||||
@SerializedName("fsRightFootPosition")
|
||||
private FoundationPosition rightFootPosition;
|
||||
|
||||
@SerializedName("fsLeftHeadPosition")
|
||||
private FoundationPosition leftHeadPosition;
|
||||
|
||||
@SerializedName("fsLeftFootPosition")
|
||||
private FoundationPosition leftFootPosition;
|
||||
|
||||
@SerializedName("fsCurrentPositionPresetRight")
|
||||
private FoundationPreset currentPositionPresetRight;
|
||||
|
||||
@SerializedName("fsCurrentPositionPresetLeft")
|
||||
private FoundationPreset currentPositionPresetLeft;
|
||||
|
||||
@SerializedName("fsOutletsOn")
|
||||
private boolean outletsOn;
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getRightHeadPosition() {
|
||||
return rightHeadPosition.getFoundationPosition().intValue();
|
||||
}
|
||||
|
||||
public int getLeftHeadPosition() {
|
||||
return leftHeadPosition.getFoundationPosition().intValue();
|
||||
}
|
||||
|
||||
public int getRightFootPosition() {
|
||||
return rightFootPosition.getFoundationPosition().intValue();
|
||||
}
|
||||
|
||||
public int getLeftFootPosition() {
|
||||
return leftFootPosition.getFoundationPosition().intValue();
|
||||
}
|
||||
|
||||
public FoundationPreset getCurrentPositionPresetRight() {
|
||||
return currentPositionPresetRight;
|
||||
}
|
||||
|
||||
public FoundationPreset getCurrentPositionPresetLeft() {
|
||||
return currentPositionPresetLeft;
|
||||
}
|
||||
|
||||
public boolean getOutletsOn() {
|
||||
return outletsOn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("FoundationStatusResponse [");
|
||||
builder.append("type=");
|
||||
builder.append(type);
|
||||
builder.append("rightHeadPosition=");
|
||||
builder.append(rightHeadPosition);
|
||||
builder.append(", leftHeadPosition=");
|
||||
builder.append(leftHeadPosition);
|
||||
builder.append(", rightFootPosition=");
|
||||
builder.append(rightFootPosition);
|
||||
builder.append(", leftFootPosition=");
|
||||
builder.append(leftFootPosition);
|
||||
builder.append(", currentPositionPresetRight=");
|
||||
builder.append(currentPositionPresetRight);
|
||||
builder.append(", currentPositionPresetLeft=");
|
||||
builder.append(currentPositionPresetLeft);
|
||||
builder.append(", outletsOn=");
|
||||
builder.append(outletsOn);
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
@ -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.enums;
|
||||
|
||||
import static org.openhab.binding.sleepiq.internal.SleepIQBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FoundationActuator} represents actuators at the head and foot of the bed side.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FoundationActuator {
|
||||
@SerializedName("H")
|
||||
HEAD("H"),
|
||||
|
||||
@SerializedName("F")
|
||||
FOOT("F");
|
||||
|
||||
private final String actuator;
|
||||
|
||||
FoundationActuator(final String actuator) {
|
||||
this.actuator = actuator;
|
||||
}
|
||||
|
||||
public String value() {
|
||||
return actuator;
|
||||
}
|
||||
|
||||
public static FoundationActuator forValue(String value) {
|
||||
for (FoundationActuator s : FoundationActuator.values()) {
|
||||
if (s.actuator.equals(value)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid actuator: " + value);
|
||||
}
|
||||
|
||||
public static FoundationActuator convertFromChannelId(String channelId) {
|
||||
FoundationActuator localActuator;
|
||||
switch (channelId) {
|
||||
case CHANNEL_RIGHT_POSITION_HEAD:
|
||||
case CHANNEL_LEFT_POSITION_HEAD:
|
||||
localActuator = FoundationActuator.HEAD;
|
||||
break;
|
||||
case CHANNEL_RIGHT_POSITION_FOOT:
|
||||
case CHANNEL_LEFT_POSITION_FOOT:
|
||||
localActuator = FoundationActuator.FOOT;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Can't convert channel to actuator: " + channelId);
|
||||
}
|
||||
return localActuator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return actuator;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 FoundationActuatorSpeed} represents speed with which the actuator operates.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FoundationActuatorSpeed {
|
||||
FAST(0),
|
||||
SLOW(1);
|
||||
|
||||
private final int speed;
|
||||
|
||||
FoundationActuatorSpeed(final int speed) {
|
||||
this.speed = speed;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public static FoundationActuatorSpeed forValue(int value) {
|
||||
for (FoundationActuatorSpeed s : FoundationActuatorSpeed.values()) {
|
||||
if (s.speed == value) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid speed: " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(speed);
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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 static org.openhab.binding.sleepiq.internal.SleepIQBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link FoundationOutlet} represents the outlets available on the foundation.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FoundationOutlet {
|
||||
RIGHT_NIGHT_STAND(1),
|
||||
LEFT_NIGHT_STAND(2),
|
||||
RIGHT_UNDER_BED_LIGHT(3),
|
||||
LEFT_UNDER_BED_LIGHT(4);
|
||||
|
||||
private final int outlet;
|
||||
|
||||
FoundationOutlet(final int outlet) {
|
||||
this.outlet = outlet;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return outlet;
|
||||
}
|
||||
|
||||
public static FoundationOutlet forValue(int value) {
|
||||
for (FoundationOutlet s : FoundationOutlet.values()) {
|
||||
if (s.outlet == value) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid outlet: " + value);
|
||||
}
|
||||
|
||||
public static FoundationOutlet convertFromChannelId(String channelId) {
|
||||
FoundationOutlet localOutlet;
|
||||
switch (channelId) {
|
||||
case CHANNEL_RIGHT_NIGHT_STAND_OUTLET:
|
||||
localOutlet = FoundationOutlet.RIGHT_NIGHT_STAND;
|
||||
break;
|
||||
case CHANNEL_LEFT_NIGHT_STAND_OUTLET:
|
||||
localOutlet = FoundationOutlet.LEFT_NIGHT_STAND;
|
||||
break;
|
||||
case CHANNEL_RIGHT_UNDER_BED_LIGHT:
|
||||
localOutlet = FoundationOutlet.RIGHT_UNDER_BED_LIGHT;
|
||||
break;
|
||||
case CHANNEL_LEFT_UNDER_BED_LIGHT:
|
||||
localOutlet = FoundationOutlet.LEFT_UNDER_BED_LIGHT;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Can't convert channel to outlet: " + channelId);
|
||||
}
|
||||
return localOutlet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(outlet);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 FoundationOutletOperation} represents the controls on a foundation outlet.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FoundationOutletOperation {
|
||||
OFF(0),
|
||||
ON(1);
|
||||
|
||||
private final int outletControl;
|
||||
|
||||
FoundationOutletOperation(final int outletControl) {
|
||||
this.outletControl = outletControl;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return outletControl;
|
||||
}
|
||||
|
||||
public static FoundationOutletOperation forValue(int value) {
|
||||
for (FoundationOutletOperation s : FoundationOutletOperation.values()) {
|
||||
if (s.outletControl == value) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid outletControl: " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(outletControl);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
/**
|
||||
* 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 FoundationPreset} represents preset bed positions for a bed side.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public enum FoundationPreset {
|
||||
NOT_AT_PRESET(0),
|
||||
FAVORITE(1),
|
||||
READ(2),
|
||||
WATCH_TV(3),
|
||||
FLAT(4),
|
||||
ZERO_G(5),
|
||||
SNORE(6);
|
||||
|
||||
private final int preset;
|
||||
|
||||
FoundationPreset(final int preset) {
|
||||
this.preset = preset;
|
||||
}
|
||||
|
||||
public int value() {
|
||||
return preset;
|
||||
}
|
||||
|
||||
public static FoundationPreset forValue(int value) {
|
||||
for (FoundationPreset s : FoundationPreset.values()) {
|
||||
if (s.preset == value) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid preset: " + value);
|
||||
}
|
||||
|
||||
public static FoundationPreset convertFromStatus(String currentPositionPreset) {
|
||||
FoundationPreset preset;
|
||||
switch (currentPositionPreset.toLowerCase()) {
|
||||
case "not at preset":
|
||||
preset = FoundationPreset.NOT_AT_PRESET;
|
||||
break;
|
||||
case "favorite":
|
||||
preset = FoundationPreset.FAVORITE;
|
||||
break;
|
||||
case "read":
|
||||
preset = FoundationPreset.READ;
|
||||
break;
|
||||
case "watch tv":
|
||||
preset = FoundationPreset.WATCH_TV;
|
||||
break;
|
||||
case "flat":
|
||||
preset = FoundationPreset.FLAT;
|
||||
break;
|
||||
case "zero g":
|
||||
preset = FoundationPreset.ZERO_G;
|
||||
break;
|
||||
case "snore":
|
||||
preset = FoundationPreset.SNORE;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown preset value: " + currentPositionPreset);
|
||||
}
|
||||
return preset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.valueOf(preset);
|
||||
}
|
||||
}
|
@ -27,8 +27,12 @@ public class Endpoints {
|
||||
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";
|
||||
private static final String SLEEP_NUMBER = "/rest/bed/%s/sleepNumber";
|
||||
private static final String FOUNDATION_STATUS = "/rest/bed/%s/foundation/status";
|
||||
private static final String FOUNDATION_FEATURES = "/rest/bed/%s/foundation/system";
|
||||
private static final String FOUNDATION_POSITION = "/rest/bed/%s/foundation/adjustment/micro";
|
||||
private static final String FOUNDATION_PRESET = "/rest/bed/%s/foundation/preset";
|
||||
private static final String FOUNDATION_OUTLET = "/rest/bed/%s/foundation/outlet";
|
||||
|
||||
public static String login() {
|
||||
return LOGIN;
|
||||
@ -54,12 +58,28 @@ public class Endpoints {
|
||||
return SLEEP_DATA;
|
||||
}
|
||||
|
||||
public static String setSleepNumber(String bedId) {
|
||||
return String.format(SET_SLEEP_NUMBER, bedId);
|
||||
public static String sleepNumber(String bedId) {
|
||||
return String.format(SLEEP_NUMBER, bedId);
|
||||
}
|
||||
|
||||
public static String setPauseMode(String bedId) {
|
||||
return String.format(SET_PAUSE_MODE, bedId);
|
||||
public static String foundationStatus(String bedId) {
|
||||
return String.format(FOUNDATION_STATUS, bedId);
|
||||
}
|
||||
|
||||
public static String foundationFeatures(String bedId) {
|
||||
return String.format(FOUNDATION_FEATURES, bedId);
|
||||
}
|
||||
|
||||
public static String foundationPosition(String bedId) {
|
||||
return String.format(FOUNDATION_POSITION, bedId);
|
||||
}
|
||||
|
||||
public static String foundationPreset(String bedId) {
|
||||
return String.format(FOUNDATION_PRESET, bedId);
|
||||
}
|
||||
|
||||
public static String foundationOutlet(String bedId) {
|
||||
return String.format(FOUNDATION_OUTLET, bedId);
|
||||
}
|
||||
|
||||
private Endpoints() {
|
||||
|
@ -15,9 +15,19 @@ 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.FoundationPosition;
|
||||
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.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.FoundationActuatorSpeedTypeAdapter;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.FoundationOutletOperationTypeAdapter;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.FoundationOutletTypeAdapter;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.FoundationPositionTypeAdapter;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.typeadapters.FoundationPresetTypeAdapter;
|
||||
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;
|
||||
@ -43,6 +53,11 @@ public class GsonGenerator {
|
||||
builder.registerTypeAdapter(TimeSince.class, new TimeSinceTypeAdapter());
|
||||
builder.registerTypeAdapter(SleepNumberRequest.class, new SleepNumberRequestAdapter());
|
||||
builder.registerTypeAdapter(Side.class, new SideTypeAdapter());
|
||||
builder.registerTypeAdapter(FoundationPreset.class, new FoundationPresetTypeAdapter());
|
||||
builder.registerTypeAdapter(FoundationActuatorSpeed.class, new FoundationActuatorSpeedTypeAdapter());
|
||||
builder.registerTypeAdapter(FoundationOutlet.class, new FoundationOutletTypeAdapter());
|
||||
builder.registerTypeAdapter(FoundationOutletOperation.class, new FoundationOutletOperationTypeAdapter());
|
||||
builder.registerTypeAdapter(FoundationPosition.class, new FoundationPositionTypeAdapter());
|
||||
|
||||
if (prettyPrint) {
|
||||
builder.setPrettyPrinting();
|
||||
|
@ -36,11 +36,17 @@ 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.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.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.FoundationFeaturesResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationOutletRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationPositionRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationPresetRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationStatusResponse;
|
||||
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;
|
||||
@ -48,6 +54,11 @@ 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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.SleepDataInterval;
|
||||
import org.slf4j.Logger;
|
||||
@ -60,6 +71,7 @@ import com.google.gson.JsonSyntaxException;
|
||||
* The {@link SleepIQImpl} class handles all interactions with the sleepiq service.
|
||||
*
|
||||
* @author Gregory Moyer - Initial contribution
|
||||
* @author Mark Hilbush - Added foundation functionality
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SleepIQImpl implements SleepIQ {
|
||||
@ -225,7 +237,7 @@ public class SleepIQImpl implements SleepIQ {
|
||||
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);
|
||||
cloudRequest(Endpoints.sleepNumber(bedId), null, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -234,7 +246,68 @@ public class SleepIQImpl implements SleepIQ {
|
||||
logger.debug("SleepIQ: setPauseMode: command={}", pauseMode);
|
||||
Map<String, String> requestParameters = new HashMap<>();
|
||||
requestParameters.put("mode", pauseMode ? "on" : "off");
|
||||
cloudRequest(Endpoints.setPauseMode(bedId), requestParameters, "");
|
||||
cloudRequest(Endpoints.pauseMode(bedId), requestParameters, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public FoundationFeaturesResponse getFoundationFeatures(String bedId)
|
||||
throws LoginException, ResponseFormatException, CommunicationException {
|
||||
try {
|
||||
String contentResponse = cloudRequest(Endpoints.foundationFeatures(bedId));
|
||||
FoundationFeaturesResponse response = GSON.fromJson(contentResponse, FoundationFeaturesResponse.class);
|
||||
if (response != null) {
|
||||
logger.debug("SleepIQ: {}", response);
|
||||
return response;
|
||||
} else {
|
||||
throw new ResponseFormatException("Failed to get a valid 'foundationFeatures' response from cloud");
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new ResponseFormatException("Failed to parse 'foundationFeatures' response");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FoundationStatusResponse getFoundationStatus(String bedId) throws LoginException, SleepIQException {
|
||||
try {
|
||||
String contentResponse = cloudRequest(Endpoints.foundationStatus(bedId));
|
||||
FoundationStatusResponse response = GSON.fromJson(contentResponse, FoundationStatusResponse.class);
|
||||
if (response != null) {
|
||||
logger.debug("SleepIQ: {}", response);
|
||||
return response;
|
||||
} else {
|
||||
throw new ResponseFormatException("Failed to get a valid 'foundationStatus' response from cloud");
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new ResponseFormatException("Failed to parse 'foundationStatus' response");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFoundationPreset(String bedId, Side side, FoundationPreset preset, FoundationActuatorSpeed speed)
|
||||
throws LoginException, SleepIQException {
|
||||
String body = GSON.toJson(new FoundationPresetRequest().withSide(side).withFoundationPreset(preset)
|
||||
.withFoundationActuatorSpeed(speed), FoundationPresetRequest.class);
|
||||
logger.debug("SleepIQ: setFoundationPreset: Request body={}", body);
|
||||
cloudRequest(Endpoints.foundationPreset(bedId), null, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFoundationPosition(String bedId, Side side, FoundationActuator actuator, int position,
|
||||
FoundationActuatorSpeed speed) throws LoginException, SleepIQException {
|
||||
String body = GSON.toJson(new FoundationPositionRequest().withSide(side).withPosition(position)
|
||||
.withFoundationActuator(actuator).withFoundationActuatorSpeed(speed), FoundationPositionRequest.class);
|
||||
logger.debug("SleepIQ: setFoundationPosition: Request body={}", body);
|
||||
cloudRequest(Endpoints.foundationPosition(bedId), null, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFoundationOutlet(String bedId, FoundationOutlet outlet, FoundationOutletOperation operation)
|
||||
throws LoginException, SleepIQException {
|
||||
String body = GSON.toJson(
|
||||
new FoundationOutletRequest().withFoundationOutlet(outlet).withFoundationOutletOperation(operation),
|
||||
FoundationOutletRequest.class);
|
||||
logger.debug("SleepIQ: setFoundationOutlet: Request body={}", body);
|
||||
cloudRequest(Endpoints.foundationOutlet(bedId), null, body);
|
||||
}
|
||||
|
||||
private String cloudRequest(String endpoint)
|
||||
@ -249,7 +322,7 @@ public class SleepIQImpl implements SleepIQ {
|
||||
|
||||
private String cloudRequest(String endpoint, @Nullable Map<String, String> parameters, @Nullable String body)
|
||||
throws LoginException, ResponseFormatException, CommunicationException {
|
||||
logger.debug("SleepIQ: cloudGetRequest: Invoke endpoint={}", endpoint);
|
||||
logger.debug("SleepIQ: cloudRequest: Invoke endpoint={}", endpoint);
|
||||
ContentResponse response = (body == null ? doGet(endpoint, parameters) : doPut(endpoint, parameters, body));
|
||||
if (isUnauthorized(response)) {
|
||||
logger.debug("SleepIQ: cloudGetRequest: UNAUTHORIZED, reset login");
|
||||
@ -258,6 +331,7 @@ public class SleepIQImpl implements SleepIQ {
|
||||
response = (body == null ? doGet(endpoint, parameters) : doPut(endpoint, parameters, body));
|
||||
}
|
||||
if (isNotOk(response)) {
|
||||
logger.debug("SleepIQ.cloudRequest: ResponseFormatException on call to endpoint {}", endpoint);
|
||||
throw new ResponseFormatException(String.format("Cloud API returned error: status=%d, message=%s",
|
||||
response.getStatus(), HttpStatus.getCode(response.getStatus()).getMessage()));
|
||||
}
|
||||
@ -282,7 +356,7 @@ public class SleepIQImpl implements SleepIQ {
|
||||
return doRequest(request, parameters);
|
||||
}
|
||||
|
||||
private ContentResponse doRequest(Request request, @Nullable Map<String, String> parameters)
|
||||
private synchronized ContentResponse doRequest(Request request, @Nullable Map<String, String> parameters)
|
||||
throws CommunicationException {
|
||||
try {
|
||||
if (parameters != null) {
|
||||
@ -291,12 +365,13 @@ public class SleepIQImpl implements SleepIQ {
|
||||
}
|
||||
}
|
||||
addCookiesToRequest(request);
|
||||
logger.debug("SleepIQ: doPut: request url={}", request.getURI());
|
||||
logger.debug("SleepIQ: doRequest: request url={}", request.getURI());
|
||||
ContentResponse response = request.send();
|
||||
logger.trace("SleepIQ: doPut: status={} response={}", response.getStatus(), response.getContentAsString());
|
||||
logger.trace("SleepIQ: doRequest: status={} response={}", response.getStatus(),
|
||||
response.getContentAsString());
|
||||
return response;
|
||||
} catch (InterruptedException | TimeoutException | ExecutionException e) {
|
||||
logger.debug("SleepIQ: doPut: Exception message={}", e.getMessage(), e);
|
||||
logger.debug("SleepIQ: doRequest: Exception message={}", e.getMessage(), e);
|
||||
throw new CommunicationException("Communication error while accessing API: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
@ -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.lang.reflect.Type;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* The {@link FoundationActuatorSpeedTypeAdapter} converts the FoundationActuatorSpeed enum
|
||||
* to the format expected by the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationActuatorSpeedTypeAdapter implements JsonSerializer<FoundationActuatorSpeed> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(FoundationActuatorSpeed speed, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(speed.value());
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.enums.FoundationOutletOperation;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* The {@link FoundationOutletOperationTypeAdapter} converts the FoundationOutletOperation enum to the
|
||||
* format expected by the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationOutletOperationTypeAdapter implements JsonSerializer<FoundationOutletOperation> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(FoundationOutletOperation operation, Type typeOfSrc,
|
||||
JsonSerializationContext context) {
|
||||
return new JsonPrimitive(operation.value());
|
||||
}
|
||||
}
|
@ -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.lang.reflect.Type;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
|
||||
/**
|
||||
* The {@link FoundationOutletTypeAdapter} converts the FoundationOutlet enum to the
|
||||
* format expected by the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationOutletTypeAdapter implements JsonSerializer<FoundationOutlet> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(FoundationOutlet outlet, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(outlet.value());
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.dto.FoundationPosition;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
/**
|
||||
* The {@link FoundationPositionTypeAdapter} converts the hex string position from the
|
||||
* foundation status response into an integer value. The position is returned by the API
|
||||
* as a two character hex string (e.g. "3f"). The position can be between 0 and 100, inclusive.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationPositionTypeAdapter implements JsonDeserializer<FoundationPosition> {
|
||||
|
||||
@Override
|
||||
public @Nullable FoundationPosition deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2)
|
||||
throws JsonParseException {
|
||||
try {
|
||||
return new FoundationPosition().withFoundationPosition(Integer.parseInt(element.getAsString(), 16));
|
||||
} catch (NumberFormatException e) {
|
||||
// If we can't parse it, just set to 0
|
||||
return new FoundationPosition().withFoundationPosition(Integer.valueOf(0));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.FoundationPreset;
|
||||
|
||||
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 FoundationPresetTypeAdapter} converts the FoundationPreset enum to the
|
||||
* format expected by the sleepiq API.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationPresetTypeAdapter
|
||||
implements JsonDeserializer<FoundationPreset>, JsonSerializer<FoundationPreset> {
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(FoundationPreset preset, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(preset.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable FoundationPreset deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2)
|
||||
throws JsonParseException {
|
||||
return FoundationPreset.convertFromStatus(element.getAsString());
|
||||
}
|
||||
}
|
@ -36,7 +36,7 @@ public class SideTypeAdapter implements JsonDeserializer<Side>, JsonSerializer<S
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Side side, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(side.value());
|
||||
return new JsonPrimitive(side.equals(Side.LEFT) ? "L" : "R");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@ package org.openhab.binding.sleepiq.internal.handler;
|
||||
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.FoundationStatusResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.Sleeper;
|
||||
|
||||
/**
|
||||
@ -27,10 +28,23 @@ public interface BedStatusListener {
|
||||
/**
|
||||
* This method will be called whenever a new bed status is received by the cloud handler.
|
||||
*
|
||||
* @param cloud the cloud service that can be used to gather additional information
|
||||
* @param status the status returned from the cloud service
|
||||
* @param status the bed status returned from the cloud service
|
||||
*/
|
||||
public void onBedStateChanged(BedStatus status);
|
||||
|
||||
/**
|
||||
* This method will be called whenever a new foundation status is received by the cloud handler.
|
||||
*
|
||||
* @param status the foundation status returned from the cloud service
|
||||
*/
|
||||
public void onFoundationStateChanged(String bedId, FoundationStatusResponse status);
|
||||
|
||||
/**
|
||||
* Determine if bed has a foundation installed.
|
||||
*
|
||||
* @return true if bed has a foundation; otherwise falase
|
||||
*/
|
||||
public boolean isFoundationInstalled();
|
||||
|
||||
public void onSleeperChanged(@Nullable Sleeper sleeper);
|
||||
}
|
||||
|
@ -32,14 +32,22 @@ 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.ResponseFormatException;
|
||||
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.FoundationFeaturesResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationStatusResponse;
|
||||
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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
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;
|
||||
@ -146,11 +154,15 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
*/
|
||||
public void registerBedStatusListener(final BedStatusListener listener) {
|
||||
bedStatusListeners.add(listener);
|
||||
scheduler.execute(() -> {
|
||||
/*
|
||||
* Delay the initial sleeper and status update to give some time for the property update
|
||||
* to determine if a foundation is installed.
|
||||
*/
|
||||
scheduler.schedule(() -> {
|
||||
refreshSleepers();
|
||||
refreshBedStatus();
|
||||
updateListenerManagement();
|
||||
});
|
||||
}, 10L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,11 +200,8 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
* @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) {
|
||||
public @Nullable Bed getBed(final String bedId) {
|
||||
logger.debug("CloudHandler: Get bed object for bedId={}", bedId);
|
||||
if (bedId == null) {
|
||||
return null;
|
||||
}
|
||||
List<Bed> beds = getBeds();
|
||||
if (beds != null) {
|
||||
for (Bed bed : beds) {
|
||||
@ -211,11 +220,8 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
* @param side the side of the bed
|
||||
* @return the sleeper or null if sleeper not found
|
||||
*/
|
||||
public @Nullable Sleeper getSleeper(@Nullable String bedId, Side side) {
|
||||
public @Nullable Sleeper getSleeper(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) {
|
||||
@ -234,10 +240,7 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
* @param sleepNumber the sleep number multiple of 5 between 5 and 100
|
||||
* @param side the chamber to set
|
||||
*/
|
||||
public void setSleepNumber(@Nullable String bedId, Side side, int sleepNumber) {
|
||||
if (bedId == null) {
|
||||
return;
|
||||
}
|
||||
public void setSleepNumber(String bedId, Side side, int sleepNumber) {
|
||||
try {
|
||||
cloud.setSleepNumber(bedId, side, sleepNumber);
|
||||
} catch (SleepIQException e) {
|
||||
@ -251,10 +254,7 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
* @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;
|
||||
}
|
||||
public void setPauseMode(String bedId, boolean mode) {
|
||||
try {
|
||||
cloud.setPauseMode(bedId, mode);
|
||||
} catch (SleepIQException e) {
|
||||
@ -262,6 +262,99 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foundation features of the specified bed
|
||||
*
|
||||
* @param bedId the bed identifier
|
||||
*/
|
||||
public @Nullable FoundationFeaturesResponse getFoundationFeatures(String bedId) {
|
||||
try {
|
||||
return cloud.getFoundationFeatures(bedId);
|
||||
} catch (ResponseFormatException e) {
|
||||
logger.debug("CloudHandler: Unable to parse foundation features response for bed={}", bedId);
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception getting foundation features, bed={}", bedId, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the foundation status of the specified bed
|
||||
*
|
||||
* @param bedId the bed identifier
|
||||
*/
|
||||
public @Nullable FoundationStatusResponse getFoundationStatus(String bedId) {
|
||||
try {
|
||||
return cloud.getFoundationStatus(bedId);
|
||||
} catch (ResponseFormatException e) {
|
||||
logger.debug("CloudHandler: Unable to parse foundation status response for bed={}", bedId);
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception getting foundation status, bed={}: {}", bedId, e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a foundation adjustment preset.
|
||||
*
|
||||
* @param bedId the bed identifier
|
||||
* @param side the side of the bed
|
||||
* @param preset the preset to be applied
|
||||
* @param speed the speed with which to make the adjustment
|
||||
*/
|
||||
public void setFoundationPreset(String bedId, Side side, FoundationPreset preset, FoundationActuatorSpeed speed) {
|
||||
try {
|
||||
cloud.setFoundationPreset(bedId, side, preset, speed);
|
||||
} catch (ResponseFormatException e) {
|
||||
logger.debug("CloudHandler: ResponseFormatException setting foundation preset for bed={}: {}", bedId,
|
||||
e.getMessage());
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception setting the foundation preset for bed={}", bedId, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a foundation position on head or foot of bed side.
|
||||
*
|
||||
* @param bedId the bed identifier
|
||||
* @param side the side of the bed
|
||||
* @param actuator the head or foot of the bed
|
||||
* @param position the new position of the actuator
|
||||
* @param speed the speed with which to make the adjustment
|
||||
*/
|
||||
public void setFoundationPosition(String bedId, Side side, FoundationActuator actuator, int position,
|
||||
FoundationActuatorSpeed speed) {
|
||||
try {
|
||||
cloud.setFoundationPosition(bedId, side, actuator, position, speed);
|
||||
} catch (ResponseFormatException e) {
|
||||
logger.debug("CloudHandler: ResponseFormatException setting foundation position for bed={}: {}", bedId,
|
||||
e.getMessage());
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception setting the foundation position for bed={}", bedId, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operate an outlet on the foundation.
|
||||
*
|
||||
* @param bedId the bed identifier
|
||||
* @param outlet the outlet to operate
|
||||
* @param operation the operation (On or Off) performed on the outlet
|
||||
*/
|
||||
public void setFoundationOutlet(String bedId, FoundationOutlet outlet, FoundationOutletOperation operation) {
|
||||
try {
|
||||
cloud.setFoundationOutlet(bedId, outlet, operation);
|
||||
} catch (ResponseFormatException e) {
|
||||
logger.debug("CloudHandler: ResponseFormatException setting the foundation outlet for bed={}: {}", bedId,
|
||||
e.getMessage());
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception setting the foundation outlet for bed={}", bedId, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given properties with attributes of the given bed. If no properties are given, a new map will be
|
||||
* created.
|
||||
@ -289,22 +382,61 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the given foundation properties with features of the given bed foundation.
|
||||
*
|
||||
* @param bed the source of data
|
||||
* @param features the foundation features 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> updateFeatures(final String bedId, final @Nullable FoundationFeaturesResponse features,
|
||||
Map<String, String> properties) {
|
||||
if (features != null) {
|
||||
logger.debug("CloudHandler: Updating foundation properties for bed={}", bedId);
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION, "Installed");
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_HW_REV,
|
||||
String.valueOf(features.getBoardHWRev()));
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_IS_BOARD_AS_SINGLE,
|
||||
features.isBoardAsSingle() ? "yes" : "no");
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_HAS_MASSAGE_AND_LIGHT,
|
||||
features.hasMassageAndLight() ? "yes" : "no");
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_HAS_FOOT_CONTROL,
|
||||
features.hasFootControl() ? "yes" : "no");
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_HAS_FOOT_WARMER,
|
||||
features.hasFootWarming() ? "yes" : "no");
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION_HAS_UNDER_BED_LIGHT,
|
||||
features.hasUnderBedLight() ? "yes" : "no");
|
||||
} else {
|
||||
logger.debug("CloudHandler: Foundation not installed on bed={}", bedId);
|
||||
properties.put(SleepIQBindingConstants.PROPERTY_FOUNDATION, "Not installed");
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the latest status on all beds and update all registered listeners
|
||||
* with bed status, sleepers and sleep data.
|
||||
* with bed status, foundation 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) {
|
||||
if (familyStatus.getBeds() != null) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
for (BedStatus bedStatus : familyStatus.getBeds()) {
|
||||
logger.debug("CloudHandler: Informing listeners with bed status for bedId={}",
|
||||
bedStatus.getBedId());
|
||||
String bedId = bedStatus.getBedId();
|
||||
logger.debug("CloudHandler: Informing listeners with bed status for bedId={}", bedId);
|
||||
bedStatusListeners.stream().forEach(l -> l.onBedStateChanged(bedStatus));
|
||||
}
|
||||
|
||||
// Get foundation status only if bed has a foundation
|
||||
bedStatusListeners.stream().filter(l -> l.isFoundationInstalled()).forEach(l -> {
|
||||
try {
|
||||
l.onFoundationStateChanged(bedId, cloud.getFoundationStatus(bedStatus.getBedId()));
|
||||
} catch (SleepIQException e) {
|
||||
logger.debug("CloudHandler: Exception getting foundation status for bedId={}", bedId);
|
||||
}
|
||||
});
|
||||
}
|
||||
List<Sleeper> localSleepers = sleepers;
|
||||
if (localSleepers != null) {
|
||||
for (Sleeper sleeper : localSleepers) {
|
||||
@ -358,7 +490,7 @@ public class SleepIQCloudHandler extends ConfigStatusBridgeHandler {
|
||||
private void createCloudConnection() throws LoginException {
|
||||
SleepIQCloudConfiguration bindingConfig = getConfigAs(SleepIQCloudConfiguration.class);
|
||||
Configuration cloudConfig = new Configuration().withUsername(bindingConfig.username)
|
||||
.withPassword(bindingConfig.password).withLogging(logger.isTraceEnabled());
|
||||
.withPassword(bindingConfig.password);
|
||||
logger.debug("CloudHandler: Authenticating at the SleepIQ cloud service");
|
||||
cloud = SleepIQ.create(cloudConfig, httpClient);
|
||||
cloud.login();
|
||||
|
@ -23,8 +23,15 @@ 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.FoundationFeaturesResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.dto.FoundationStatusResponse;
|
||||
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.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.Side;
|
||||
import org.openhab.binding.sleepiq.internal.config.SleepIQBedConfiguration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
@ -60,13 +67,15 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(SleepIQDualBedHandler.class);
|
||||
|
||||
private volatile @Nullable String bedId;
|
||||
private volatile String bedId = "";
|
||||
|
||||
private @Nullable Sleeper sleeperLeft;
|
||||
private @Nullable Sleeper sleeperRight;
|
||||
|
||||
private @Nullable BedStatus previousStatus;
|
||||
|
||||
private @Nullable FoundationFeaturesResponse foundationFeatures;
|
||||
|
||||
public SleepIQDualBedHandler(final Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
@ -84,12 +93,15 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Incorrect bridge thing found");
|
||||
return;
|
||||
}
|
||||
bedId = getConfigAs(SleepIQBedConfiguration.class).bedId;
|
||||
if (bedId == null) {
|
||||
String localBedId = getConfigAs(SleepIQBedConfiguration.class).bedId;
|
||||
if (localBedId == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Bed id not found in configuration");
|
||||
return;
|
||||
}
|
||||
bedId = localBedId;
|
||||
// Assume the bed has a foundation until we determine otherwise
|
||||
setFoundationFeatures(new FoundationFeaturesResponse());
|
||||
|
||||
logger.debug("BedHandler: Registering SleepIQ bed status listener for bedId={}", bedId);
|
||||
SleepIQCloudHandler cloudHandler = (SleepIQCloudHandler) handler;
|
||||
@ -111,7 +123,7 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
if (cloudHandler != null) {
|
||||
cloudHandler.unregisterBedStatusListener(this);
|
||||
}
|
||||
bedId = null;
|
||||
bedId = "";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,12 +140,14 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
// Channels will be refreshed automatically by cloud handler
|
||||
return;
|
||||
}
|
||||
String channelId = channelUID.getId();
|
||||
String groupId = channelUID.getGroupId();
|
||||
|
||||
switch (channelUID.getId()) {
|
||||
switch (channelId) {
|
||||
case CHANNEL_LEFT_SLEEP_NUMBER:
|
||||
case CHANNEL_RIGHT_SLEEP_NUMBER:
|
||||
if (command instanceof DecimalType) {
|
||||
Side side = Side.convertFromGroup(channelUID.getGroupId());
|
||||
Side side = Side.convertFromGroup(groupId);
|
||||
logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side);
|
||||
SleepIQCloudHandler cloudHandler = getCloudHandler();
|
||||
if (cloudHandler != null) {
|
||||
@ -144,7 +158,7 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
case CHANNEL_LEFT_PRIVACY_MODE:
|
||||
case CHANNEL_RIGHT_PRIVACY_MODE:
|
||||
if (command instanceof OnOffType) {
|
||||
Side side = Side.convertFromGroup(channelUID.getGroupId());
|
||||
Side side = Side.convertFromGroup(groupId);
|
||||
logger.debug("BedHandler: Set sleepnumber to {} for bedId={}, side={}", command, bedId, side);
|
||||
SleepIQCloudHandler cloudHandler = getCloudHandler();
|
||||
if (cloudHandler != null) {
|
||||
@ -152,6 +166,60 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_LEFT_FOUNDATION_PRESET:
|
||||
case CHANNEL_RIGHT_FOUNDATION_PRESET:
|
||||
logger.debug("Received command {} on channel {} to set preset", command, channelUID);
|
||||
if (isFoundationInstalled() && command instanceof DecimalType) {
|
||||
try {
|
||||
Side side = Side.convertFromGroup(groupId);
|
||||
FoundationPreset preset = FoundationPreset.forValue(((DecimalType) command).intValue());
|
||||
logger.debug("BedHandler: Set foundation preset to {} for bedId={}, side={}", command, bedId,
|
||||
side);
|
||||
SleepIQCloudHandler cloudHandler = getCloudHandler();
|
||||
if (cloudHandler != null) {
|
||||
cloudHandler.setFoundationPreset(bedId, side, preset, FoundationActuatorSpeed.SLOW);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.info("BedHandler: Foundation preset invalid: {} must be 1-6", command);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_LEFT_NIGHT_STAND_OUTLET:
|
||||
case CHANNEL_RIGHT_NIGHT_STAND_OUTLET:
|
||||
case CHANNEL_LEFT_UNDER_BED_LIGHT:
|
||||
case CHANNEL_RIGHT_UNDER_BED_LIGHT:
|
||||
logger.debug("Received command {} on channel {} to control outlet", command, channelUID);
|
||||
if (isFoundationInstalled() && command instanceof OnOffType) {
|
||||
try {
|
||||
logger.debug("BedHandler: Set foundation outlet channel {} to {} for bedId={}", channelId,
|
||||
command, bedId);
|
||||
FoundationOutlet outlet = FoundationOutlet.convertFromChannelId(channelId);
|
||||
SleepIQCloudHandler cloudHandler = getCloudHandler();
|
||||
if (cloudHandler != null) {
|
||||
FoundationOutletOperation operation = command == OnOffType.ON ? FoundationOutletOperation.ON
|
||||
: FoundationOutletOperation.OFF;
|
||||
cloudHandler.setFoundationOutlet(bedId, outlet, operation);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.info("BedHandler: Can't convert channel {} to foundation outlet", channelId);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CHANNEL_LEFT_POSITION_HEAD:
|
||||
case CHANNEL_RIGHT_POSITION_HEAD:
|
||||
logger.debug("Received command {} on channel {} to set position", command, channelUID);
|
||||
if (groupId != null && isFoundationInstalled() && command instanceof DecimalType) {
|
||||
setFoundationPosition(groupId, channelId, command);
|
||||
}
|
||||
|
||||
case CHANNEL_LEFT_POSITION_FOOT:
|
||||
case CHANNEL_RIGHT_POSITION_FOOT:
|
||||
logger.debug("Received command {} on channel {} to set position", command, channelUID);
|
||||
if (groupId != null && isFoundationInstalled() && isFoundationFootAdjustable()
|
||||
&& command instanceof DecimalType) {
|
||||
setFoundationPosition(groupId, channelId, command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,6 +247,7 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
return;
|
||||
}
|
||||
logger.debug("BedHandler: Updating bed status channels for bed {}", bedId);
|
||||
BedStatus localPreviousStatus = previousStatus;
|
||||
|
||||
BedSideStatus left = status.getLeftSide();
|
||||
updateState(CHANNEL_LEFT_IN_BED, left.isInBed() ? OnOffType.ON : OnOffType.OFF);
|
||||
@ -187,8 +256,8 @@ 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);
|
||||
if (localPreviousStatus != null) {
|
||||
updateSleepDataChannels(localPreviousStatus.getLeftSide(), left, sleeperLeft);
|
||||
}
|
||||
|
||||
BedSideStatus right = status.getRightSide();
|
||||
@ -198,13 +267,57 @@ 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);
|
||||
if (localPreviousStatus != null) {
|
||||
updateSleepDataChannels(localPreviousStatus.getRightSide(), right, sleeperRight);
|
||||
}
|
||||
|
||||
previousStatus = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFoundationStateChanged(String bedId, final @Nullable FoundationStatusResponse status) {
|
||||
if (status == null || !bedId.equals(this.bedId)) {
|
||||
return;
|
||||
}
|
||||
logger.debug("BedHandler: Updating foundation status channels for bed {}", bedId);
|
||||
updateState(CHANNEL_LEFT_POSITION_HEAD, new DecimalType(status.getLeftHeadPosition()));
|
||||
updateState(CHANNEL_LEFT_POSITION_FOOT, new DecimalType(status.getLeftFootPosition()));
|
||||
updateState(CHANNEL_RIGHT_POSITION_HEAD, new DecimalType(status.getRightHeadPosition()));
|
||||
updateState(CHANNEL_RIGHT_POSITION_FOOT, new DecimalType(status.getRightFootPosition()));
|
||||
updateState(CHANNEL_LEFT_FOUNDATION_PRESET, new DecimalType(status.getCurrentPositionPresetLeft().value()));
|
||||
updateState(CHANNEL_RIGHT_FOUNDATION_PRESET, new DecimalType(status.getCurrentPositionPresetRight().value()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFoundationInstalled() {
|
||||
return foundationFeatures != null;
|
||||
}
|
||||
|
||||
private void setFoundationFeatures(@Nullable FoundationFeaturesResponse features) {
|
||||
foundationFeatures = features;
|
||||
}
|
||||
|
||||
private boolean isFoundationFootAdjustable() {
|
||||
FoundationFeaturesResponse localFoundationFeatures = foundationFeatures;
|
||||
return localFoundationFeatures != null ? localFoundationFeatures.hasFootControl() : false;
|
||||
}
|
||||
|
||||
private void setFoundationPosition(String groupId, String channelId, Command command) {
|
||||
try {
|
||||
logger.debug("BedHandler: Set foundation position channel {} to {} for bedId={}", channelId, command,
|
||||
bedId);
|
||||
Side side = Side.convertFromGroup(groupId);
|
||||
FoundationActuator actuator = FoundationActuator.convertFromChannelId(channelId);
|
||||
int position = ((DecimalType) command).intValue();
|
||||
SleepIQCloudHandler cloudHandler = getCloudHandler();
|
||||
if (cloudHandler != null) {
|
||||
cloudHandler.setFoundationPosition(bedId, side, actuator, position, FoundationActuatorSpeed.SLOW);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.info("BedHandler: Can't convert channel {} to foundation position", channelId);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSleepDataChannels(BedSideStatus previousSideStatus, BedSideStatus currentSideStatus,
|
||||
@Nullable Sleeper sleeper) {
|
||||
if (sleeper == null) {
|
||||
@ -331,6 +444,13 @@ public class SleepIQDualBedHandler extends BaseThingHandler implements BedStatus
|
||||
return;
|
||||
}
|
||||
updateProperties(cloudHandler.updateProperties(bed, editProperties()));
|
||||
|
||||
logger.debug("BedHandler: Checking if foundation is installed for bedId={}", bedId);
|
||||
if (isFoundationInstalled()) {
|
||||
FoundationFeaturesResponse foundationFeaturesResponse = cloudHandler.getFoundationFeatures(bedId);
|
||||
updateProperties(cloudHandler.updateFeatures(bedId, foundationFeaturesResponse, editProperties()));
|
||||
setFoundationFeatures(foundationFeaturesResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,18 @@ channel-type.sleepiq.alertIdType.label = Alert ID
|
||||
channel-type.sleepiq.alertIdType.description = Identifier for an alert condition with the chamber
|
||||
channel-type.sleepiq.firstNameType.label = First Name
|
||||
channel-type.sleepiq.firstNameType.description = The first name of the sleeper
|
||||
channel-type.sleepiq.foundationPositionFootType.label = Foot Position
|
||||
channel-type.sleepiq.foundationPositionFootType.description = The position of the adjustable foot
|
||||
channel-type.sleepiq.foundationPositionHeadType.label = Head Position
|
||||
channel-type.sleepiq.foundationPositionHeadType.description = The position of the adjustable head
|
||||
channel-type.sleepiq.foundationPresetType.label = Preset
|
||||
channel-type.sleepiq.foundationPresetType.description = Bed position preset
|
||||
channel-type.sleepiq.foundationPresetType.state.option.1 = Favorite
|
||||
channel-type.sleepiq.foundationPresetType.state.option.2 = Read
|
||||
channel-type.sleepiq.foundationPresetType.state.option.3 = Watch TV
|
||||
channel-type.sleepiq.foundationPresetType.state.option.4 = Flat
|
||||
channel-type.sleepiq.foundationPresetType.state.option.5 = Zero G
|
||||
channel-type.sleepiq.foundationPresetType.state.option.6 = Snore
|
||||
channel-type.sleepiq.inBedType.label = In Bed
|
||||
channel-type.sleepiq.inBedType.description = The presence of a person or object on the chamber
|
||||
channel-type.sleepiq.lastLinkType.label = Last Link
|
||||
@ -43,6 +55,8 @@ channel-type.sleepiq.monthlyAverageRespirationRateType.label = Monthly Avg Respi
|
||||
channel-type.sleepiq.monthlyAverageRespirationRateType.description = The average respiration rate for the past month
|
||||
channel-type.sleepiq.monthlySleepIQType.label = Monthly Sleep IQ
|
||||
channel-type.sleepiq.monthlySleepIQType.description = The overall Sleep Quotient for the past month
|
||||
channel-type.sleepiq.nightStandOutletType.label = Night Stand
|
||||
channel-type.sleepiq.nightStandOutletType.description = The night stand outlet
|
||||
channel-type.sleepiq.pressureType.label = Pressure
|
||||
channel-type.sleepiq.pressureType.description = The current pressure inside the chamber
|
||||
channel-type.sleepiq.privacyMode.label = Privacy Mode
|
||||
@ -69,6 +83,13 @@ channel-type.sleepiq.todaySleepRestfulSecondsType.label = Today's Sleep Restful
|
||||
channel-type.sleepiq.todaySleepRestfulSecondsType.description = The total duration of restful sleep for today in seconds
|
||||
channel-type.sleepiq.todaySleepRestlessSecondsType.label = Today's Sleep Restless Duration
|
||||
channel-type.sleepiq.todaySleepRestlessSecondsType.description = The total duration of restless sleep for today in seconds
|
||||
channel-type.sleepiq.underBedLightType.label = Under Bed Light
|
||||
channel-type.sleepiq.underBedLightType.description = The under bed lighting
|
||||
|
||||
# channel types
|
||||
|
||||
channel-type.sleepiq.nightLightOutletType.label = Night Light
|
||||
channel-type.sleepiq.nightLightOutletType.description = The night light outlet
|
||||
|
||||
# configuration messages
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
</channel-groups>
|
||||
|
||||
<properties>
|
||||
<property name="thingTypeVersion">1</property>
|
||||
<property name="thingTypeVersion">2</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
@ -105,6 +105,11 @@
|
||||
<channel id="monthlySleepIQ" typeId="monthlySleepIQType"/>
|
||||
<channel id="monthlyAverageHeartRate" typeId="monthlyAverageHeartRateType"/>
|
||||
<channel id="monthlyAverageRespirationRate" typeId="monthlyAverageRespirationRateType"/>
|
||||
<channel id="foundationPreset" typeId="foundationPresetType"/>
|
||||
<channel id="foundationPositionHead" typeId="foundationPositionHeadType"/>
|
||||
<channel id="foundationPositionFoot" typeId="foundationPositionFootType"/>
|
||||
<channel id="nightStandOutlet" typeId="nightStandOutletType"/>
|
||||
<channel id="underBedLight" typeId="underBedLightType"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
@ -235,5 +240,44 @@
|
||||
<description>The average respiration rate for the past month</description>
|
||||
<state readOnly="true" pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="foundationPresetType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Preset</label>
|
||||
<description>Bed position preset</description>
|
||||
<state readOnly="false" min="1" max="6" step="1" pattern="%d">
|
||||
<options>
|
||||
<option value="1">Favorite</option>
|
||||
<option value="2">Read</option>
|
||||
<option value="3">Watch TV</option>
|
||||
<option value="4">Flat</option>
|
||||
<option value="5">Zero G</option>
|
||||
<option value="6">Snore</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
<channel-type id="foundationPositionHeadType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Head Position</label>
|
||||
<description>The position of the adjustable head</description>
|
||||
<state readOnly="false" min="0" max="100" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="foundationPositionFootType">
|
||||
<item-type>Number</item-type>
|
||||
<label>Foot Position</label>
|
||||
<description>The position of the adjustable foot</description>
|
||||
<state readOnly="false" min="0" max="100" step="1" pattern="%d"/>
|
||||
</channel-type>
|
||||
<channel-type id="nightStandOutletType">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Night Stand</label>
|
||||
<description>The night stand outlet</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
<channel-type id="underBedLightType">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Under Bed Light</label>
|
||||
<description>The under bed lighting</description>
|
||||
<state readOnly="false"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
|
@ -20,6 +20,24 @@
|
||||
</add-channel>
|
||||
</instruction-set>
|
||||
|
||||
<instruction-set targetVersion="2">
|
||||
<add-channel id="foundationPreset" groupIds="left,right">
|
||||
<type>sleepiq:foundationPresetType</type>
|
||||
</add-channel>
|
||||
<add-channel id="foundationPositionHead" groupIds="left,right">
|
||||
<type>sleepiq:foundationPositionHeadType</type>
|
||||
</add-channel>
|
||||
<add-channel id="foundationPositionFoot" groupIds="left,right">
|
||||
<type>sleepiq:foundationPositionFootType</type>
|
||||
</add-channel>
|
||||
<add-channel id="nightStandOutlet" groupIds="left,right">
|
||||
<type>sleepiq:nightStandOutletType</type>
|
||||
</add-channel>
|
||||
<add-channel id="underBedLight" groupIds="left,right">
|
||||
<type>sleepiq:underBedLightType</type>
|
||||
</add-channel>
|
||||
</instruction-set>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</update:update-descriptions>
|
||||
|
@ -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.*;
|
||||
|
||||
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.FoundationStatusResponse;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The {@link FoundationStatusResponseTest} tests deserialization of a foundation status
|
||||
* response object.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FoundationStatusResponseTest extends AbstractTest {
|
||||
private static Gson gson = GsonGenerator.create(true);
|
||||
|
||||
@Test
|
||||
public void testDeserializeAllFields() throws Exception {
|
||||
try (FileReader reader = new FileReader(getTestDataFile("foundation-status-response.json"))) {
|
||||
FoundationStatusResponse status = gson.fromJson(reader, FoundationStatusResponse.class);
|
||||
|
||||
assertNotNull(status);
|
||||
assertEquals(0x0f, status.getLeftHeadPosition());
|
||||
assertEquals(0x21, status.getLeftFootPosition());
|
||||
assertEquals(0x0d, status.getRightHeadPosition());
|
||||
assertEquals(0x04, status.getRightFootPosition());
|
||||
assertEquals(FoundationPreset.SNORE, status.getCurrentPositionPresetLeft());
|
||||
assertEquals(FoundationPreset.READ, status.getCurrentPositionPresetRight());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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 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.FoundationOutletRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutlet;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationOutletOperation;
|
||||
import org.openhab.binding.sleepiq.internal.api.impl.GsonGenerator;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* The {@link SetFoundationOutletTest} tests serialization of the foundation outlet request.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SetFoundationOutletTest extends AbstractTest {
|
||||
private static Gson gson = GsonGenerator.create(true);
|
||||
|
||||
@Test
|
||||
public void testSerializeAllFields() throws Exception {
|
||||
FoundationOutletRequest preset = new FoundationOutletRequest()
|
||||
.withFoundationOutlet(FoundationOutlet.RIGHT_UNDER_BED_LIGHT)
|
||||
.withFoundationOutletOperation(FoundationOutletOperation.ON);
|
||||
assertEquals(readJson("set-foundation-outlet.json"), gson.toJson(preset));
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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 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.FoundationPositionRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuator;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
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 SetFoundationPositionTest} tests serialization of the foundation position request.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SetFoundationPositionTest extends AbstractTest {
|
||||
private static Gson gson = GsonGenerator.create(true);
|
||||
|
||||
@Test
|
||||
public void testSerializeAllFields() throws Exception {
|
||||
FoundationPositionRequest preset = new FoundationPositionRequest().withSide(Side.RIGHT).withPosition(75)
|
||||
.withFoundationActuator(FoundationActuator.HEAD)
|
||||
.withFoundationActuatorSpeed(FoundationActuatorSpeed.FAST);
|
||||
assertEquals(readJson("set-foundation-position.json"), gson.toJson(preset));
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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 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.FoundationPresetRequest;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationActuatorSpeed;
|
||||
import org.openhab.binding.sleepiq.internal.api.enums.FoundationPreset;
|
||||
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 SetFoundationPresetTest} tests serialization of the foundation preset request.
|
||||
*
|
||||
* @author Mark Hilbush - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class SetFoundationPresetTest extends AbstractTest {
|
||||
private static Gson gson = GsonGenerator.create(true);
|
||||
|
||||
@Test
|
||||
public void testSerializeAllFields() throws Exception {
|
||||
FoundationPresetRequest preset = new FoundationPresetRequest().withSide(Side.RIGHT)
|
||||
.withFoundationPreset(FoundationPreset.WATCH_TV)
|
||||
.withFoundationActuatorSpeed(FoundationActuatorSpeed.FAST);
|
||||
assertEquals(readJson("set-foundation-preset.json"), gson.toJson(preset));
|
||||
}
|
||||
}
|
@ -34,17 +34,6 @@ import com.google.gson.Gson;
|
||||
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");
|
||||
|
@ -0,0 +1,30 @@
|
||||
{
|
||||
"fsType": "Single",
|
||||
"fsNeedsHoming": false,
|
||||
"fsIsMoving": false,
|
||||
"fsStatusSummary": "48",
|
||||
"fsConfigured": true,
|
||||
"fsCurrentPositionPreset": "66",
|
||||
"fsTimerPositionPreset": "00",
|
||||
|
||||
"fsCurrentPositionPresetLeft": "Snore",
|
||||
"fsLeftHeadPosition": "0f",
|
||||
"fsLeftFootPosition": "21",
|
||||
"fsLeftHeadActuatorMotorStatus": "08",
|
||||
"fsLeftFootActuatorMotorStatus": "00",
|
||||
"fsTimerPositionPresetLeft": "No timer running, thus no preset to active",
|
||||
"fsLeftPositionTimerMSB": "00",
|
||||
"fsLeftPositionTimerLSB": "00",
|
||||
|
||||
"fsCurrentPositionPresetRight": "Read",
|
||||
"fsRightHeadPosition": "0d",
|
||||
"fsRightFootPosition": "04",
|
||||
"fsRightHeadActuatorMotorStatus": "08",
|
||||
"fsRightFootActuatorMotorStatus": "00",
|
||||
"fsTimerPositionPresetRight": "No timer running, thus no preset to active",
|
||||
"fsRightPositionTimerMSB": "00",
|
||||
"fsRightPositionTimerLSB": "00",
|
||||
|
||||
"fsOutletsOn": true,
|
||||
"fsTimedOutletsOn": false
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
{
|
||||
"outletId": 3,
|
||||
"setting": 1
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"side": "R",
|
||||
"position": 75,
|
||||
"actuator": "H",
|
||||
"speed": 0
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{
|
||||
"side": "R",
|
||||
"preset": 3,
|
||||
"speed": 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user