Merge branch '58-allow-many-input-devices-to-connect-to-many-output-devices' into 'dev'

Resolve "Allow many input devices to connect to many output devices"

Closes #58

See merge request sa4-2020/the-sanmarinoes/backend!78
This commit is contained in:
Claudio Maggioni 2020-04-16 18:38:28 +02:00
commit 895c5015b1
34 changed files with 224 additions and 428 deletions

View file

@ -18,19 +18,19 @@ import org.springframework.web.bind.annotation.*;
@EnableAutoConfiguration @EnableAutoConfiguration
@RequestMapping("/buttonDimmer") @RequestMapping("/buttonDimmer")
public class ButtonDimmerController public class ButtonDimmerController
extends InputDeviceConnectionController<ButtonDimmer, DimmableLight> { extends InputDeviceConnectionController<ButtonDimmer, Dimmable> {
private ButtonDimmerRepository buttonDimmerRepository; private ButtonDimmerRepository buttonDimmerRepository;
private DimmableLightRepository dimmableLightRepository; private DimmableRepository<Dimmable> dimmableRepository;
@Autowired @Autowired
protected ButtonDimmerController( protected ButtonDimmerController(
ButtonDimmerRepository inputRepository, DimmableLightRepository outputRepository) { ButtonDimmerRepository inputRepository, DimmableRepository<Dimmable> outputRepository) {
super( super(
inputRepository, inputRepository,
outputRepository, outputRepository,
DimmableLight.BUTTON_DIMMER_DIMMABLE_LIGHT_CONNECTOR); DimmableLight.BUTTON_DIMMER_DIMMABLE_CONNECTOR);
this.buttonDimmerRepository = inputRepository; this.buttonDimmerRepository = inputRepository;
this.dimmableLightRepository = outputRepository; this.dimmableRepository = outputRepository;
} }
@GetMapping @GetMapping
@ -53,7 +53,7 @@ public class ButtonDimmerController
} }
@PutMapping("/dim") @PutMapping("/dim")
public Set<DimmableLight> dim( public Set<Dimmable> dim(
@Valid @RequestBody final ButtonDimmerDimRequest bd, final Principal principal) @Valid @RequestBody final ButtonDimmerDimRequest bd, final Principal principal)
throws NotFoundException { throws NotFoundException {
final ButtonDimmer buttonDimmer = final ButtonDimmer buttonDimmer =
@ -70,25 +70,11 @@ public class ButtonDimmerController
break; break;
} }
dimmableLightRepository.saveAll(buttonDimmer.getOutputs()); dimmableRepository.saveAll(buttonDimmer.getOutputs());
return buttonDimmer.getOutputs(); return buttonDimmer.getOutputs();
} }
@PostMapping("/{id}/lights")
public Set<? extends OutputDevice> addLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return addOutput(inputId, lightId);
}
@DeleteMapping("/{id}/lights")
public Set<? extends OutputDevice> removeLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return removeOutput(inputId, lightId);
}
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public void delete(@PathVariable("id") long id) { public void delete(@PathVariable("id") long id) {
buttonDimmerRepository.deleteById(id); buttonDimmerRepository.deleteById(id);

View file

@ -2,7 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.CurtainsSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.DimmableSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Curtains; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Curtains;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.CurtainsRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.CurtainsRepository;
@ -28,21 +28,21 @@ public class CurtainsController {
return curtainsService.findById(id).orElseThrow(NotFoundException::new); return curtainsService.findById(id).orElseThrow(NotFoundException::new);
} }
private Curtains save(Curtains newRL, CurtainsSaveRequest s) { private Curtains save(Curtains newRL, DimmableSaveRequest s) {
newRL.setName(s.getName()); newRL.setName(s.getName());
newRL.setRoomId(s.getRoomId()); newRL.setRoomId(s.getRoomId());
newRL.setOpenedAmount(s.getOpening()); newRL.setIntensity(s.getIntensity());
return curtainsService.save(newRL); return curtainsService.save(newRL);
} }
@PostMapping @PostMapping
public Curtains create(@Valid @RequestBody CurtainsSaveRequest curtain) { public Curtains create(@Valid @RequestBody DimmableSaveRequest curtain) {
return save(new Curtains(), curtain); return save(new Curtains(), curtain);
} }
@PutMapping @PutMapping
public Curtains update(@Valid @RequestBody CurtainsSaveRequest curtain) public Curtains update(@Valid @RequestBody DimmableSaveRequest curtain)
throws NotFoundException { throws NotFoundException {
return save( return save(
curtainsService.findById(curtain.getId()).orElseThrow(NotFoundException::new), curtainsService.findById(curtain.getId()).orElseThrow(NotFoundException::new),

View file

@ -2,7 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.DimmableLightSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.DimmableSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLightRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLightRepository;
@ -30,7 +30,7 @@ public class DimmableLightController {
return dimmableLightService.findById(id).orElseThrow(NotFoundException::new); return dimmableLightService.findById(id).orElseThrow(NotFoundException::new);
} }
private DimmableLight save(DimmableLight initial, DimmableLightSaveRequest dl) { private DimmableLight save(DimmableLight initial, DimmableSaveRequest dl) {
initial.setIntensity(dl.getIntensity()); initial.setIntensity(dl.getIntensity());
initial.setName(dl.getName()); initial.setName(dl.getName());
initial.setRoomId(dl.getRoomId()); initial.setRoomId(dl.getRoomId());
@ -39,13 +39,13 @@ public class DimmableLightController {
} }
@PostMapping @PostMapping
public DimmableLight create(@Valid @RequestBody DimmableLightSaveRequest dl) { public DimmableLight create(@Valid @RequestBody DimmableSaveRequest dl) {
return save(new DimmableLight(), dl); return save(new DimmableLight(), dl);
} }
@PutMapping @PutMapping
public DimmableLight update( public DimmableLight update(
@Valid @RequestBody DimmableLightSaveRequest sp, final Principal principal) @Valid @RequestBody DimmableSaveRequest sp, final Principal principal)
throws NotFoundException { throws NotFoundException {
return save( return save(
dimmableLightService dimmableLightService

View file

@ -2,10 +2,18 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
/** /**
* An abstract controller for an input device that has output connected to it. Aids to create the * An abstract controller for an input device that has output connected to it. Aids to create the
* output add and output remove route * output add and output remove route
@ -103,4 +111,18 @@ public abstract class InputDeviceConnectionController<
outputReposiory.saveAll(pair.output); outputReposiory.saveAll(pair.output);
return pair.input.getOutputs(); return pair.input.getOutputs();
} }
@PostMapping("/{id}/lights")
public List<OutputDevice> addLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return toList(addOutput(inputId, lightId));
}
@DeleteMapping("/{id}/lights")
public List<OutputDevice> removeLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return toList(removeOutput(inputId, lightId));
}
} }

View file

@ -18,20 +18,20 @@ import org.springframework.web.bind.annotation.*;
@EnableAutoConfiguration @EnableAutoConfiguration
@RequestMapping("/knobDimmer") @RequestMapping("/knobDimmer")
public class KnobDimmerController public class KnobDimmerController
extends InputDeviceConnectionController<KnobDimmer, DimmableLight> { extends InputDeviceConnectionController<KnobDimmer, Dimmable> {
@Autowired private KnobDimmerRepository knobDimmerRepository; @Autowired private KnobDimmerRepository knobDimmerRepository;
@Autowired private DimmableLightRepository dimmableLightRepository; @Autowired private DimmableRepository<Dimmable> dimmableRepository;
@Autowired @Autowired
protected KnobDimmerController( protected KnobDimmerController(
KnobDimmerRepository inputRepository, DimmableLightRepository outputRepository) { KnobDimmerRepository inputRepository, DimmableRepository<Dimmable> outputRepository) {
super( super(
inputRepository, inputRepository,
outputRepository, outputRepository,
DimmableLight.KNOB_DIMMER_DIMMABLE_LIGHT_CONNECTOR); Dimmable.KNOB_DIMMER_DIMMABLE_CONNECTOR);
this.knobDimmerRepository = inputRepository; this.knobDimmerRepository = inputRepository;
this.dimmableLightRepository = outputRepository; this.dimmableRepository = outputRepository;
} }
@GetMapping @GetMapping
@ -54,7 +54,7 @@ public class KnobDimmerController
} }
@PutMapping("/dimTo") @PutMapping("/dimTo")
public Set<DimmableLight> dimTo( public Set<Dimmable> dimTo(
@Valid @RequestBody final KnobDimmerDimRequest bd, final Principal principal) @Valid @RequestBody final KnobDimmerDimRequest bd, final Principal principal)
throws NotFoundException { throws NotFoundException {
final KnobDimmer dimmer = final KnobDimmer dimmer =
@ -63,25 +63,11 @@ public class KnobDimmerController
.orElseThrow(NotFoundException::new); .orElseThrow(NotFoundException::new);
dimmer.setLightIntensity(bd.getIntensity()); dimmer.setLightIntensity(bd.getIntensity());
dimmableLightRepository.saveAll(dimmer.getOutputs()); dimmableRepository.saveAll(dimmer.getOutputs());
return dimmer.getOutputs(); return dimmer.getOutputs();
} }
@PostMapping("/{id}/lights")
public Set<? extends OutputDevice> addLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return addOutput(inputId, lightId);
}
@DeleteMapping("/{id}/lights")
public Set<? extends OutputDevice> removeLight(
@PathVariable("id") long inputId, @RequestBody List<Long> lightId)
throws NotFoundException {
return removeOutput(inputId, lightId);
}
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public void delete(@PathVariable("id") long id) { public void delete(@PathVariable("id") long id) {
knobDimmerRepository.deleteById(id); knobDimmerRepository.deleteById(id);

View file

@ -2,7 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.RegularLightSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchableSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLightRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.RegularLightRepository;
@ -37,7 +37,7 @@ public class RegularLightController {
return regularLightService.findById(id).orElseThrow(NotFoundException::new); return regularLightService.findById(id).orElseThrow(NotFoundException::new);
} }
private RegularLight save(RegularLight newRL, RegularLightSaveRequest rl) { private RegularLight save(RegularLight newRL, SwitchableSaveRequest rl) {
newRL.setName(rl.getName()); newRL.setName(rl.getName());
newRL.setRoomId(rl.getRoomId()); newRL.setRoomId(rl.getRoomId());
newRL.setOn(rl.isOn()); newRL.setOn(rl.isOn());
@ -46,13 +46,13 @@ public class RegularLightController {
} }
@PostMapping @PostMapping
public RegularLight create(@Valid @RequestBody RegularLightSaveRequest rl) { public RegularLight create(@Valid @RequestBody SwitchableSaveRequest rl) {
return save(new RegularLight(), rl); return save(new RegularLight(), rl);
} }
@PutMapping @PutMapping
public RegularLight update( public RegularLight update(
@Valid @RequestBody RegularLightSaveRequest rl, final Principal principal) @Valid @RequestBody SwitchableSaveRequest rl, final Principal principal)
throws NotFoundException { throws NotFoundException {
return save( return save(
regularLightService regularLightService

View file

@ -2,7 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SecurityCameraSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchableSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SecurityCamera; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SecurityCamera;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SecurityCameraRepository; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.SecurityCameraRepository;
@ -37,7 +37,7 @@ public class SecurityCameraController {
return securityCameraService.findById(id).orElseThrow(NotFoundException::new); return securityCameraService.findById(id).orElseThrow(NotFoundException::new);
} }
private SecurityCamera save(SecurityCamera newSC, SecurityCameraSaveRequest sc) { private SecurityCamera save(SecurityCamera newSC, SwitchableSaveRequest sc) {
newSC.setName(sc.getName()); newSC.setName(sc.getName());
newSC.setRoomId(sc.getRoomId()); newSC.setRoomId(sc.getRoomId());
newSC.setOn(sc.isOn()); newSC.setOn(sc.isOn());
@ -46,13 +46,13 @@ public class SecurityCameraController {
} }
@PostMapping @PostMapping
public SecurityCamera create(@Valid @RequestBody SecurityCameraSaveRequest sc) { public SecurityCamera create(@Valid @RequestBody SwitchableSaveRequest sc) {
return save(new SecurityCamera(), sc); return save(new SecurityCamera(), sc);
} }
@PutMapping @PutMapping
public SecurityCamera update( public SecurityCamera update(
@Valid @RequestBody SecurityCameraSaveRequest sc, final Principal principal) @Valid @RequestBody SwitchableSaveRequest sc, final Principal principal)
throws NotFoundException { throws NotFoundException {
return save( return save(
securityCameraService securityCameraService

View file

@ -2,11 +2,10 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.controller;
import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList; import static ch.usi.inf.sa4.sanmarinoes.smarthut.utils.Utils.toList;
import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SmartPlugSaveRequest; import ch.usi.inf.sa4.sanmarinoes.smarthut.dto.SwitchableSaveRequest;
import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException; import ch.usi.inf.sa4.sanmarinoes.smarthut.error.NotFoundException;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.security.Principal; import java.security.Principal;
import java.util.*;
import java.util.List; import java.util.List;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -30,7 +29,7 @@ public class SmartPlugController {
return smartPlugRepository.findById(id).orElseThrow(NotFoundException::new); return smartPlugRepository.findById(id).orElseThrow(NotFoundException::new);
} }
private SmartPlug save(SmartPlug newSP, SmartPlugSaveRequest sp) { private SmartPlug save(SmartPlug newSP, SwitchableSaveRequest sp) {
newSP.setOn(sp.isOn()); newSP.setOn(sp.isOn());
newSP.setId(sp.getId()); newSP.setId(sp.getId());
newSP.setName(sp.getName()); newSP.setName(sp.getName());
@ -40,12 +39,12 @@ public class SmartPlugController {
} }
@PostMapping @PostMapping
public SmartPlug create(@Valid @RequestBody SmartPlugSaveRequest sp) { public SmartPlug create(@Valid @RequestBody SwitchableSaveRequest sp) {
return save(new SmartPlug(), sp); return save(new SmartPlug(), sp);
} }
@PutMapping @PutMapping
public SmartPlug update(@Valid @RequestBody SmartPlugSaveRequest sp, final Principal principal) public SmartPlug update(@Valid @RequestBody SwitchableSaveRequest sp, final Principal principal)
throws NotFoundException { throws NotFoundException {
return save( return save(
smartPlugRepository smartPlugRepository

View file

@ -9,6 +9,7 @@ import ch.usi.inf.sa4.sanmarinoes.smarthut.models.*;
import java.security.Principal; import java.security.Principal;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.*;
@ -81,20 +82,6 @@ public class SwitchController extends InputDeviceConnectionController<Switch, Sw
return s.getOutputs(); return s.getOutputs();
} }
@PostMapping("/{id}/lights")
public Set<? extends OutputDevice> addSwitchable(
@PathVariable("id") long inputId, @RequestBody List<Long> switchableId)
throws NotFoundException {
return addOutput(inputId, switchableId);
}
@DeleteMapping("/{id}/lights")
public Set<? extends OutputDevice> removeSwitchable(
@PathVariable("id") long inputId, @RequestBody List<Long> switchableId)
throws NotFoundException {
return removeOutput(inputId, switchableId);
}
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
public void deleteById(@PathVariable("id") long id) { public void deleteById(@PathVariable("id") long id) {
switchRepository.deleteById(id); switchRepository.deleteById(id);

View file

@ -1,57 +0,0 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
public class CurtainsSaveRequest {
/** The state of this switch */
@NotNull
@Min(0)
@Max(100)
private int openedAmount;
/** Device identifier */
@NotNull private long id;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public int getOpening() {
return this.openedAmount;
}
public void setOpening(int newOpening) {
this.openedAmount = newOpening;
}
public void setId(long id) {
this.id = id;
}
}

View file

@ -4,10 +4,10 @@ import javax.validation.constraints.Max;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
public class DimmableLightSaveRequest { public class DimmableSaveRequest {
/** Device id (used only for update requests) */ /** Device id (used only for update requests) */
private Long id; private long id;
/** The light intensity value. Goes from 0 (off) to 100 (on) */ /** The light intensity value. Goes from 0 (off) to 100 (on) */
@NotNull @NotNull
@ -48,11 +48,11 @@ public class DimmableLightSaveRequest {
this.intensity = intensity; this.intensity = intensity;
} }
public Long getId() { public long getId() {
return id; return id;
} }
public void setId(Long id) { public void setId(long id) {
this.id = id; this.id = id;
} }
} }

View file

@ -1,53 +0,0 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.NotNull;
public class SecurityCameraSaveRequest {
/** The state of this Security Camera */
private boolean on;
/** Device identifier */
private Long id;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
public void setId(long id) {
this.id = id;
}
}

View file

@ -1,52 +0,0 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.NotNull;
public class SmartPlugSaveRequest {
/** Whether the smart plug is on */
@NotNull private boolean on;
/** Device identifier */
private long id;
/**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from
* a REST call.
*/
@NotNull private Long roomId;
/** The name of the device as assigned by the user (e.g. 'Master bedroom light') */
@NotNull private String name;
public void setRoomId(Long roomId) {
this.roomId = roomId;
}
public void setName(String name) {
this.name = name;
}
public long getId() {
return id;
}
public Long getRoomId() {
return roomId;
}
public String getName() {
return name;
}
public boolean isOn() {
return on;
}
public void setOn(boolean on) {
this.on = on;
}
public void setId(long id) {
this.id = id;
}
}

View file

@ -2,12 +2,12 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.dto;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
public class RegularLightSaveRequest { public class SwitchableSaveRequest {
/** The state of this switch */ /** The state of this switch */
private boolean on; private boolean on;
/** Device identifier */ /** Device identifier */
private Long id; private long id;
/** /**
* The room this device belongs in, as a foreign key id. To use when updating and inserting from * The room this device belongs in, as a foreign key id. To use when updating and inserting from

View file

@ -18,14 +18,14 @@ public class ButtonDimmer extends Dimmer {
/** Increases the current intensity level of the dimmable light by DIM_INCREMENT */ /** Increases the current intensity level of the dimmable light by DIM_INCREMENT */
public void increaseIntensity() { public void increaseIntensity() {
for (DimmableLight dl : getOutputs()) { for (Dimmable dl : getOutputs()) {
dl.setIntensity(dl.getIntensity() + DIM_INCREMENT); dl.setIntensity(dl.getIntensity() + DIM_INCREMENT);
} }
} }
/** Decreases the current intensity level of the dimmable light by DIM_INCREMENT */ /** Decreases the current intensity level of the dimmable light by DIM_INCREMENT */
public void decreaseIntensity() { public void decreaseIntensity() {
for (DimmableLight dl : getOutputs()) { for (Dimmable dl : getOutputs()) {
dl.setIntensity(dl.getIntensity() - DIM_INCREMENT); dl.setIntensity(dl.getIntensity() - DIM_INCREMENT);
} }
} }

View file

@ -23,25 +23,25 @@ public interface Connector<I extends InputDevice, O extends OutputDevice> {
void connect(I input, O output, boolean connect); void connect(I input, O output, boolean connect);
/** /**
* Produces a basic implementation of a connector, assuming there is a OneToMany relationship * Produces a basic implementation of a connector, assuming there is a ManyToMany relationship
* between J and K * between J and K
* *
* @param outputsGetter the getter method of the set of outputs on the input class * @param outputsGetter the getter method of the set of outputs on the input class
* @param inputSetter the setter method for the input id on the output class * @param inputsGetter the getter method of the set of outputs on the input class
* @param <J> the input device type * @param <J> the input device type
* @param <K> the output device type * @param <K> the output device type
* @return a Connector implementation for the pair of types J and K * @return a Connector implementation for the pair of types J and K
*/ */
static <J extends InputDevice, K extends OutputDevice> Connector<J, K> basic( static <J extends InputDevice, K extends OutputDevice> Connector<J, K> basic(
Function<J, Set<? super K>> outputsGetter, BiConsumer<K, Long> inputSetter) { Function<J, Set<? super K>> outputsGetter, Function<K, Set<? super J>> inputsGetter) {
return (i, o, connect) -> { return (i, o, connect) -> {
if (connect) { if (connect) {
outputsGetter.apply(i).add(o); outputsGetter.apply(i).add(o);
inputsGetter.apply(o).add(i);
} else { } else {
outputsGetter.apply(i).remove(o); outputsGetter.apply(i).remove(o);
inputsGetter.apply(o).remove(i);
} }
inputSetter.accept(o, connect ? i.getId() : null);
}; };
} }
} }

View file

@ -1,41 +1,14 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Entity
public class Curtains extends OutputDevice {
/** /**
* it represents how much the curtains are opened, 0 is completely closed 100 is completely open * Represents a curtain. The intensity represents how much the curtains are opened,
* 0 is completely closed 100 is completely open
*/ */
@NotNull @Entity
@Column(nullable = false) public class Curtains extends Dimmable {
@Min(0)
@Max(100)
private int openedAmount;
public Curtains() { public Curtains() {
super("curtains"); super("curtains");
this.openedAmount = 0;
}
/** return the current state of the curtain */
public int getOpenedAmount() {
return this.openedAmount;
}
/** sets the state to a desired one */
public void setOpenedAmount(int newOpening) {
if (newOpening < 0) {
this.openedAmount = 0;
} else if (newOpening > 100) {
this.openedAmount = 100;
} else {
this.openedAmount = newOpening;
}
} }
} }

View file

@ -1,3 +1,3 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
public interface CurtainsRepository extends DeviceRepository<Curtains> {} public interface CurtainsRepository extends DimmableRepository<Curtains> {}

View file

@ -8,7 +8,7 @@ import javax.validation.constraints.NotNull;
/** Generic abstraction for a smart home device */ /** Generic abstraction for a smart home device */
@Entity @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.JOINED)
public abstract class Device { public abstract class Device {
/** Ways a device can behave in the automation flow. For now only input/output */ /** Ways a device can behave in the automation flow. For now only input/output */

View file

@ -0,0 +1,78 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import java.util.Set;
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Dimmable extends Switchable {
public static final Connector<KnobDimmer, Dimmable>
KNOB_DIMMER_DIMMABLE_CONNECTOR =
Connector.basic(KnobDimmer::getOutputs, Dimmable::getDimmers);
public static final Connector<ButtonDimmer, Dimmable>
BUTTON_DIMMER_DIMMABLE_CONNECTOR =
Connector.basic(ButtonDimmer::getOutputs, Dimmable::getDimmers);
protected Dimmable(String kind) {
super(kind);
}
@ManyToMany(mappedBy = "dimmables", cascade = CascadeType.DETACH)
@GsonExclude
private Set<Dimmer> dimmers;
/** The light intensity value. Goes from 0 (off) to 100 (on) */
@NotNull
@Column(nullable = false)
@Min(0)
@Max(100)
private Integer intensity = 0;
@NotNull
@Column(nullable = false)
private Integer oldIntensity = 100;
public Integer getIntensity() {
return intensity;
}
/**
* 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;
} else if (intensity > 100) {
this.intensity = 100;
this.oldIntensity = 100;
} else {
this.intensity = intensity;
this.oldIntensity = intensity;
}
}
@Override
public boolean isOn() {
return intensity != 0;
}
@Override
public void setOn(boolean on) {
intensity = on ? oldIntensity : 0;
}
public Set<Dimmer> getDimmers() {
return this.dimmers;
}
}

View file

@ -1,89 +1,11 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; import javax.persistence.*;
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;
import javax.validation.constraints.NotNull;
/** Represent a dimmable light */ /** Represent a dimmable light */
@Entity @Entity
public class DimmableLight extends Switchable { public class DimmableLight extends Dimmable {
public static final Connector<ButtonDimmer, DimmableLight>
BUTTON_DIMMER_DIMMABLE_LIGHT_CONNECTOR =
Connector.basic(ButtonDimmer::getOutputs, DimmableLight::setDimmerId);
public static final Connector<KnobDimmer, DimmableLight> KNOB_DIMMER_DIMMABLE_LIGHT_CONNECTOR =
Connector.basic(KnobDimmer::getOutputs, DimmableLight::setDimmerId);
public DimmableLight() { public DimmableLight() {
super("dimmableLight"); super("dimmableLight");
} }
@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(0)
@Max(100)
private Integer intensity = 0;
@NotNull
@Column(nullable = false)
private Integer oldIntensity = 100;
public Integer getIntensity() {
return intensity;
}
/**
* 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;
} else if (intensity > 100) {
this.intensity = 100;
this.oldIntensity = 100;
} else {
this.intensity = intensity;
this.oldIntensity = intensity;
}
}
@Override
public boolean isOn() {
return intensity != 0;
}
@Override
public void setOn(boolean on) {
intensity = on ? oldIntensity : 0;
}
public void setDimmerId(Long dimmerId) {
this.dimmerId = dimmerId;
super.setSwitchId(null);
}
@Override
public void setSwitchId(Long switchId) {
super.setSwitchId(switchId);
this.dimmerId = null;
}
} }

View file

@ -1,3 +1,3 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
public interface DimmableLightRepository extends SwitchableRepository<DimmableLight> {} public interface DimmableLightRepository extends DimmableRepository<DimmableLight> {}

View file

@ -0,0 +1,4 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
public interface DimmableRepository<T extends Dimmable> extends SwitchableRepository<T> {
}

View file

@ -1,12 +1,10 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.persistence.Entity; import javax.persistence.*;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.OneToMany;
import javax.persistence.PreRemove;
/** Represents a generic dimmer input device */ /** Represents a generic dimmer input device */
@Entity @Entity
@ -16,8 +14,14 @@ public abstract class Dimmer extends InputDevice {
super(kind); super(kind);
} }
@OneToMany(mappedBy = "dimmer") @ManyToMany(cascade = CascadeType.DETACH)
private Set<DimmableLight> lights = new HashSet<>(); @GsonExclude
@JoinTable(
name = "dimmer_dimmable",
joinColumns = @JoinColumn(name = "dimmer_id"),
inverseJoinColumns = @JoinColumn(name = "dimmable_id")
)
private Set<Dimmable> dimmables = new HashSet<>();
/** /**
* Get the lights connected to this dimmer * Get the lights connected to this dimmer
@ -25,19 +29,12 @@ public abstract class Dimmer extends InputDevice {
* @return duh * @return duh
*/ */
@Override @Override
public Set<DimmableLight> getOutputs() { public Set<Dimmable> getOutputs() {
return this.lights; return this.dimmables;
} }
/** Add a light to be controller by this dimmer */ /** Add a light to be controller by this dimmer */
public void addDimmableLight(DimmableLight dimmableLight) { public void addDimmable(Dimmable dimmableLight) {
lights.add(dimmableLight); dimmables.add(dimmableLight);
}
@PreRemove
private void removeLightsFromDimmer() {
for (DimmableLight dl : getOutputs()) {
dl.setDimmerId(null);
}
} }
} }

View file

@ -10,7 +10,7 @@ import javax.persistence.InheritanceType;
* environment (sensor) or the user (switch / dimmer). * environment (sensor) or the user (switch / dimmer).
*/ */
@Entity @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.JOINED)
public abstract class InputDevice extends Device { public abstract class InputDevice extends Device {
public InputDevice(String kind) { public InputDevice(String kind) {
super(kind, FlowType.INPUT); super(kind, FlowType.INPUT);

View file

@ -24,7 +24,7 @@ public class KnobDimmer extends Dimmer {
*/ */
public void setLightIntensity(int intensity) { public void setLightIntensity(int intensity) {
this.intensity = intensity; this.intensity = intensity;
for (DimmableLight dl : getOutputs()) { for (Dimmable dl : getOutputs()) {
dl.setIntensity(intensity); dl.setIntensity(intensity);
} }
} }

View file

@ -7,7 +7,7 @@ import javax.persistence.*;
* ...). * ...).
*/ */
@Entity @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.JOINED)
public abstract class OutputDevice extends Device { public abstract class OutputDevice extends Device {
public OutputDevice(String kind) { public OutputDevice(String kind) {
super(kind, FlowType.OUTPUT); super(kind, FlowType.OUTPUT);

View file

@ -1,5 +1,7 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import com.google.common.base.Objects;
import java.math.BigDecimal; import java.math.BigDecimal;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
@ -44,4 +46,12 @@ public class SmartPlug extends Switchable {
public SmartPlug() { public SmartPlug() {
super("smartPlug"); super("smartPlug");
} }
@Override
public String toString() {
return Objects.toStringHelper(this)
.add("totalConsumption", totalConsumption)
.add("on", on)
.toString();
}
} }

View file

@ -1,17 +1,22 @@
package ch.usi.inf.sa4.sanmarinoes.smarthut.models; package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import javax.persistence.Column; import javax.persistence.*;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.PreRemove;
/** A switch input device */ /** A switch input device */
@Entity @Entity
public class Switch extends InputDevice { public class Switch extends InputDevice {
@OneToMany(mappedBy = "switchDevice") @ManyToMany(cascade = CascadeType.DETACH)
@GsonExclude
@JoinTable(
name = "switch_switchable",
joinColumns = @JoinColumn(name = "switch_id"),
inverseJoinColumns = @JoinColumn(name = "switchable_id")
)
private Set<Switchable> switchables = new HashSet<>(); private Set<Switchable> switchables = new HashSet<>();
/** The state of this switch */ /** The state of this switch */
@ -52,11 +57,4 @@ public class Switch extends InputDevice {
public Set<Switchable> getOutputs() { public Set<Switchable> getOutputs() {
return switchables; return switchables;
} }
@PreRemove
public void removeSwitchable() {
for (Switchable s : getOutputs()) {
s.setSwitchId(null);
}
}
} }

View file

@ -2,22 +2,20 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut.models;
import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude; import ch.usi.inf.sa4.sanmarinoes.smarthut.config.GsonExclude;
import javax.persistence.*; import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
/** A device that can be turned either on or off */ /** A device that can be turned either on or off */
@Entity @Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Inheritance(strategy = InheritanceType.JOINED)
public abstract class Switchable extends OutputDevice { public abstract class Switchable extends OutputDevice {
public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR = public static final Connector<Switch, Switchable> SWITCH_SWITCHABLE_CONNECTOR =
Connector.basic(Switch::getOutputs, Switchable::setSwitchId); Connector.basic(Switch::getOutputs, Switchable::getSwitches);
@ManyToOne @ManyToMany(mappedBy = "switchables", cascade = CascadeType.DETACH)
@GsonExclude @GsonExclude
@JoinColumn(name = "switch_id", updatable = false, insertable = false) private Set<Switch> inputs = new HashSet<>();
private Switch switchDevice;
@Column(name = "switch_id")
private Long switchId;
protected Switchable(String kind) { protected Switchable(String kind) {
super(kind); super(kind);
@ -37,11 +35,7 @@ public abstract class Switchable extends OutputDevice {
*/ */
public abstract void setOn(boolean on); public abstract void setOn(boolean on);
public Long getSwitchId() { public Set<Switch> getSwitches() {
return switchId; return inputs;
}
public void setSwitchId(Long switchId) {
this.switchId = switchId;
} }
} }

View file

@ -14,7 +14,7 @@ public final class Utils {
void apply(T input) throws Throwable; void apply(T input) throws Throwable;
} }
public static <T> List<T> toList(Iterable<T> iterable) { public static <T> List<T> toList(Iterable<? extends T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
} }

View file

@ -3,6 +3,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.ButtonDimmer;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Dimmable;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
@ -30,7 +31,7 @@ public class ButtonDimmerTests {
dl = new DimmableLight(); dl = new DimmableLight();
dl.setIntensity(10); dl.setIntensity(10);
; ;
buttonDimmer.addDimmableLight(dl); buttonDimmer.addDimmable(dl);
} }
} }
@ -38,7 +39,7 @@ public class ButtonDimmerTests {
@DisplayName(" increase the intensity ") @DisplayName(" increase the intensity ")
public void increase() { public void increase() {
buttonDimmer.increaseIntensity(); buttonDimmer.increaseIntensity();
for (DimmableLight dl : buttonDimmer.getOutputs()) { for (Dimmable dl : buttonDimmer.getOutputs()) {
assertTrue(dl.getIntensity() > 10); assertTrue(dl.getIntensity() > 10);
} }
} }
@ -47,7 +48,7 @@ public class ButtonDimmerTests {
@DisplayName(" decrease the intensity ") @DisplayName(" decrease the intensity ")
public void decrease() { public void decrease() {
buttonDimmer.decreaseIntensity(); buttonDimmer.decreaseIntensity();
for (DimmableLight dl : buttonDimmer.getOutputs()) { for (Dimmable dl : buttonDimmer.getOutputs()) {
assertTrue(dl.getIntensity() < 10); assertTrue(dl.getIntensity() < 10);
} }
} }

View file

@ -19,27 +19,27 @@ public class CurtainsTests {
@Test @Test
@DisplayName("State when just created") @DisplayName("State when just created")
public void initialState() { public void initialState() {
assertEquals(0, this.curtains.getOpenedAmount()); assertEquals(0, this.curtains.getIntensity());
} }
@Test @Test
@DisplayName("Check wether setting the opening works") @DisplayName("Check wether setting the opening works")
public void normalSet() { public void normalSet() {
this.curtains.setOpenedAmount(42); this.curtains.setIntensity(42);
assertEquals(42, this.curtains.getOpenedAmount()); assertEquals(42, this.curtains.getIntensity());
} }
@Test @Test
@DisplayName("Set setting a negative number") @DisplayName("Set setting a negative number")
public void setNeg() { public void setNeg() {
this.curtains.setOpenedAmount(-1); this.curtains.setIntensity(-1);
assertEquals(0, this.curtains.getOpenedAmount()); assertEquals(0, this.curtains.getIntensity());
} }
@Test @Test
@DisplayName("Setting state to a number greater than 100") @DisplayName("Setting state to a number greater than 100")
public void setLarge() { public void setLarge() {
this.curtains.setOpenedAmount(32768); this.curtains.setIntensity(32768);
assertEquals(100, this.curtains.getOpenedAmount()); assertEquals(100, this.curtains.getIntensity());
} }
} }

View file

@ -2,6 +2,7 @@ package ch.usi.inf.sa4.sanmarinoes.smarthut;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.Dimmable;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.DimmableLight;
import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmer; import ch.usi.inf.sa4.sanmarinoes.smarthut.models.KnobDimmer;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -30,7 +31,7 @@ public class KnobDimmerTests {
dl = new DimmableLight(); dl = new DimmableLight();
dl.setIntensity(10); dl.setIntensity(10);
; ;
knobDimmer.addDimmableLight(dl); knobDimmer.addDimmable(dl);
} }
} }
@ -38,7 +39,7 @@ public class KnobDimmerTests {
@DisplayName(" set the intensity ") @DisplayName(" set the intensity ")
public void increase() { public void increase() {
knobDimmer.setLightIntensity(30); knobDimmer.setLightIntensity(30);
for (DimmableLight dl : knobDimmer.getOutputs()) { for (Dimmable dl : knobDimmer.getOutputs()) {
assertEquals(30, dl.getIntensity()); assertEquals(30, dl.getIntensity());
} }
} }