mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[Netatmo] Enhance webhook handling and dispatching (#15045)
* Enhance webhook handling and dispatching Signed-off-by: clinique <gael@lhopital.org> * Corrects flapping channels on Home when using single home for security and energy Signed-off-by: clinique <gael@lhopital.org> * Some code enhancement Signed-off-by: clinique <gael@lhopital.org> * Adding some missing EventType submitted on the webhook Signed-off-by: clinique <gael@lhopital.org> --------- Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
c9c6e95807
commit
d40c20b2dd
@ -460,6 +460,7 @@ The Home thing has the following configuration elements:
|
||||
| securityId | String | No | Id of a home holding security monitoring devices |
|
||||
|
||||
At least one of these parameter must be filled - at most two :
|
||||
|
||||
* id or securityId
|
||||
* id or energyId
|
||||
* securityId and energyId
|
||||
|
@ -18,7 +18,6 @@ import java.net.URI;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
@ -94,7 +93,7 @@ public class SecurityApi extends RestManager {
|
||||
|
||||
// Remove unneeded events being before oldestKnown
|
||||
return events.stream().filter(event -> freshestEventTime == null || event.getTime().isAfter(freshestEventTime))
|
||||
.sorted(Comparator.comparing(HomeEvent::getTime).reversed()).collect(Collectors.toList());
|
||||
.sorted(Comparator.comparing(HomeEvent::getTime).reversed()).toList();
|
||||
}
|
||||
|
||||
public List<HomeEvent> getPersonEvents(String homeId, String personId) throws NetatmoException {
|
||||
|
@ -43,6 +43,8 @@ public enum EventSubType {
|
||||
BATTERY_VERY_LOW(1, EventType.BATTERY_STATUS),
|
||||
SMOKE_CLEARED(0, EventType.SMOKE),
|
||||
SMOKE_DETECTED(1, EventType.SMOKE),
|
||||
HUSH_ACTIVATED(0, EventType.HUSH),
|
||||
HUSH_DEACTIVATED(1, EventType.HUSH),
|
||||
SOUND_TEST_OK(0, EventType.SOUND_TEST),
|
||||
SOUND_TEST_ERROR(1, EventType.SOUND_TEST),
|
||||
DETECTOR_READY(0, EventType.TAMPERED),
|
||||
|
@ -28,6 +28,8 @@ import com.google.gson.annotations.SerializedName;
|
||||
@NonNullByDefault
|
||||
public enum EventType {
|
||||
UNKNOWN(),
|
||||
@SerializedName("webhook_activation") // Ack of a 'webhook set' Api Call
|
||||
WEBHOOK_ACTIVATION(ModuleType.ACCOUNT),
|
||||
|
||||
@SerializedName("person") // When the Indoor Camera detects a face
|
||||
PERSON(ModuleType.PERSON, ModuleType.WELCOME),
|
||||
@ -71,6 +73,15 @@ public enum EventType {
|
||||
@SerializedName("module_end_update") // Module's firmware update is over
|
||||
MODULE_END_UPDATE(ModuleType.WELCOME),
|
||||
|
||||
@SerializedName("tag_big_move") // Module's firmware update is over
|
||||
TAG_BIG_MOVE(ModuleType.WELCOME),
|
||||
|
||||
@SerializedName("tag_open") // Module's firmware update is over
|
||||
TAG_OPEN(ModuleType.WELCOME),
|
||||
|
||||
@SerializedName("tag_small_move") // Module's firmware update is over
|
||||
TAG_SMALL_MOVE(ModuleType.WELCOME),
|
||||
|
||||
@SerializedName("connection") // When the camera connects to Netatmo servers
|
||||
CONNECTION(ModuleType.WELCOME, ModuleType.PRESENCE),
|
||||
|
||||
|
@ -38,17 +38,50 @@ public class HomeData extends NAThing implements NAModule, LocationEx {
|
||||
public class HomesDataResponse extends ApiResponse<ListBodyResponse<HomeData>> {
|
||||
}
|
||||
|
||||
public class Security extends HomeData {
|
||||
private NAObjectMap<HomeDataPerson> persons = new NAObjectMap<>();
|
||||
|
||||
public NAObjectMap<HomeDataPerson> getPersons() {
|
||||
return persons;
|
||||
}
|
||||
|
||||
public List<HomeDataPerson> getKnownPersons() {
|
||||
return persons.values().stream().filter(HomeDataPerson::isKnown).toList();
|
||||
}
|
||||
}
|
||||
|
||||
public class Energy extends HomeData {
|
||||
private String temperatureControlMode = "";
|
||||
private SetpointMode thermMode = SetpointMode.UNKNOWN;
|
||||
private int thermSetpointDefaultDuration;
|
||||
private List<ThermProgram> schedules = List.of();
|
||||
|
||||
public int getThermSetpointDefaultDuration() {
|
||||
return thermSetpointDefaultDuration;
|
||||
}
|
||||
|
||||
public SetpointMode getThermMode() {
|
||||
return thermMode;
|
||||
}
|
||||
|
||||
public String getTemperatureControlMode() {
|
||||
return temperatureControlMode;
|
||||
}
|
||||
|
||||
public List<ThermProgram> getThermSchedules() {
|
||||
return schedules;
|
||||
}
|
||||
|
||||
public @Nullable ThermProgram getActiveProgram() {
|
||||
return schedules.stream().filter(ThermProgram::isSelected).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
private double altitude;
|
||||
private double[] coordinates = {};
|
||||
private @Nullable String country;
|
||||
private @Nullable String timezone;
|
||||
|
||||
private @Nullable String temperatureControlMode;
|
||||
private SetpointMode thermMode = SetpointMode.UNKNOWN;
|
||||
private int thermSetpointDefaultDuration;
|
||||
private List<ThermProgram> schedules = List.of();
|
||||
|
||||
private NAObjectMap<HomeDataPerson> persons = new NAObjectMap<>();
|
||||
private NAObjectMap<HomeDataRoom> rooms = new NAObjectMap<>();
|
||||
private NAObjectMap<HomeDataModule> modules = new NAObjectMap<>();
|
||||
|
||||
@ -77,26 +110,6 @@ public class HomeData extends NAThing implements NAModule, LocationEx {
|
||||
return Optional.ofNullable(timezone);
|
||||
}
|
||||
|
||||
public int getThermSetpointDefaultDuration() {
|
||||
return thermSetpointDefaultDuration;
|
||||
}
|
||||
|
||||
public SetpointMode getThermMode() {
|
||||
return thermMode;
|
||||
}
|
||||
|
||||
public NAObjectMap<HomeDataPerson> getPersons() {
|
||||
return persons;
|
||||
}
|
||||
|
||||
public List<HomeDataPerson> getKnownPersons() {
|
||||
return persons.values().stream().filter(HomeDataPerson::isKnown).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public Optional<String> getTemperatureControlMode() {
|
||||
return Optional.ofNullable(temperatureControlMode);
|
||||
}
|
||||
|
||||
public NAObjectMap<HomeDataRoom> getRooms() {
|
||||
return rooms;
|
||||
}
|
||||
@ -108,12 +121,4 @@ public class HomeData extends NAThing implements NAModule, LocationEx {
|
||||
public Set<FeatureArea> getFeatures() {
|
||||
return getModules().values().stream().map(m -> m.getType().feature).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public List<ThermProgram> getThermSchedules() {
|
||||
return schedules;
|
||||
}
|
||||
|
||||
public @Nullable ThermProgram getActiveProgram() {
|
||||
return schedules.stream().filter(ThermProgram::isSelected).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class HomeStatusPerson extends NAThing {
|
||||
return ModuleType.PERSON;
|
||||
}
|
||||
|
||||
public boolean isOutOfSight() {
|
||||
return outOfSight;
|
||||
public boolean atHome() {
|
||||
return !outOfSight;
|
||||
}
|
||||
}
|
||||
|
@ -32,22 +32,26 @@ public class NAHomeStatus {
|
||||
|
||||
public class HomeStatus extends NAThing {
|
||||
private @Nullable NAObjectMap<HomeStatusModule> modules;
|
||||
private @Nullable NAObjectMap<HomeStatusPerson> persons;
|
||||
private @Nullable NAObjectMap<Room> rooms;
|
||||
|
||||
public NAObjectMap<HomeStatusModule> getModules() {
|
||||
NAObjectMap<HomeStatusModule> localModules = modules;
|
||||
return localModules != null ? localModules : new NAObjectMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
public NAObjectMap<HomeStatusPerson> getPersons() {
|
||||
NAObjectMap<HomeStatusPerson> localPersons = persons;
|
||||
return localPersons != null ? localPersons : new NAObjectMap<>();
|
||||
}
|
||||
public class Energy extends HomeStatus {
|
||||
private NAObjectMap<Room> rooms = new NAObjectMap<>();
|
||||
|
||||
public NAObjectMap<Room> getRooms() {
|
||||
NAObjectMap<Room> localRooms = rooms;
|
||||
return localRooms != null ? localRooms : new NAObjectMap<>();
|
||||
return rooms;
|
||||
}
|
||||
}
|
||||
|
||||
public class Security extends HomeStatus {
|
||||
private NAObjectMap<HomeStatusPerson> persons = new NAObjectMap<>();
|
||||
|
||||
public NAObjectMap<HomeStatusPerson> getPersons() {
|
||||
return persons;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,9 @@ import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.netatmo.internal.api.NetatmoException;
|
||||
import org.openhab.binding.netatmo.internal.api.data.ModuleType;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
@ -49,22 +52,26 @@ public class NADeserializer {
|
||||
.registerTypeAdapter(NAObjectMap.class, new NAObjectMapDeserializer())
|
||||
.registerTypeAdapter(NAPushType.class, new NAPushTypeDeserializer())
|
||||
.registerTypeAdapter(ModuleType.class, new ModuleTypeDeserializer())
|
||||
.registerTypeAdapter(ZonedDateTime.class,
|
||||
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> {
|
||||
long netatmoTS = json.getAsJsonPrimitive().getAsLong();
|
||||
Instant i = Instant.ofEpochSecond(netatmoTS);
|
||||
return ZonedDateTime.ofInstant(i, timeZoneProvider.getTimeZone());
|
||||
})
|
||||
.registerTypeAdapter(HomeStatus.class,
|
||||
(JsonDeserializer<HomeStatus>) (json, type, context) -> context.deserialize(json,
|
||||
json.getAsJsonObject().has("persons") ? NAHomeStatus.Security.class
|
||||
: NAHomeStatus.Energy.class))
|
||||
.registerTypeAdapter(HomeData.class,
|
||||
(JsonDeserializer<HomeData>) (json, type, context) -> context.deserialize(json,
|
||||
json.getAsJsonObject().has("therm_mode") ? HomeData.Energy.class
|
||||
: HomeData.Security.class))
|
||||
.registerTypeAdapter(ZonedDateTime.class, (JsonDeserializer<ZonedDateTime>) (json, type, context) -> {
|
||||
long netatmoTS = json.getAsJsonPrimitive().getAsLong();
|
||||
Instant i = Instant.ofEpochSecond(netatmoTS);
|
||||
return ZonedDateTime.ofInstant(i, timeZoneProvider.getTimeZone());
|
||||
})
|
||||
.registerTypeAdapter(OnOffType.class,
|
||||
(JsonDeserializer<OnOffType>) (json, type, jsonDeserializationContext) -> OnOffType
|
||||
(JsonDeserializer<OnOffType>) (json, type, context) -> OnOffType
|
||||
.from(json.getAsJsonPrimitive().getAsString()))
|
||||
.registerTypeAdapter(OpenClosedType.class,
|
||||
(JsonDeserializer<OpenClosedType>) (json, type, jsonDeserializationContext) -> {
|
||||
String value = json.getAsJsonPrimitive().getAsString().toUpperCase();
|
||||
return "TRUE".equals(value) || "1".equals(value) ? OpenClosedType.CLOSED
|
||||
: OpenClosedType.OPEN;
|
||||
})
|
||||
.create();
|
||||
.registerTypeAdapter(OpenClosedType.class, (JsonDeserializer<OpenClosedType>) (json, type, context) -> {
|
||||
String value = json.getAsJsonPrimitive().getAsString().toUpperCase();
|
||||
return "TRUE".equals(value) || "1".equals(value) ? OpenClosedType.CLOSED : OpenClosedType.OPEN;
|
||||
}).create();
|
||||
}
|
||||
|
||||
public <T> T deserialize(Class<T> clazz, String json) throws NetatmoException {
|
||||
|
@ -32,6 +32,7 @@ import com.google.gson.JsonElement;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
class NAPushTypeDeserializer implements JsonDeserializer<NAPushType> {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(NAPushTypeDeserializer.class);
|
||||
|
||||
@Override
|
||||
@ -40,15 +41,19 @@ class NAPushTypeDeserializer implements JsonDeserializer<NAPushType> {
|
||||
final String[] elements = string.split("-");
|
||||
ModuleType moduleType = ModuleType.UNKNOWN;
|
||||
EventType eventType = EventType.UNKNOWN;
|
||||
|
||||
if (elements.length == 2) {
|
||||
moduleType = fromNetatmoObject(elements[0]);
|
||||
eventType = fromEvent(elements[1]);
|
||||
} else {
|
||||
logger.warn("Unexpected syntax received for push_type field : {}", string);
|
||||
} else if (elements.length == 1) {
|
||||
moduleType = ModuleType.ACCOUNT;
|
||||
eventType = fromEvent(string);
|
||||
}
|
||||
|
||||
if (moduleType.equals(ModuleType.UNKNOWN) || eventType.equals(EventType.UNKNOWN)) {
|
||||
logger.warn("Unknown module or event type : {}, deserialized to '{}-{}'", string, moduleType, eventType);
|
||||
}
|
||||
|
||||
return new NAPushType(moduleType, eventType);
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ import org.openhab.binding.netatmo.internal.api.WeatherApi;
|
||||
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.FeatureArea;
|
||||
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.Scope;
|
||||
import org.openhab.binding.netatmo.internal.api.data.NetatmoConstants.ServiceError;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAMain;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAModule;
|
||||
@ -395,8 +396,9 @@ public class ApiBridgeHandler extends BaseBridgeHandler {
|
||||
|| h.getFeatures().contains(FeatureArea.WEATHER) && h.getFeatures().size() == 1))
|
||||
.forEach(home -> {
|
||||
action.apply(home, accountUID).ifPresent(homeUID -> {
|
||||
home.getKnownPersons().forEach(person -> action.apply(person, homeUID));
|
||||
|
||||
if (home instanceof HomeData.Security securityData) {
|
||||
securityData.getKnownPersons().forEach(person -> action.apply(person, homeUID));
|
||||
}
|
||||
Map<String, ThingUID> bridgesUids = new HashMap<>();
|
||||
|
||||
home.getRooms().values().stream().forEach(room -> {
|
||||
|
@ -18,7 +18,6 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -134,8 +133,7 @@ public interface CommonInterface {
|
||||
if (thing instanceof Bridge) {
|
||||
return ((Bridge) thing).getThings().stream().filter(Thing::isEnabled)
|
||||
.filter(th -> th.getStatusInfo().getStatusDetail() != ThingStatusDetail.BRIDGE_OFFLINE)
|
||||
.map(Thing::getHandler).filter(Objects::nonNull).map(CommonInterface.class::cast)
|
||||
.collect(Collectors.toList());
|
||||
.map(Thing::getHandler).filter(Objects::nonNull).map(CommonInterface.class::cast).toList();
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
|
@ -12,13 +12,20 @@
|
||||
*/
|
||||
package org.openhab.binding.netatmo.internal.handler.capability;
|
||||
|
||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||
import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAObject;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent;
|
||||
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
|
||||
import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
|
||||
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* {@link AlarmEventCapability} gives the ability to handle Alarm modules events
|
||||
@ -34,6 +41,22 @@ public class AlarmEventCapability extends HomeSecurityThingCapability {
|
||||
super(handler, descriptionProvider, channelHelpers);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateWebhookEvent(WebhookEvent event) {
|
||||
super.updateWebhookEvent(event);
|
||||
|
||||
final ThingUID thingUid = handler.getThing().getUID();
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_TYPE),
|
||||
toStringType(event.getEventType()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_TIME),
|
||||
toDateTimeType(event.getTime()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_SUBTYPE),
|
||||
event.getSubTypeDescription().map(d -> toStringType(d)).orElse(UnDefType.NULL));
|
||||
final String message = event.getName();
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_MESSAGE),
|
||||
message == null || message.isBlank() ? UnDefType.NULL : toStringType(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<NAObject> updateReadings() {
|
||||
return getSecurityCapability().map(cap -> cap.getDeviceLastEvent(handler.getId(), moduleType.apiName))
|
||||
|
@ -17,7 +17,6 @@ import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -35,8 +34,10 @@ import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
|
||||
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.StateOption;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
@ -53,6 +54,8 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
||||
|
||||
protected @Nullable String localUrl;
|
||||
protected @Nullable String vpnUrl;
|
||||
private boolean hasSubEventGroup;
|
||||
private boolean hasLastEventGroup;
|
||||
|
||||
public CameraCapability(CommonInterface handler, NetatmoDescriptionProvider descriptionProvider,
|
||||
List<ChannelHelper> channelHelpers) {
|
||||
@ -63,6 +66,13 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
||||
"CameraCapability must find a CameraChannelHelper, please file a bug report."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
Thing thing = handler.getThing();
|
||||
hasSubEventGroup = !thing.getChannelsOfGroup(GROUP_SUB_EVENT).isEmpty();
|
||||
hasLastEventGroup = !thing.getChannelsOfGroup(GROUP_LAST_EVENT).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHomeStatusModule(HomeStatusModule newData) {
|
||||
super.updateHomeStatusModule(newData);
|
||||
@ -85,23 +95,13 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
||||
protected void updateWebhookEvent(WebhookEvent event) {
|
||||
super.updateWebhookEvent(event);
|
||||
|
||||
final ThingUID thingUid = handler.getThing().getUID();
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_TYPE),
|
||||
toStringType(event.getEventType()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_TIME),
|
||||
toDateTimeType(event.getTime()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_SNAPSHOT),
|
||||
toRawType(event.getSnapshotUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_SNAPSHOT_URL),
|
||||
toStringType(event.getSnapshotUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_VIGNETTE),
|
||||
toRawType(event.getVignetteUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_VIGNETTE_URL),
|
||||
toStringType(event.getVignetteUrl()));
|
||||
if (hasSubEventGroup) {
|
||||
updateSubGroup(event, thing.getUID(), GROUP_SUB_EVENT);
|
||||
}
|
||||
|
||||
final String message = event.getName();
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_SUB_EVENT, CHANNEL_EVENT_MESSAGE),
|
||||
message == null || message.isBlank() ? UnDefType.NULL : toStringType(message));
|
||||
if (hasLastEventGroup) {
|
||||
updateSubGroup(event, thing.getUID(), GROUP_LAST_EVENT);
|
||||
}
|
||||
|
||||
// The channel should get triggered at last (after super and sub methods), because this allows rules to access
|
||||
// the new updated data from the other channels.
|
||||
@ -111,6 +111,25 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
||||
handler.triggerChannel(CHANNEL_HOME_EVENT, eventType);
|
||||
}
|
||||
|
||||
private void updateSubGroup(WebhookEvent event, ThingUID thingUid, String group) {
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_TYPE), toStringType(event.getEventType()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_TIME), toDateTimeType(event.getTime()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_SNAPSHOT), toRawType(event.getSnapshotUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_SNAPSHOT_URL),
|
||||
toStringType(event.getSnapshotUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_VIGNETTE), toRawType(event.getVignetteUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_VIGNETTE_URL),
|
||||
toStringType(event.getVignetteUrl()));
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_SUBTYPE),
|
||||
event.getSubTypeDescription().map(d -> toStringType(d)).orElse(UnDefType.NULL));
|
||||
final String message = event.getName();
|
||||
handler.updateState(new ChannelUID(thingUid, group, CHANNEL_EVENT_MESSAGE),
|
||||
message == null || message.isBlank() ? UnDefType.NULL : toStringType(message));
|
||||
State personId = event.getPersons().isEmpty() ? UnDefType.NULL
|
||||
: toStringType(event.getPersons().values().iterator().next().getId());
|
||||
handler.updateState(personChannelUID, personId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(String channelName, Command command) {
|
||||
if (command instanceof OnOffType && CHANNEL_MONITORING.equals(channelName)) {
|
||||
@ -125,8 +144,8 @@ public class CameraCapability extends HomeSecurityThingCapability {
|
||||
super.beforeNewData();
|
||||
getSecurityCapability().ifPresent(cap -> {
|
||||
NAObjectMap<HomeDataPerson> persons = cap.getPersons();
|
||||
descriptionProvider.setStateOptions(personChannelUID, persons.values().stream()
|
||||
.map(p -> new StateOption(p.getId(), p.getName())).collect(Collectors.toList()));
|
||||
descriptionProvider.setStateOptions(personChannelUID,
|
||||
persons.values().stream().map(p -> new StateOption(p.getId(), p.getName())).toList());
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -63,32 +63,32 @@ public class Capability {
|
||||
|
||||
public final @Nullable String setNewData(NAObject newData) {
|
||||
beforeNewData();
|
||||
if (newData instanceof HomeData) {
|
||||
updateHomeData((HomeData) newData);
|
||||
if (newData instanceof HomeData homeData) {
|
||||
updateHomeData(homeData);
|
||||
}
|
||||
if (newData instanceof HomeStatus) {
|
||||
updateHomeStatus((HomeStatus) newData);
|
||||
if (newData instanceof HomeStatus homeStatus) {
|
||||
updateHomeStatus(homeStatus);
|
||||
}
|
||||
if (newData instanceof HomeStatusModule) {
|
||||
updateHomeStatusModule((HomeStatusModule) newData);
|
||||
if (newData instanceof HomeStatusModule homeStatusModule) {
|
||||
updateHomeStatusModule(homeStatusModule);
|
||||
}
|
||||
if (newData instanceof Event) {
|
||||
updateEvent((Event) newData);
|
||||
|
||||
if (newData instanceof HomeEvent homeEvent) {
|
||||
updateHomeEvent(homeEvent);
|
||||
} else if (newData instanceof WebhookEvent webhookEvent && webhookEvent.getEventType().validFor(moduleType)) {
|
||||
updateWebhookEvent(webhookEvent);
|
||||
} else if (newData instanceof Event event) {
|
||||
updateEvent(event);
|
||||
}
|
||||
if (newData instanceof WebhookEvent) {
|
||||
updateWebhookEvent((WebhookEvent) newData);
|
||||
|
||||
if (newData instanceof NAThing naThing) {
|
||||
updateNAThing(naThing);
|
||||
}
|
||||
if (newData instanceof HomeEvent) {
|
||||
updateHomeEvent((HomeEvent) newData);
|
||||
if (newData instanceof NAMain naMain) {
|
||||
updateNAMain(naMain);
|
||||
}
|
||||
if (newData instanceof NAThing) {
|
||||
updateNAThing((NAThing) newData);
|
||||
}
|
||||
if (newData instanceof NAMain) {
|
||||
updateNAMain((NAMain) newData);
|
||||
}
|
||||
if (newData instanceof Device) {
|
||||
updateNADevice((Device) newData);
|
||||
if (newData instanceof Device device) {
|
||||
updateNADevice(device);
|
||||
}
|
||||
afterNewData(newData);
|
||||
return statusReason;
|
||||
|
@ -15,7 +15,6 @@ package org.openhab.binding.netatmo.internal.handler.capability;
|
||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.netatmo.internal.api.EnergyApi;
|
||||
@ -26,6 +25,7 @@ import org.openhab.binding.netatmo.internal.api.dto.HomeData;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeDataRoom;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.Room;
|
||||
import org.openhab.binding.netatmo.internal.config.HomeConfiguration;
|
||||
@ -65,38 +65,41 @@ public class EnergyCapability extends RestCapability<EnergyApi> {
|
||||
|
||||
@Override
|
||||
protected void updateHomeData(HomeData homeData) {
|
||||
NAObjectMap<HomeDataRoom> rooms = homeData.getRooms();
|
||||
NAObjectMap<HomeDataModule> modules = homeData.getModules();
|
||||
handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
rooms.getOpt(childId)
|
||||
.ifPresentOrElse(roomData -> childHandler.setNewData(roomData.ignoringForThingUpdate()), () -> {
|
||||
modules.getOpt(childId)
|
||||
.ifPresent(childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
descriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), GROUP_ENERGY, CHANNEL_PLANNING),
|
||||
homeData.getThermSchedules().stream().map(p -> new StateOption(p.getId(), p.getName()))
|
||||
.collect(Collectors.toList()));
|
||||
setPointDefaultDuration = homeData.getThermSetpointDefaultDuration();
|
||||
if (homeData instanceof HomeData.Energy energyData) {
|
||||
NAObjectMap<HomeDataRoom> rooms = energyData.getRooms();
|
||||
NAObjectMap<HomeDataModule> modules = energyData.getModules();
|
||||
handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
rooms.getOpt(childId)
|
||||
.ifPresentOrElse(roomData -> childHandler.setNewData(roomData.ignoringForThingUpdate()), () -> {
|
||||
modules.getOpt(childId).ifPresent(
|
||||
childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
descriptionProvider.setStateOptions(new ChannelUID(thing.getUID(), GROUP_ENERGY, CHANNEL_PLANNING),
|
||||
energyData.getThermSchedules().stream().map(p -> new StateOption(p.getId(), p.getName())).toList());
|
||||
setPointDefaultDuration = energyData.getThermSetpointDefaultDuration();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateHomeStatus(HomeStatus homeStatus) {
|
||||
NAObjectMap<Room> rooms = homeStatus.getRooms();
|
||||
NAObjectMap<HomeStatusModule> modules = homeStatus.getModules();
|
||||
handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
rooms.getOpt(childId).ifPresentOrElse(roomData -> childHandler.setNewData(roomData), () -> {
|
||||
modules.getOpt(childId).ifPresent(moduleData -> {
|
||||
childHandler.setNewData(moduleData);
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
if (homeStatus instanceof NAHomeStatus.Energy energyStatus) {
|
||||
NAObjectMap<Room> rooms = energyStatus.getRooms();
|
||||
NAObjectMap<HomeStatusModule> modules = energyStatus.getModules();
|
||||
handler.getActiveChildren(FeatureArea.ENERGY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
rooms.getOpt(childId).ifPresentOrElse(roomData -> childHandler.setNewData(roomData), () -> {
|
||||
modules.getOpt(childId).ifPresent(moduleData -> {
|
||||
childHandler.setNewData(moduleData);
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setThermPoint(String roomId, SetpointMode mode, long endtime, double temp) {
|
||||
|
@ -13,11 +13,11 @@
|
||||
package org.openhab.binding.netatmo.internal.handler.capability;
|
||||
|
||||
import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||
import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.*;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -28,13 +28,16 @@ import org.openhab.binding.netatmo.internal.api.dto.Event;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeDataModule;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAObject;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.WebhookEvent;
|
||||
import org.openhab.binding.netatmo.internal.handler.CommonInterface;
|
||||
import org.openhab.binding.netatmo.internal.handler.channelhelper.ChannelHelper;
|
||||
import org.openhab.binding.netatmo.internal.providers.NetatmoDescriptionProvider;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.StateOption;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* {@link PersonCapability} gives the ability to handle Person specifics
|
||||
@ -60,7 +63,7 @@ public class PersonCapability extends HomeSecurityThingCapability {
|
||||
Stream<HomeDataModule> cameras = cap.getModules().values().stream()
|
||||
.filter(module -> module.getType() == ModuleType.WELCOME);
|
||||
descriptionProvider.setStateOptions(cameraChannelUID,
|
||||
cameras.map(p -> new StateOption(p.getId(), p.getName())).collect(Collectors.toList()));
|
||||
cameras.map(p -> new StateOption(p.getId(), p.getName())).toList());
|
||||
});
|
||||
}
|
||||
|
||||
@ -71,6 +74,28 @@ public class PersonCapability extends HomeSecurityThingCapability {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateWebhookEvent(WebhookEvent event) {
|
||||
super.updateWebhookEvent(event);
|
||||
|
||||
ThingUID thingUid = thing.getUID();
|
||||
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_SUBTYPE),
|
||||
event.getSubTypeDescription().map(d -> toStringType(d)).orElse(UnDefType.NULL));
|
||||
|
||||
final String message = event.getName();
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_MESSAGE),
|
||||
message == null || message.isBlank() ? UnDefType.NULL : toStringType(message));
|
||||
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_TIME),
|
||||
toDateTimeType(event.getTime()));
|
||||
|
||||
handler.updateState(new ChannelUID(thingUid, GROUP_LAST_EVENT, CHANNEL_EVENT_SNAPSHOT),
|
||||
toRawType(event.getSnapshotUrl()));
|
||||
|
||||
handler.updateState(cameraChannelUID, toStringType(event.getCameraId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEvent(Event event) {
|
||||
super.updateEvent(event);
|
||||
|
@ -31,6 +31,7 @@ import org.openhab.binding.netatmo.internal.api.dto.HomeDataPerson;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeEvent;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeStatusModule;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeStatusPerson;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAObject;
|
||||
import org.openhab.binding.netatmo.internal.config.HomeConfiguration;
|
||||
@ -69,34 +70,38 @@ class SecurityCapability extends RestCapability<SecurityApi> {
|
||||
|
||||
@Override
|
||||
protected void updateHomeData(HomeData homeData) {
|
||||
persons = homeData.getPersons();
|
||||
modules = homeData.getModules();
|
||||
handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
persons.getOpt(childId)
|
||||
.ifPresentOrElse(personData -> childHandler.setNewData(personData.ignoringForThingUpdate()), () -> {
|
||||
modules.getOpt(childId)
|
||||
.ifPresent(childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
if (homeData instanceof HomeData.Security securityData) {
|
||||
persons = securityData.getPersons();
|
||||
modules = homeData.getModules();
|
||||
handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
persons.getOpt(childId).ifPresentOrElse(
|
||||
personData -> childHandler.setNewData(personData.ignoringForThingUpdate()), () -> {
|
||||
modules.getOpt(childId).ifPresent(
|
||||
childData -> childHandler.setNewData(childData.ignoringForThingUpdate()));
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateHomeStatus(HomeStatus homeStatus) {
|
||||
NAObjectMap<HomeStatusPerson> persons = homeStatus.getPersons();
|
||||
NAObjectMap<HomeStatusModule> modules = homeStatus.getModules();
|
||||
handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
persons.getOpt(childId).ifPresentOrElse(personData -> childHandler.setNewData(personData), () -> {
|
||||
modules.getOpt(childId).ifPresent(childData -> {
|
||||
childHandler.setNewData(childData);
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
if (homeStatus instanceof NAHomeStatus.Security securityStatus) {
|
||||
NAObjectMap<HomeStatusPerson> persons = securityStatus.getPersons();
|
||||
NAObjectMap<HomeStatusModule> modules = securityStatus.getModules();
|
||||
handler.getActiveChildren(FeatureArea.SECURITY).forEach(childHandler -> {
|
||||
String childId = childHandler.getId();
|
||||
persons.getOpt(childId).ifPresentOrElse(personData -> childHandler.setNewData(personData), () -> {
|
||||
modules.getOpt(childId).ifPresent(childData -> {
|
||||
childHandler.setNewData(childData);
|
||||
modules.values().stream().filter(module -> childId.equals(module.getBridge()))
|
||||
.forEach(bridgedModule -> childHandler.setNewData(bridgedModule));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,13 +50,12 @@ public class EnergyChannelHelper extends ChannelHelper {
|
||||
|
||||
@Override
|
||||
protected @Nullable State internalGetProperty(String channelId, NAThing data, Configuration config) {
|
||||
if (data instanceof HomeData) {
|
||||
HomeData homeData = (HomeData) data;
|
||||
SetpointMode thermMode = homeData.getThermMode();
|
||||
ThermProgram currentProgram = homeData.getActiveProgram();
|
||||
if (data instanceof HomeData.Energy energyData) {
|
||||
SetpointMode thermMode = energyData.getThermMode();
|
||||
ThermProgram currentProgram = energyData.getActiveProgram();
|
||||
switch (channelId) {
|
||||
case CHANNEL_SETPOINT_DURATION:
|
||||
return toQuantityType(homeData.getThermSetpointDefaultDuration(), Units.MINUTE);
|
||||
return toQuantityType(energyData.getThermSetpointDefaultDuration(), Units.MINUTE);
|
||||
case CHANNEL_PLANNING:
|
||||
return (currentProgram != null ? toStringType(currentProgram.getName()) : null);
|
||||
case CHANNEL_SETPOINT_END_TIME:
|
||||
|
@ -54,7 +54,7 @@ public class PersonChannelHelper extends ChannelHelper {
|
||||
HomeStatusPerson person = (HomeStatusPerson) naThing;
|
||||
switch (channelId) {
|
||||
case CHANNEL_PERSON_AT_HOME:
|
||||
return OnOffType.from(!person.isOutOfSight());
|
||||
return OnOffType.from(person.atHome());
|
||||
case CHANNEL_LAST_SEEN:
|
||||
return toDateTimeType(person.getLastSeen());
|
||||
}
|
||||
|
@ -17,15 +17,14 @@ import static org.openhab.binding.netatmo.internal.utils.ChannelTypeUtils.toRawT
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeData;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeDataPerson;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.HomeStatusPerson;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus.HomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAHomeStatus;
|
||||
import org.openhab.binding.netatmo.internal.api.dto.NAObject;
|
||||
import org.openhab.binding.netatmo.internal.deserialization.NAObjectMap;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
@ -50,16 +49,11 @@ public class SecurityChannelHelper extends ChannelHelper {
|
||||
@Override
|
||||
public void setNewData(@Nullable NAObject data) {
|
||||
super.setNewData(data);
|
||||
if (data instanceof HomeData) {
|
||||
HomeData homeData = (HomeData) data;
|
||||
knownIds = homeData.getPersons().values().stream().filter(person -> person.isKnown()).map(p -> p.getId())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
if (data instanceof HomeStatus) {
|
||||
HomeStatus status = (HomeStatus) data;
|
||||
NAObjectMap<HomeStatusPerson> allPersons = status.getPersons();
|
||||
List<HomeStatusPerson> present = allPersons.values().stream().filter(p -> !p.isOutOfSight())
|
||||
.collect(Collectors.toList());
|
||||
if (data instanceof HomeData.Security securityData) {
|
||||
knownIds = securityData.getKnownPersons().stream().map(HomeDataPerson::getId).toList();
|
||||
} else if (data instanceof NAHomeStatus.Security securityStatus) {
|
||||
List<HomeStatusPerson> present = securityStatus.getPersons().values().stream()
|
||||
.filter(HomeStatusPerson::atHome).toList();
|
||||
|
||||
persons = present.size();
|
||||
unknowns = present.stream().filter(person -> !knownIds.contains(person.getId())).count();
|
||||
|
@ -18,7 +18,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -63,8 +62,7 @@ public class NetatmoThingTypeProvider implements ThingTypeProvider {
|
||||
@Override
|
||||
public Collection<ThingType> getThingTypes(@Nullable Locale locale) {
|
||||
return ModuleType.AS_SET.stream().filter(mt -> mt != ModuleType.UNKNOWN)
|
||||
.map(mt -> Optional.ofNullable(getThingType(mt.thingTypeUID, locale))).map(Optional::get)
|
||||
.collect(Collectors.toList());
|
||||
.map(mt -> Optional.ofNullable(getThingType(mt.thingTypeUID, locale))).map(Optional::get).toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,7 +93,7 @@ public class NetatmoThingTypeProvider implements ThingTypeProvider {
|
||||
|
||||
private List<ChannelGroupDefinition> getGroupDefinitions(ModuleType thingType) {
|
||||
return thingType.getGroupTypes().stream().map(groupType -> new ChannelGroupDefinition(toGroupName(groupType),
|
||||
new ChannelGroupTypeUID(BINDING_ID, groupType))).collect(Collectors.toList());
|
||||
new ChannelGroupTypeUID(BINDING_ID, groupType))).toList();
|
||||
}
|
||||
|
||||
public static String toGroupName(String groupeTypeName) {
|
||||
|
@ -70,8 +70,8 @@ channel-group-type.netatmo.rain.channel.sum-1.label = Rain 1h
|
||||
channel-group-type.netatmo.rain.channel.sum-1.description = Quantity of water over last hour.
|
||||
channel-group-type.netatmo.rain.channel.sum-24.label = Rain 24h
|
||||
channel-group-type.netatmo.rain.channel.sum-24.description = Quantity of water during the current day.
|
||||
channel-group-type.netatmo.security.label = Home Security
|
||||
channel-group-type.netatmo.security-event.label = Home Security Event
|
||||
channel-group-type.netatmo.security.label = Home Security
|
||||
channel-group-type.netatmo.setpoint.label = Setpoint
|
||||
channel-group-type.netatmo.setpoint.channel.end.label = Setpoint End
|
||||
channel-group-type.netatmo.setpoint.channel.end.description = End time of the currently applied setpoint.
|
||||
@ -81,13 +81,6 @@ channel-group-type.netatmo.signal.label = Signal
|
||||
channel-group-type.netatmo.siren.label = Siren Status
|
||||
channel-group-type.netatmo.status-doorbell.label = Camera Status
|
||||
channel-group-type.netatmo.status.label = Camera Status
|
||||
channel-group-type.netatmo.sub-event.label = Sub Event
|
||||
channel-group-type.netatmo.sub-event.channel.time.label = Sub-Event Timestamp
|
||||
channel-group-type.netatmo.sub-event.channel.time.description = Moment when the sub-event occurred.
|
||||
channel-group-type.netatmo.sub-event.channel.vignette.label = Vignette
|
||||
channel-group-type.netatmo.sub-event.channel.vignette.description = Vignette of the Snapshot.
|
||||
channel-group-type.netatmo.sub-event.channel.vignette-url.label = Vignette URL
|
||||
channel-group-type.netatmo.sub-event.channel.vignette-url.description = URL of the vignette.
|
||||
channel-group-type.netatmo.sub-event-doorbell.label = Sub Event
|
||||
channel-group-type.netatmo.sub-event-doorbell.channel.time.label = Sub-Event Timestamp
|
||||
channel-group-type.netatmo.sub-event-doorbell.channel.time.description = Moment when the sub-event occurred.
|
||||
@ -95,6 +88,13 @@ channel-group-type.netatmo.sub-event-doorbell.channel.vignette.label = Vignette
|
||||
channel-group-type.netatmo.sub-event-doorbell.channel.vignette.description = Vignette of the Snapshot.
|
||||
channel-group-type.netatmo.sub-event-doorbell.channel.vignette-url.label = Vignette URL
|
||||
channel-group-type.netatmo.sub-event-doorbell.channel.vignette-url.description = URL of the vignette.
|
||||
channel-group-type.netatmo.sub-event.label = Sub Event
|
||||
channel-group-type.netatmo.sub-event.channel.time.label = Sub-Event Timestamp
|
||||
channel-group-type.netatmo.sub-event.channel.time.description = Moment when the sub-event occurred.
|
||||
channel-group-type.netatmo.sub-event.channel.vignette.label = Vignette
|
||||
channel-group-type.netatmo.sub-event.channel.vignette.description = Vignette of the Snapshot.
|
||||
channel-group-type.netatmo.sub-event.channel.vignette-url.label = Vignette URL
|
||||
channel-group-type.netatmo.sub-event.channel.vignette-url.description = URL of the vignette.
|
||||
channel-group-type.netatmo.tag.label = Door Tag
|
||||
channel-group-type.netatmo.temperature-extended.label = Temperature
|
||||
channel-group-type.netatmo.temperature-extended.channel.max-time.label = Today Max Timestamp
|
||||
@ -189,6 +189,8 @@ channel-type.netatmo.event-subtype.state.option.BATTERY_LOW = Battery low
|
||||
channel-type.netatmo.event-subtype.state.option.BATTERY_VERY_LOW = Battery very low
|
||||
channel-type.netatmo.event-subtype.state.option.SMOKE_CLEARED = Smoke cleared
|
||||
channel-type.netatmo.event-subtype.state.option.SMOKE_DETECTED = Smoke detected
|
||||
channel-type.netatmo.event-subtype.state.option.HUSH_ACTIVATED = Smoke detection activated
|
||||
channel-type.netatmo.event-subtype.state.option.HUSH_DEACTIVATED = Smoke detection deactivated
|
||||
channel-type.netatmo.event-subtype.state.option.WIFI_STATUS_OK = Wi-Fi status ok
|
||||
channel-type.netatmo.event-subtype.state.option.WIFI_STATUS_ERROR = Wi-Fi status error
|
||||
channel-type.netatmo.event-subtype.state.option.CO_OK = Carbon Monoxide OK
|
||||
|
@ -404,6 +404,8 @@
|
||||
<option value="BATTERY_VERY_LOW">Battery very low</option>
|
||||
<option value="SMOKE_CLEARED">Smoke cleared</option>
|
||||
<option value="SMOKE_DETECTED">Smoke detected</option>
|
||||
<option value="HUSH_ACTIVATED">Smoke detection activated</option>
|
||||
<option value="HUSH_DEACTIVATED">Smoke detection deactivated</option>
|
||||
<option value="WIFI_STATUS_OK">Wi-Fi status ok</option>
|
||||
<option value="WIFI_STATUS_ERROR">Wi-Fi status error</option>
|
||||
<option value="CO_OK">Carbon Monoxide OK</option>
|
||||
|
@ -17,6 +17,7 @@ import static org.openhab.binding.netatmo.internal.NetatmoBindingConstants.*;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.binding.netatmo.internal.api.data.EventType;
|
||||
@ -27,9 +28,10 @@ import org.openhab.core.types.State;
|
||||
/**
|
||||
* @author Sven Strohschein - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EventCameraChannelHelperTest {
|
||||
|
||||
private EventCameraChannelHelper helper;
|
||||
private @NonNullByDefault({}) EventCameraChannelHelper helper;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
|
Loading…
Reference in New Issue
Block a user