Button dimmer now with new rest conversation scheme

This commit is contained in:
Claudio Maggioni 2020-03-13 18:20:16 +01:00
parent 7bb05b705f
commit 3a97d40858
14 changed files with 293 additions and 98 deletions

View file

@ -23,6 +23,7 @@ public class GsonConfig {
private Gson gson() {
final GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter());
builder.addSerializationExclusionStrategy(new AnnotationExclusionStrategy());
return builder.create();
}
}
@ -34,3 +35,16 @@ class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> {
return JsonParser.parseString(json.value());
}
}
/** GSON exclusion strategy to exclude attributes with @GsonExclude */
class AnnotationExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(GsonExclude.class) != null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}

View file

@ -0,0 +1,10 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface GsonExclude {}

View file

@ -2,11 +2,12 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.ButtonDimmerDimRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.ButtonDimmerSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmerRepository;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.util.List;
import java.util.Set;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -15,37 +16,74 @@ import org.springframework.web.bind.annotation.*;
@RestController
@EnableAutoConfiguration
@RequestMapping("/buttonDimmer")
public class ButtonDimmerController {
@Autowired private ButtonDimmerRepository buttonDimmerService;
public class ButtonDimmerController
extends InputDeviceConnectionController<ButtonDimmer, DimmableLight> {
private ButtonDimmerRepository buttonDimmerRepository;
private DimmableLightRepository dimmableLightRepository;
@Autowired
protected ButtonDimmerController(
ButtonDimmerRepository inputRepository, DimmableLightRepository outputRepository) {
super(inputRepository, outputRepository);
this.buttonDimmerRepository = inputRepository;
this.dimmableLightRepository = outputRepository;
}
@GetMapping
public List<ButtonDimmer> findAll() {
return toList(buttonDimmerService.findAll());
return toList(buttonDimmerRepository.findAll());
}
@GetMapping("/{id}")
public ButtonDimmer findById(@PathVariable("id") long id) throws NotFoundException {
return buttonDimmerService.findById(id).orElseThrow(NotFoundException::new);
return buttonDimmerRepository.findById(id).orElseThrow(NotFoundException::new);
}
@PostMapping
public ButtonDimmer create(@Valid @RequestBody final ButtonDimmerSaveRequest bd) {
ButtonDimmer newBD = new ButtonDimmer();
newBD.setLights(bd.getLights());
newBD.setId(bd.getId());
newBD.setName(bd.getName());
newBD.setRoomId(bd.getRoomId());
return buttonDimmerService.save(newBD);
return buttonDimmerRepository.save(newBD);
}
@PutMapping
public ButtonDimmer update(@Valid @RequestBody ButtonDimmerSaveRequest bd) {
return this.create(bd);
@PutMapping("/dim")
public Set<DimmableLight> dim(@Valid @RequestBody final ButtonDimmerDimRequest bd)
throws NotFoundException {
final ButtonDimmer buttonDimmer =
buttonDimmerRepository.findById(bd.getId()).orElseThrow(NotFoundException::new);
switch (bd.getDimType()) {
case UP:
buttonDimmer.increaseIntensity();
break;
case DOWN:
buttonDimmer.decreaseIntensity();
break;
}
dimmableLightRepository.saveAll(buttonDimmer.getLights());
return buttonDimmer.getOutputs();
}
@PostMapping("/{id}/lights")
public Set<DimmableLight> addLight(
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
throws NotFoundException {
return addOutput(inputId, lightId);
}
@DeleteMapping("/{id}/lights")
public Set<DimmableLight> removeLight(
@PathVariable("id") long inputId, @RequestParam("lightId") Long lightId)
throws NotFoundException {
return removeOutput(inputId, lightId);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") long id) {
buttonDimmerService.deleteById(id);
buttonDimmerRepository.deleteById(id);
}
}

View file

@ -33,19 +33,12 @@ public class DimmableLightController {
public DimmableLight create(@Valid @RequestBody DimmableLightSaveRequest dl) {
DimmableLight newDL = new DimmableLight();
newDL.setIntensity(dl.getIntensity());
newDL.setId(dl.getId());
newDL.setName(dl.getName());
newDL.setRoomId(dl.getRoomId());
return dimmableLightService.save(newDL);
}
@PutMapping
public DimmableLight update(@Valid @RequestBody DimmableLightSaveRequest dl) {
dl.setId(0);
return this.create(dl);
}
@DeleteMapping("/{id}")
public void delete(@PathVariable("id") long id) {
dimmableLightService.deleteById(id);

View file

@ -0,0 +1,81 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.util.Set;
/**
* An abstract controller for an input device that has output connected to it. Aids to create the
* output add and output remove route
*
* @param <I> the type of device this controller is for
* @param <O> the output device attached to I
*/
public abstract class InputDeviceConnectionController<
I extends InputDevice & OutputConnectable<O>,
O extends OutputDevice & InputConnectable<I>> {
private class IOPair {
private final I input;
private final O output;
private IOPair(I input, O output) {
this.input = input;
this.output = output;
}
}
private DeviceRepository<I> inputRepository;
private DeviceRepository<O> outputReposiory;
protected InputDeviceConnectionController(
DeviceRepository<I> inputRepository, DeviceRepository<O> outputRepository) {
this.inputRepository = inputRepository;
this.outputReposiory = outputRepository;
}
private IOPair checkConnectionIDs(Long inputId, Long outputId) throws NotFoundException {
final I input =
inputRepository
.findById(inputId)
.orElseThrow(() -> new NotFoundException("input device"));
final O output =
outputReposiory
.findById(outputId)
.orElseThrow(() -> new NotFoundException("output device"));
return new IOPair(input, output);
}
/**
* Implements the output device connection creation (add) route
*
* @param inputId input device id
* @param outputId output device id
* @return the list of output devices attached to the input device of id inputId
* @throws NotFoundException if inputId or outputId are not valid
*/
protected Set<O> addOutput(Long inputId, Long outputId) throws NotFoundException {
final IOPair pair = checkConnectionIDs(inputId, outputId);
pair.input.getOutputs().add(pair.output);
pair.output.connect(pair.input.getId());
outputReposiory.save(pair.output);
return pair.input.getOutputs();
}
/**
* Implements the output device connection destruction (remove) route
*
* @param inputId input device id
* @param outputId output device id
* @return the list of output devices attached to the input device of id inputId
* @throws NotFoundException if inputId or outputId are not valid
*/
protected Set<O> removeOutput(Long inputId, Long outputId) throws NotFoundException {
final IOPair pair = checkConnectionIDs(inputId, outputId);
pair.input.getOutputs().remove(pair.output);
pair.output.connect(null);
outputReposiory.save(pair.output);
return pair.input.getOutputs();
}
}

View file

@ -0,0 +1,34 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.NotNull;
/** A 'dim' event from a button dimmer. */
public class ButtonDimmerDimRequest {
/** The device id */
@NotNull private Long id;
public enum DimType {
UP,
DOWN;
}
/** Whether the dim is up or down */
@NotNull private DimType dimType;
public DimType getDimType() {
return dimType;
}
public void setDimType(DimType dimType) {
this.dimType = dimType;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}

View file

@ -1,21 +1,8 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
public class ButtonDimmerSaveRequest {
@Lob private Set<DimmableLight> lights = new HashSet<DimmableLight>();
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
@ -25,18 +12,6 @@ public class ButtonDimmerSaveRequest {
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public Set<DimmableLight> getLights() {
return this.lights;
}
public void setLights(Set<DimmableLight> newLights) {
this.lights = newLights;
}
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
@ -45,14 +20,6 @@ public class ButtonDimmerSaveRequest {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
@ -60,8 +27,4 @@ public class ButtonDimmerSaveRequest {
public String getName() {
return name;
}
public void setId(long id) {
this.id = id;
}
}

View file

@ -1,6 +1,5 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Room;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@ -13,12 +12,6 @@ public class DimmableLightSaveRequest {
@Max(100)
private Integer intensity = 0;
/** Device identifier */
private long id;
/** The room this device belongs in */
private Room room;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
@ -28,10 +21,6 @@ public class DimmableLightSaveRequest {
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setRoom(Room room) {
this.room = room;
}
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
@ -40,14 +29,6 @@ public class DimmableLightSaveRequest {
this.name = name;
}
public long getId() {
return id;
}
public Room getRoom() {
return room;
}
public Long getRoomId() {
return roomId;
}
@ -60,14 +41,7 @@ public class DimmableLightSaveRequest {
return intensity;
}
public void setIntensity(Integer intensity) throws IllegalArgumentException {
if (intensity < 0 || intensity > 100) {
throw new IllegalArgumentException("The intensity level can't go below 0 or above 100");
}
public void setIntensity(Integer intensity) {
this.intensity = intensity;
}
public void setId(long id) {
this.id = id;
}
}

View file

@ -6,6 +6,10 @@ import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class NotFoundException extends Exception {
public NotFoundException() {
super("Not Found");
super("Not found");
}
public NotFoundException(String what) {
super(what + " not found");
}
}

View file

@ -1,6 +1,5 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
@ -10,7 +9,10 @@ import javax.persistence.OneToMany;
* dimmer with a '+' and a '-' button)
*/
@Entity
public class ButtonDimmer extends Dimmer {
public class ButtonDimmer extends Dimmer implements OutputConnectable<DimmableLight> {
/** The delta amount to apply to a increase or decrease intensity */
public static final int DIM_INCREMENT = 10;
public ButtonDimmer() {
super("button-dimmer");
}
@ -18,17 +20,19 @@ public class ButtonDimmer extends Dimmer {
@OneToMany(mappedBy = "dimmer")
private Set<DimmableLight> lights;
/** Increases the current intensity level of the dimmable light by 1 */
/** Increases the current intensity level of the dimmable light by DIM_INCREMENT */
public void increaseIntensity() {
for (DimmableLight dl : lights) {
dl.setIntensity(dl.getIntensity() + 1);
dl.setIntensity(dl.getIntensity() + DIM_INCREMENT);
System.out.println("malusa: " + dl.getIntensity());
}
}
/** Decreases the current intensity level of the dimmable light by 1 */
/** Decreases the current intensity level of the dimmable light by DIM_INCREMENT */
public void decreaseIntensity() {
for (DimmableLight dl : lights) {
dl.setIntensity(dl.getIntensity() - 1);
dl.setIntensity(dl.getIntensity() - DIM_INCREMENT);
System.out.println("malusa: " + dl.getIntensity());
}
}
@ -64,6 +68,11 @@ public class ButtonDimmer extends Dimmer {
return this.lights;
}
@Override
public Set<DimmableLight> getOutputs() {
return this.lights;
}
public void setLights(Set<DimmableLight> newLights) {
this.lights = newLights;
}

View file

@ -1,7 +1,9 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
@ -9,18 +11,24 @@ import javax.validation.constraints.NotNull;
/** Represent a dimmable light */
@Entity
public class DimmableLight extends Light {
public class DimmableLight extends Light implements InputConnectable<ButtonDimmer> {
public DimmableLight() {
super("light");
}
@ManyToOne private Dimmer dimmer;
@ManyToOne
@GsonExclude
@JoinColumn(name = "dimmer_id", updatable = false, insertable = false)
private Dimmer dimmer;
@Column(name = "dimmer_id")
private Long dimmerId;
/** The light intensity value. Goes from 0 (off) to 100 (on) */
@NotNull
@Column(nullable = false)
@Min(1)
@Min(0)
@Max(100)
private Integer intensity = 0;
@ -28,10 +36,39 @@ public class DimmableLight extends Light {
return intensity;
}
public void setIntensity(Integer intensity) throws IllegalArgumentException {
if (intensity < 0 || intensity > 100) {
throw new IllegalArgumentException("The intensity level can't go below 0 or above 100");
/**
* Sets the intensity to a certain level. Out of bound values are corrected to the respective
* extremums. An intensity level of 0 turns the light off, but keeps the old intensity level
* stored.
*
* @param intensity the intensity level (may be out of bounds)
*/
public void setIntensity(Integer intensity) {
if (intensity <= 0) {
this.intensity = 0;
setOn(false);
} else {
setOn(true);
if (intensity > 100) {
this.intensity = 100;
} else {
this.intensity = intensity;
}
}
this.intensity = intensity;
}
@Override
public void setOn(boolean on) {
super.setOn(on);
if (on) {
intensity = 100;
} else {
intensity = 0;
}
}
@Override
public void connect(Long inputId) {
this.dimmerId = inputId;
}
}

View file

@ -0,0 +1,18 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
/**
* An output device to which an input can be connected
*
* @param <O> the type of input device that can be connected to this device
*/
public interface InputConnectable<O extends InputDevice> {
/**
* Connect an input device to this output device. This method should set the corresponding FK in
* the entity.
*
* @param inputId the input device id, null for deleting the connection
*/
void connect(Long inputId);
}

View file

@ -0,0 +1,18 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import java.util.Set;
/**
* An input device to which outputs can be connected
*
* @param <O> the type of output device that can be connected to this device
*/
public interface OutputConnectable<O extends OutputDevice> {
/**
* Get the set of all output devices connected to this device
*
* @return The set of outputs connected to this device
*/
Set<O> getOutputs();
}

View file

@ -42,6 +42,8 @@ public class Sensor extends InputDevice {
public void setSensor(SensorType sensor) {
this.sensor = sensor;
// TODO: setup hook for sockets live update
}
public int getValue() {