Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#79 Add air purifier to MQTT Hass code #84

Merged
merged 1 commit into from
May 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package de.dvdgeisler.iot.dirigera.client.mqtt.hass;

import com.fasterxml.jackson.databind.ObjectMapper;
import de.dvdgeisler.iot.dirigera.client.api.AirPurifierDeviceApi;
import de.dvdgeisler.iot.dirigera.client.api.DirigeraApi;
import de.dvdgeisler.iot.dirigera.client.api.model.device.airpurifier.AirPurifierDevice;
import de.dvdgeisler.iot.dirigera.client.api.model.device.airpurifier.AirPurifierFanMode;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailability;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.DeviceAvailabilityState;
import de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.airpurifier.AirPurifierConfig;
import java.util.Optional;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class HassAirPurifierEventHandler extends HassDeviceEventHandler<AirPurifierDevice> {
private final static String HASS_COMPONENT = "air_quality";

private final AirPurifierDeviceApi api;

public HassAirPurifierEventHandler(
final MqttClient mqtt,
final DirigeraApi api,
@Value("${dirigera.mqtt.hass.prefix:homeassistant}")
final String topicPrefix,
final ObjectMapper objectMapper) {
super(mqtt, api, AirPurifierDevice.class, topicPrefix, objectMapper);

this.api = api.device.airPurifier;
this.api.all()
.block()
.forEach(this::onDeviceCreated);
}

@Override
protected void onDeviceCreated(final AirPurifierDevice device) {
final AirPurifierConfig config;

config = new AirPurifierConfig();
config.unique_id = config.object_id = device.id;
config.name = getDefaultName(device);
config.device = this.getDeviceConfig(device);
config.command_topic = this.getTopic(device, HASS_COMPONENT, TOPIC_SET);
config.state_topic = this.getTopic(device, HASS_COMPONENT, TOPIC_STATE);
config.payload_off = this.toJSON(AirPurifierFanMode.OFF);
config.payload_auto = this.toJSON(AirPurifierFanMode.AUTO);
config.payload_manual = this.toJSON(AirPurifierFanMode.MANUAL);
config.state_off = this.toJSON(AirPurifierFanMode.OFF);
config.state_auto = this.toJSON(AirPurifierFanMode.AUTO);
config.state_manual = this.toJSON(AirPurifierFanMode.MANUAL);
config.value_template = "{{value}}";

config.availability = new DeviceAvailability();
config.availability.topic = this.getTopic(device, HASS_COMPONENT, TOPIC_AVAILABILITY);
config.availability.payload_available = this.toJSON(DeviceAvailabilityState.ONLINE);
config.availability.payload_not_available = this.toJSON(DeviceAvailabilityState.OFFLINE);
this.publish(this.getTopic(device, HASS_COMPONENT, TOPIC_CONFIG), config);

this.subscribe(
this.getTopic(device, HASS_COMPONENT, TOPIC_SET),
AirPurifierFanMode.class,
status -> this.setDeviceStatus(device, status));

this.onDeviceStateChanged(device);
}

protected void setDeviceStatus(final AirPurifierDevice device, final AirPurifierFanMode state) {
this.api.setFanMode(device, state).block();
}

@Override
protected void onDeviceStateChanged(final AirPurifierDevice device) {
getState(device).ifPresent(state ->
this.publish(this.getTopic(device, HASS_COMPONENT, TOPIC_STATE), state));
getAvailability(device).ifPresent(s ->
this.publish(this.getTopic(device, HASS_COMPONENT, TOPIC_AVAILABILITY), s));
}

@Override
protected void onDeviceRemoved(final AirPurifierDevice device) {
this.publish(this.getTopic(device, HASS_COMPONENT, TOPIC_AVAILABILITY), DeviceAvailabilityState.OFFLINE);
this.publish(this.getTopic(device, HASS_COMPONENT, TOPIC_REMOVE), null);
this.unsubscribe(this.getTopic(device, HASS_COMPONENT, TOPIC_SET));
}

public static Optional<AirPurifierFanMode> getState(final AirPurifierDevice device) {
return Optional.of(device)
.map(d->d.attributes)
.map(a->a.state)
.map(s->s.fanMode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package de.dvdgeisler.iot.dirigera.client.mqtt.hass.model.airpurifier;

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;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class AirPurifierConfig {
public String object_id;
public String unique_id;
public String name;
public Device device;
public String payload_off;
public String payload_auto;
public String payload_manual;
public String command_topic;
public String state_off;
public String state_auto;
public String state_manual;
public String state_topic;
public String value_template;
public DeviceAvailability availability;

public AirPurifierConfig(String object_id, String unique_id, String name, Device device,
String payload_off, String payload_auto, String payload_manual, String command_topic,
String state_off, String state_auto, String state_manual, String state_topic,
String value_template, DeviceAvailability availability) {
this.object_id = object_id;
this.unique_id = unique_id;
this.name = name;
this.device = device;
this.payload_off = payload_off;
this.payload_auto = payload_auto;
this.payload_manual = payload_manual;
this.command_topic = command_topic;
this.state_off = state_off;
this.state_auto = state_auto;
this.state_manual = state_manual;
this.state_topic = state_topic;
this.value_template = value_template;
this.availability = availability;
}

public AirPurifierConfig() {
}
}