Skip to content

Commit

Permalink
Merge pull request #37 from dvdgeisler/bugfix/issue-33
Browse files Browse the repository at this point in the history
Bugfix/issue 33
  • Loading branch information
dvdgeisler authored Nov 24, 2022
2 parents b7e48dc + c5a5ff5 commit b6d413b
Show file tree
Hide file tree
Showing 11 changed files with 41 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,18 @@ public class LightColorAttributes {
public Float saturation;
@JsonProperty("colorTemperature")
public Integer temperature;

/**
* The minimal color temperature in Kelvin.
* @implNote higher Kelvin indicates lower color temperature
*/
@JsonProperty("colorTemperatureMin")
public Integer temperatureMin;

/**
* The maximal color temperature in Kelvin.
* @implNote lower Kelvin indicates higher color temperature
*/
@JsonProperty("colorTemperatureMax")
public Integer temperatureMax;
@JsonProperty("colorMode")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ public MqttBridge(
@Value("${dirigera.mqtt.reconnect:true}") final Boolean reconnect,
@Value("${dirigera.mqtt.timeout:10}") final Integer timeout,
final DirigeraApi api) throws MqttException {
super(String.format("tcp://%s:%d", host, port),
Objects.requireNonNull(api.status().map(s -> s.id).block()));
super(String.format("tcp://%s:%d", host, port), clientId(api));
final MqttConnectOptions options;
this.api = api;
this.eventHandler = new HashMap<>();
Expand Down Expand Up @@ -122,4 +121,9 @@ public <_Device extends Device> void removeDevice(final _Device device) {
.flatMap(factory -> factory.removeDevice(this, this.api, device))
.forEach(this::publishMessage);
}

private static String clientId(final DirigeraApi api) {
api.pairIfRequired().block();
return api.status().map(s -> s.id).block();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,24 @@

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.PrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.dvdgeisler.iot.dirigera.client.api.DirigeraApi;
import de.dvdgeisler.iot.dirigera.client.api.model.device.light.LightDevice;
import de.dvdgeisler.iot.dirigera.client.mqtt.MqttBridge;
import de.dvdgeisler.iot.dirigera.client.mqtt.MqttBridgeMessage;
import de.dvdgeisler.iot.dirigera.client.mqtt.MqttEventHandler;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.Device;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailability;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.light.LightStatus;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailabilityState.OFFLINE;
import static de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailabilityState.ONLINE;
import static java.lang.Math.max;
import static java.lang.Math.min;

public abstract class HassEventHandler<_Device extends de.dvdgeisler.iot.dirigera.client.api.model.device.Device, _DeviceState> implements MqttEventHandler<_Device> {
private final static Logger log = LoggerFactory.getLogger(HassEventHandler.class);
Expand Down Expand Up @@ -56,22 +47,35 @@ protected String topic(final MqttBridge mqtt, final _Device device, final String
.collect(Collectors.joining("/"));
}

protected <T> MqttBridgeMessage<_Device> build(final MqttBridge mqtt, final _Device device, final String topic, final T payload) {
protected <T> MqttBridgeMessage<_Device> build(
final MqttBridge mqtt,
final _Device device,
final String topic,
final T payload) {
try {
return new MqttBridgeMessage<>(
device,
this,
this.topic(mqtt, device, topic),
new MqttMessage(this.objectMapper.writeValueAsBytes(payload)));
new MqttMessage(this.objectMapper.writeValueAsBytes(payload)){{
this.setQos(1);
this.setRetained(true);
}});
} catch (JsonProcessingException e) {
log.error(e.getMessage());
}
return null;
}

protected void subscribe(final MqttBridge mqtt, final DirigeraApi api, final _Device device) {
protected void subscribe(final MqttBridge mqtt, final DirigeraApi api, final _Device device, final String topicSuffix) {
final String topic;

try {
mqtt.subscribe(this.topic(mqtt, device, "set"), (topic, message) -> {
topic = this.topic(mqtt, device, topicSuffix);
log.info("Subscribe to device: topic={}, id={}, name={}, category={}, type={}",
topic, device.id, device.attributes.state.customName, device.deviceType, device.type);

mqtt.subscribe(this.topic(mqtt, device, topicSuffix), (t, message) -> {
final _DeviceState state;

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ public void setDevice(final MqttBridge mqtt, final DirigeraApi api, final LightD

Optional.ofNullable(status.color_temp)
.filter(t -> canReceive(device, "colorTemperature"))
.map(t -> max(t, getMaxTemperatureMireds(device))) // todo: getMaxTemperatureMireds may return null
.map(t -> min(t, getMinTemperatureMireds(device))) // todo: getMinTemperatureMireds may return null
.flatMap(t -> Optional.ofNullable(getMaxTemperatureMireds(device)).map(maxT -> min(t, maxT)))
.flatMap(t -> Optional.ofNullable(getMinTemperatureMireds(device)).map(minT -> max(t, minT)))
.map(LightUtils::miredsToKelvin)
.map(t -> api.device.light.setTemperature(device, t))
.ifPresent(Mono::block);
Expand Down Expand Up @@ -81,7 +81,7 @@ public Stream<MqttBridgeMessage<LightDevice>> addDevice(
final List<LightColorMode> colorModes;

colorModes = colorModes(device);
this.subscribe(mqtt, api, device);
this.subscribe(mqtt, api, device, TOPIC_SET);
return Stream.of(this.build(mqtt, device, TOPIC_CONFIG,
new LightConfig(
device.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ public Stream<MqttBridgeMessage<MotionSensorDevice>> addDevice(
final DirigeraApi api,
final MotionSensorDevice device) {

this.subscribe(mqtt, api, device);
return Stream.of(this.build(mqtt, device, TOPIC_CONFIG,
new MotionSensorConfig(
device.id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public Stream<MqttBridgeMessage<OutletDevice>> addDevice(
final DirigeraApi api,
final OutletDevice device) {

this.subscribe(mqtt, api, device);
this.subscribe(mqtt, api, device, TOPIC_SET);
return Stream.of(this.build(mqtt, device, TOPIC_CONFIG,
new OutletConfig(
device.id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package de.dvdgeisler.iot.dirigera.client.mqtt.hass.model;


import de.dvdgeisler.iot.dirigera.client.api.model.device.Device;

public class DeviceAvailability {
public String topic;
public String payload_available;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.light;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class LightColor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public static Integer miredsToKelvin(final Integer kelvin) {
}

public static Integer getMaxTemperatureMireds(final LightDevice device) {
return Optional.ofNullable(getMaxTemperatureKelvin(device))
return Optional.ofNullable(getMinTemperatureKelvin(device))
.map(LightUtils::kelvinToMireds)
.orElse(null);
}
Expand All @@ -34,12 +34,12 @@ public static Integer getMaxTemperatureKelvin(final LightDevice device) {
.map(d -> d.attributes)
.map(d -> d.state)
.map(d -> d.color)
.map(d -> d.temperatureMax)
.map(d -> d.temperatureMin)
.orElse(null);
}

public static Integer getMinTemperatureMireds(final LightDevice device) {
return Optional.ofNullable(getTemperatureMireds(device))
return Optional.ofNullable(getMaxTemperatureKelvin(device))
.map(LightUtils::miredsToKelvin)
.orElse(null);
}
Expand All @@ -49,7 +49,7 @@ public static Integer getMinTemperatureKelvin(final LightDevice device) {
.map(d -> d.attributes)
.map(d -> d.state)
.map(d -> d.color)
.map(d -> d.temperatureMin)
.map(d -> d.temperatureMax)
.orElse(null);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.motionsensor;

import de.dvdgeisler.iot.dirigera.client.api.model.device.motionsensor.MotionSensorDevice;
import de.dvdgeisler.iot.dirigera.client.api.model.device.outlet.OutletDevice;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceState;

import java.util.Optional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.Device;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailability;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceState;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.light.LightColorMode;

import java.util.List;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class OutletConfig {
Expand Down

0 comments on commit b6d413b

Please sign in to comment.