Added apply() method on State to change underlying device accordingly

This commit is contained in:
Claudio Maggioni (maggicl) 2020-04-15 23:08:57 +02:00
parent 6be999ffcc
commit 495c317eb8
18 changed files with 150 additions and 52 deletions

View file

@ -5,7 +5,6 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.service.ThermostatService;
import java.security.Principal;
import java.util.*;
import java.util.List;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
@ -42,10 +41,10 @@ public class ThermostatController {
newT.setUseExternalSensors(t.isUseExternalSensors());
if (t.isTurnOn()) {
newT.setState(Thermostat.ThermostatState.IDLE);
newT.setMode(Thermostat.Mode.IDLE);
thermostatService.computeState(newT);
} else {
newT.setState(Thermostat.ThermostatState.OFF);
newT.setMode(Thermostat.Mode.OFF);
}
newT = thermostatRepository.save(newT);

View file

@ -0,0 +1,13 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/**
* An IDimmable Device whose state can be set by a DimmableState of the corresponding type
* @param <T> the type of the class that extends this interface (just for type bounds, does not mean actually anything)
*/
public interface AlterableFromDimmableState<T extends OutputDevice & AlterableFromDimmableState<T>>
extends IDimmable, AlterableFromState<State<T>> {
default void readStateAndSet(State<T> state) {
final DimmableState<T> hack = (DimmableState<T>) state;
setDimAmount(hack.getDimAmount());
}
}

View file

@ -0,0 +1,6 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/** An OutputDevice whose state can be set by a State of corresponding device type */
public interface AlterableFromState<T extends State<? extends OutputDevice>> {
void readStateAndSet(T state);
}

View file

@ -0,0 +1,13 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/**
* An ISwitchable Device whose state can be set by a SwitchableState of the corresponding type
* @param <T> the type of the class that extends this interface (just for type bounds, does not mean actually anything)
*/
public interface AlterableFromSwitchableState<T extends OutputDevice & AlterableFromSwitchableState<T>>
extends ISwtichable, AlterableFromState<State<T>> {
default void readStateAndSet(State<T> state) {
final SwitchableState<T> hack = (SwitchableState<T>) state;
setOn(hack.isOn());
}
}

View file

@ -7,7 +7,7 @@ import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Entity
public class Curtains extends OutputDevice {
public class Curtains extends OutputDevice implements IDimmable, AlterableFromDimmableState<Curtains> {
/**
* it represents how much the curtains are opened, 0 is completely closed 100 is completely open
@ -38,4 +38,14 @@ public class Curtains extends OutputDevice {
this.openedAmount = newOpening;
}
}
@Override
public Integer getDimAmount() {
return getOpenedAmount();
}
@Override
public void setDimAmount(Integer intensity) {
setOpenedAmount(intensity);
}
}

View file

@ -11,7 +11,7 @@ import javax.validation.constraints.NotNull;
/** Represent a dimmable light */
@Entity
public class DimmableLight extends Switchable {
public class DimmableLight extends Switchable implements IDimmable, AlterableFromDimmableState<DimmableLight> {
public static final Connector<ButtonDimmer, DimmableLight>
BUTTON_DIMMER_DIMMABLE_LIGHT_CONNECTOR =
@ -86,4 +86,14 @@ public class DimmableLight extends Switchable {
super.setSwitchId(switchId);
this.dimmerId = null;
}
@Override
public Integer getDimAmount() {
return getIntensity();
}
@Override
public void setDimAmount(Integer intensity) {
setIntensity(intensity);
}
}

View file

@ -6,22 +6,22 @@ import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
/** Represent a dimmable light state */
/** Represent a state for an IDimmable device */
@Entity
public class DimmableLightState extends State {
public class DimmableState<T extends OutputDevice & AlterableFromState<State<T>>> extends State<T> {
/** The light intensity value. Goes from 0 (off) to 100 (on) */
@NotNull
@Column(nullable = false)
@Min(0)
@Max(100)
private Integer intensity = 0;
private Integer dimAmount = 0;
public Integer getIntensity() {
return intensity;
public Integer getDimAmount() {
return dimAmount;
}
public void setIntensity(Integer intensity) {
this.intensity = intensity;
public void setDimAmount(Integer dimAmount) {
this.dimAmount = dimAmount;
}
}

View file

@ -0,0 +1,10 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/**
* Although not totally enforced in code, it represents an OutputDevice that can be set a state (here "dimAmount")
* that ranges from 0 to 100
*/
public interface IDimmable {
Integer getDimAmount();
void setDimAmount(Integer intensity);
}

View file

@ -0,0 +1,20 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/** Interface equivalent of Switchable. Altough not totally enforced in code, it represents an OutputDevice that can be
* turned on or off
*/
public interface ISwtichable {
/**
* Returns whether the device is on (true) or not (false)
*
* @return whether the device is on (true) or not (false)
*/
boolean isOn();
/**
* Sets the on status of the device
*
* @param on the new on status: true for on, false for off
*/
void setOn(boolean on);
}

View file

@ -6,7 +6,7 @@ import javax.validation.constraints.NotNull;
/** Represents a standard non-dimmable light */
@Entity
public class RegularLight extends Switchable {
public class RegularLight extends Switchable implements AlterableFromSwitchableState<RegularLight> {
/** Whether the light is on or not */
@Column(name = "light_on", nullable = false)

View file

@ -5,7 +5,7 @@ import javax.persistence.Entity;
import javax.validation.constraints.NotNull;
@Entity
public class SecurityCamera extends Switchable {
public class SecurityCamera extends Switchable implements AlterableFromSwitchableState<SecurityCamera> {
public SecurityCamera() {
super("securityCamera");

View file

@ -7,7 +7,7 @@ import javax.validation.constraints.NotNull;
/** A smart plug that can be turned either on or off */
@Entity
public class SmartPlug extends Switchable {
public class SmartPlug extends Switchable implements AlterableFromSwitchableState<SmartPlug> {
/** The average consumption of an active plug when on in Watt */
public static final Double AVERAGE_CONSUMPTION_KW = 200.0;

View file

@ -2,6 +2,8 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
@ -11,7 +13,7 @@ import javax.validation.constraints.NotNull;
*/
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class State {
public abstract class State<D extends OutputDevice & AlterableFromState<State<D>>> {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@ -19,10 +21,10 @@ public abstract class State {
@ApiModelProperty(hidden = true)
private long id;
@ManyToOne
@ManyToOne(targetEntity = OutputDevice.class)
@JoinColumn(name = "device_id", updatable = false, insertable = false)
@GsonExclude
private Device device;
private D device;
/**
* The device this state belongs in, as a foreign key id. To use when updating and inserting
@ -41,6 +43,13 @@ public abstract class State {
@NotNull
private Long sceneId;
/**
* Sets the state of the connected device to the state represented by this object.
*/
public void apply() {
device.readStateAndSet(this);
}
public long getId() {
return id;
}
@ -49,11 +58,11 @@ public abstract class State {
this.id = id;
}
public Device getDevice() {
public D getDevice() {
return device;
}
public void setDevice(Device device) {
public void setDevice(D device) {
this.device = device;
}

View file

@ -6,7 +6,7 @@ import javax.persistence.*;
/** A device that can be turned either on or off */
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Switchable extends OutputDevice {
public abstract class Switchable extends OutputDevice implements ISwtichable {
public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR =
Connector.basic(Switch::getOutputs, Switchable::setSwitchId);
@ -23,20 +23,6 @@ public abstract class Switchable extends OutputDevice {
super(kind);
}
/**
* Returns whether the device is on (true) or not (false)
*
* @return whether the device is on (true) or not (false)
*/
public abstract boolean isOn();
/**
* Sets the on status of the device
*
* @param on the new on status: true for on, false for off
*/
public abstract void setOn(boolean on);
public Long getSwitchId() {
return switchId;
}

View file

@ -4,9 +4,9 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.validation.constraints.NotNull;
/** A state for RegularLight and SmartPlug */
/** Represents a state for a Switchable device */
@Entity
public class SwitchableState extends State {
public class SwitchableState<T extends OutputDevice & AlterableFromState<State<T>>> extends State<T> {
@Column(name = "switchable_on", nullable = false)
@NotNull

View file

@ -9,9 +9,15 @@ import javax.validation.constraints.NotNull;
/** A thermostat capable of controlling cooling and heating. */
@Entity
public class Thermostat extends OutputDevice {
public class Thermostat extends OutputDevice implements AlterableFromState<State<Thermostat>> {
public enum ThermostatState {
@Override
public void readStateAndSet(State<Thermostat> state) {
final ThermostatState hack = (ThermostatState) state;
setMode(hack.getMode());
}
public enum Mode {
@SerializedName("OFF")
OFF,
@SerializedName("IDLE")
@ -31,7 +37,7 @@ public class Thermostat extends OutputDevice {
Sensor.TYPICAL_VALUES.get(Sensor.SensorType.TEMPERATURE);
/** State of this thermostat */
@Column @NotNull private ThermostatState state;
@Column @NotNull private Thermostat.Mode mode;
@Transient private BigDecimal measuredTemperature;
@ -40,15 +46,15 @@ public class Thermostat extends OutputDevice {
/** Creates a thermostat with a temperature sensor and its initial OFF state */
public Thermostat() {
super("thermostat");
this.state = ThermostatState.OFF;
this.mode = Mode.OFF;
}
public void setState(ThermostatState state) {
this.state = state;
public void setMode(Mode state) {
this.mode = state;
}
public ThermostatState getState() {
return this.state;
public Mode getMode() {
return this.mode;
}
public BigDecimal getTargetTemperature() {

View file

@ -0,0 +1,16 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import javax.persistence.Entity;
@Entity
public class ThermostatState extends State<Thermostat> {
private Thermostat.Mode mode;
public Thermostat.Mode getMode() {
return mode;
}
public void setMode(Thermostat.Mode mode) {
this.mode = mode;
}
}

View file

@ -43,7 +43,7 @@ public class ThermostatService {
}
public boolean computeState(Thermostat t) {
if (t.getState() == Thermostat.ThermostatState.OFF) {
if (t.getMode() == Thermostat.Mode.OFF) {
return false;
}
@ -53,14 +53,14 @@ public class ThermostatService {
BigDecimal delta = target.subtract(measured);
if (delta.abs().doubleValue() < 0.25) {
if (t.getState() == Thermostat.ThermostatState.IDLE) return false;
t.setState(Thermostat.ThermostatState.IDLE);
if (t.getMode() == Thermostat.Mode.IDLE) return false;
t.setMode(Thermostat.Mode.IDLE);
} else if (delta.signum() > 0) {
if (t.getState() == Thermostat.ThermostatState.HEATING) return false;
t.setState(Thermostat.ThermostatState.HEATING);
if (t.getMode() == Thermostat.Mode.HEATING) return false;
t.setMode(Thermostat.Mode.HEATING);
} else {
if (t.getState() == Thermostat.ThermostatState.COOLING) return false;
t.setState(Thermostat.ThermostatState.COOLING);
if (t.getMode() == Thermostat.Mode.COOLING) return false;
t.setMode(Thermostat.Mode.COOLING);
}
return true;