Skip to content

Commit

Permalink
add scene device trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
dvdgeisler committed Nov 24, 2022
1 parent e60b7d0 commit 55643a1
Show file tree
Hide file tree
Showing 9 changed files with 220 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public Mono<Scene> refresh(final Scene scene) {
public Mono<Scene> create(final String name, final String icon) {
return this.clientApi.scene.createScene(new SceneAttributes(
new SceneInfo(name, icon), List.of(), List.of()))
.flatMap(id -> this.clientApi.scene.getScene(id.id));
.flatMap(id -> this.clientApi.scene.getScene(id.id).retry(10));
}

public Mono<Void> delete(final Scene scene) {
Expand All @@ -40,8 +40,8 @@ public Mono<Scene> update(final Scene scene, final String name, final String ico
.flatMap(this::refresh);
}

public Mono<Scene> setTrigger(final Scene scene, final List<SceneTrigger> trigger) {
return this.clientApi.scene.updateScene(scene.id, new SceneAttributes(null, trigger, List.of()))
public Mono<Scene> setTrigger(final Scene scene, final List<SceneTrigger> triggers) {
return this.clientApi.scene.updateScene(scene.id, new SceneAttributes(scene.attributes.info, triggers, List.of()))
.thenReturn(scene)
.flatMap(this::refresh);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public Mono<Map> dump() {
.bodyToMono(Map.class);
}

public void websocket(final Consumer<String> consumer) {
public Mono<Void> websocket(final Consumer<String> consumer) {
final String token;
final String authorizationHeader;
final HttpClient httpClient;
Expand All @@ -104,13 +104,13 @@ public void websocket(final Consumer<String> consumer) {
.headers(headers -> headers.add(HttpHeaders.AUTHORIZATION, authorizationHeader))
.keepAlive(true);
client = new ReactorNettyWebSocketClient(httpClient);
client.execute(URI.create(String.format("https://%s:%d/v1/", this.hostname, this.port)), session ->
return client.execute(URI.create(String.format("https://%s:%d/v1/", this.hostname, this.port)), session ->
session.receive()
.map(WebSocketMessage::getPayloadAsText)
.doOnNext(consumer)
.repeat()
.then()
).block();
);
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,29 @@
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import de.dvdgeisler.iot.dirigera.client.api.model.Identifier;

import java.time.LocalDateTime;

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
@JsonSubTypes({
@JsonSubTypes.Type(value = SceneTriggerApp.class, name = "app"),
@JsonSubTypes.Type(value = SceneTriggerSunriseSunset.class, name = "sunriseSunset"),
@JsonSubTypes.Type(value = SceneTriggerTime.class, name = "time"),
@JsonSubTypes.Type(value = SceneTriggerController.class, name = "controller"),
})
public class SceneTrigger extends Identifier {
public SceneTriggerType type;
public Boolean disabled;
public LocalDateTime triggeredAt;
public SceneEndTrigger endTrigger;

public SceneTrigger() {
}

public SceneTrigger(final String id, final SceneTriggerType type, final Boolean disabled) {
public SceneTrigger(final String id, final SceneTriggerType type, final Boolean disabled, final LocalDateTime triggeredAt, final SceneEndTrigger endTrigger) {
super(id);
this.type = type;
this.disabled = disabled;
this.triggeredAt = triggeredAt;
this.endTrigger = endTrigger;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package de.dvdgeisler.iot.dirigera.client.api.model.scene;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.time.LocalDateTime;

import static de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerType.APPLICATION;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class SceneTriggerApp extends SceneTrigger {
public LocalDateTime triggeredAt;

public SceneTriggerApp() {
}

public SceneTriggerApp(final String id, final Boolean disabled, final LocalDateTime triggeredAt) {
super(id, APPLICATION, disabled);
this.triggeredAt = triggeredAt;
public SceneTriggerApp(final String id, final Boolean disabled, final LocalDateTime triggeredAt, final SceneEndTrigger endTrigger) {
super(id, APPLICATION, disabled, triggeredAt, endTrigger);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.dvdgeisler.iot.dirigera.client.api.model.scene;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.time.LocalDateTime;

import static de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerType.CONTROLLER;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class SceneTriggerController extends SceneTrigger {
public SceneTriggerControllerTrigger trigger;

public SceneTriggerController() {
}

public SceneTriggerController(final String id, final Boolean disabled, final LocalDateTime triggeredAt, final SceneEndTrigger endTrigger, final SceneTriggerControllerTrigger trigger) {
super(id, CONTROLLER, disabled, triggeredAt, endTrigger);
this.trigger = trigger;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package de.dvdgeisler.iot.dirigera.client.api.model.scene;

import com.fasterxml.jackson.annotation.JsonInclude;
import de.dvdgeisler.iot.dirigera.client.api.model.device.DeviceType;

import java.util.List;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class SceneTriggerControllerTrigger {
public List<String> days;
public DeviceType controllerType;
public Integer buttonIndex;
public String deviceId;

public SceneTriggerControllerTrigger(final List<String> days, final DeviceType controllerType, final Integer buttonIndex, final String deviceId) {
this.days = days;
this.controllerType = controllerType;
this.buttonIndex = buttonIndex;
this.deviceId = deviceId;
}

public SceneTriggerControllerTrigger() {
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package de.dvdgeisler.iot.dirigera.client.api.model.scene;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.time.LocalDateTime;

import static de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerType.SUNRISE_SUNSET;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class SceneTriggerSunriseSunset extends SceneTrigger {
public SceneTriggerSunriseSunsetTrigger trigger;
public LocalDateTime nextTriggerAt;
public LocalDateTime triggeredAt;
public SceneEndTrigger endTrigger;

public SceneTriggerSunriseSunset(final String id, final Boolean disabled, final SceneEndTrigger endTrigger, final SceneTriggerSunriseSunsetTrigger trigger, final LocalDateTime nextTriggerAt, final LocalDateTime triggeredAt) {
super(id, SUNRISE_SUNSET, disabled);
super(id, SUNRISE_SUNSET, disabled, triggeredAt, endTrigger);
this.trigger = trigger;
this.nextTriggerAt = nextTriggerAt;
this.triggeredAt = triggeredAt;
this.endTrigger = endTrigger;
}

public SceneTriggerSunriseSunset() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@
public class SceneTriggerTime extends SceneTrigger {
public SceneTriggerTimeTrigger trigger;
public LocalDateTime nextTriggerAt;
public LocalDateTime triggeredAt;
public SceneEndTrigger endTrigger;

public SceneTriggerTime(final String id, final SceneTriggerType type, final Boolean disabled, final SceneEndTrigger endTrigger, final SceneTriggerTimeTrigger trigger, final LocalDateTime nextTriggerAt, final LocalDateTime triggeredAt) {
super(id, TIME, disabled);
public SceneTriggerTime(final String id, final Boolean disabled, final SceneEndTrigger endTrigger, final SceneTriggerTimeTrigger trigger, final LocalDateTime nextTriggerAt, final LocalDateTime triggeredAt) {
super(id, TIME, disabled, triggeredAt, endTrigger);
this.trigger = trigger;
this.nextTriggerAt = nextTriggerAt;
this.triggeredAt = triggeredAt;
this.endTrigger = endTrigger;
}

public SceneTriggerTime() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package de.dvdgeisler.iot.dirigera.client.examples.scenetriggers;

import com.fasterxml.jackson.databind.ObjectMapper;
import de.dvdgeisler.iot.dirigera.client.api.DirigeraApi;
import de.dvdgeisler.iot.dirigera.client.api.http.ClientApi;
import de.dvdgeisler.iot.dirigera.client.api.model.device.Device;
import de.dvdgeisler.iot.dirigera.client.api.model.device.DeviceType;
import de.dvdgeisler.iot.dirigera.client.api.model.scene.Scene;
import de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerApp;
import de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerController;
import de.dvdgeisler.iot.dirigera.client.api.model.scene.SceneTriggerControllerTrigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import reactor.core.publisher.Mono;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

/**
*
*/
@SpringBootApplication
@ComponentScan(basePackageClasses = {DirigeraApi.class})
public class SceneTriggers {
private final static Logger log = LoggerFactory.getLogger(SceneTriggers.class);
private final DirigeraApi dapi;
private final ClientApi capi;
private final ObjectMapper json;

public SceneTriggers(final DirigeraApi dapi, final ClientApi capi, final ObjectMapper json) {
this.dapi = dapi;
this.capi = capi;
this.json = json;
}

private static SceneTriggerController createTrigger(final Device device, final int buttonIndex) {
return new SceneTriggerController( // trigger for button 0 (turn light on)
null, false, null, null,
new SceneTriggerControllerTrigger(
null,
DeviceType.SHORTCUT_CONTROLLER,
buttonIndex,
device.id));
}

private Scene createDummyScene(final Device device, final int button) {
final Scene scene;
final String name;

name = String.format("%s button %d", device.attributes.state.customName, button);

scene = this.dapi.scene.create(name, "Icon")
.doOnSuccess(s -> log.info("Created Scene {}: name={}, icon={}", s.id, s.attributes.info.name, s.attributes.info.icon))
.block(); // create dummy scene

return this.dapi.scene.setTrigger(scene, List.of(
new SceneTriggerApp(null, null, null, null),
createTrigger(device, button))
).block();
}

private Stream<Scene> createDummyScenes(final Device device) {
return Stream.of(
this.createDummyScene(device, 0),
this.createDummyScene(device, 1),
this.createDummyScene(device, 2));
}

@Bean
public CommandLineRunner run() {
return (String... args) -> {
List<Scene> scenes;
this.dapi.pairIfRequired().block();


scenes = new ArrayList<>();


try {
this.dapi.device.controller.light // create dummy scenes for light controller
.all()
.block()
.stream()
.flatMap(this::createDummyScenes)
.forEach(scenes::add);
this.dapi.device.controller.shortcut // create dummy scenes for shortcut controller
.all()
.block()
.stream()
.flatMap(this::createDummyScenes)
.forEach(scenes::add);
this.dapi.device.controller.sound // create dummy scenes for sound controller
.all()
.block()
.stream()
.flatMap(this::createDummyScenes)
.forEach(scenes::add);
this.dapi.device.motionSensor // create dummy scenes for motion sensors
.all()
.block()
.stream()
.flatMap(this::createDummyScenes)
.forEach(scenes::add);
log.info("Press button of any connected controller");
this.capi.websocket(this::logButtonPress)
.block(Duration.ofSeconds(60));
} catch (Exception e) {
log.error(e.getMessage());
}

scenes.stream()
.peek(scene -> log.info("Delete scene {}", scene.attributes.info.name))
.map(this.dapi.scene::delete)
.forEach(Mono::block);
};
}

private void logButtonPress(final String s) {
final Map json, data, info;
final String type;

try {
json = this.json.readValue(s, Map.class);
type = json.get("type").toString();
if(!Objects.equals(type, "sceneUpdated")) {
log.info("Received: {}", s);
return;
}
data = (Map) json.get("data");
info = (Map) data.get("info");
log.info("Received: {}", info.get("name"));
} catch (Throwable e) {
log.error(e.getMessage());
}
}

public static void main(String[] args) {
SpringApplication.run(SceneTriggers.class, args).close();
}


}

0 comments on commit 55643a1

Please sign in to comment.