mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[freeboxos] Complete Alarm system handling (#17233)
* Initiating the addition of the PIR sensor * Finalized integration of the alarm system * Corrected bug in initialization of basic-shutter Signed-off-by: Gaël L'hopital <gael@lhopital.org>
This commit is contained in:
parent
5975a5b065
commit
b00db4dd01
@ -71,9 +71,9 @@ public class FreeboxOsBindingConstants {
|
||||
public static final Set<ThingTypeUID> THINGS_TYPES_UIDS = Set.of(THING_TYPE_FXS, THING_TYPE_DECT, THING_TYPE_CALL,
|
||||
THING_TYPE_HOST, THING_TYPE_VM, THING_TYPE_PLAYER, THING_TYPE_ACTIVE_PLAYER, THING_TYPE_DELTA,
|
||||
THING_TYPE_REVOLUTION, THING_TYPE_REPEATER, THING_TYPE_WIFI_HOST, THING_TYPE_FREEPLUG);
|
||||
public static final Set<ThingTypeUID> HOME_TYPES_UIDS = Set.of(Category.BASIC_SHUTTER.getThingTypeUID(),
|
||||
Category.SHUTTER.getThingTypeUID(), Category.KFB.getThingTypeUID(), Category.CAMERA.getThingTypeUID(),
|
||||
Category.ALARM.getThingTypeUID());
|
||||
public static final Set<ThingTypeUID> HOME_TYPES_UIDS = Set.of(Category.BASIC_SHUTTER.thingTypeUID,
|
||||
Category.SHUTTER.thingTypeUID, Category.KFB.thingTypeUID, Category.CAMERA.thingTypeUID,
|
||||
Category.ALARM.thingTypeUID, Category.PIR.thingTypeUID);
|
||||
|
||||
protected static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
|
||||
.of(BRIDGE_TYPE_UIDS, THINGS_TYPES_UIDS, HOME_TYPES_UIDS).flatMap(Set::stream).collect(Collectors.toSet());
|
||||
@ -175,20 +175,30 @@ public class FreeboxOsBindingConstants {
|
||||
public static final String XDSL_UPTIME = "uptime";
|
||||
|
||||
// Home channels
|
||||
public static final String TIMESTAMP_POSTFIX = "-timestamp";
|
||||
|
||||
public static final String KEYFOB_ENABLE = "enable";
|
||||
public static final String KEYFOB_PUSHED = "pushed";
|
||||
public static final String KEYFOB_PUSHED_UPDATE = KEYFOB_PUSHED + TIMESTAMP_POSTFIX;
|
||||
|
||||
public static final String NODE_BATTERY = "battery";
|
||||
public static final String SHUTTER_POSITION = "position-set";
|
||||
public static final String SHUTTER_STOP = "stop";
|
||||
public static final String BASIC_SHUTTER_STATE = "state";
|
||||
public static final String BASIC_SHUTTER_UP = "up";
|
||||
public static final String BASIC_SHUTTER_DOWN = "down";
|
||||
// public static final String BASIC_SHUTTER_CMD = "basic-shutter";
|
||||
public static final String ALARM_PIN = "pin";
|
||||
public static final String ALARM_SOUND = "sound";
|
||||
public static final String ALARM_VOLUME = "volume";
|
||||
public static final String ALARM_TIMEOUT1 = "timeout1";
|
||||
public static final String ALARM_TIMEOUT2 = "timeout2";
|
||||
public static final String ALARM_TIMEOUT3 = "timeout3";
|
||||
public static final String ALARM_STATE = "state";
|
||||
|
||||
public static final String PIR_TAMPER = "tamper";
|
||||
public static final String PIR_TRIGGER = "trigger";
|
||||
public static final String PIR_TAMPER_UPDATE = PIR_TAMPER + TIMESTAMP_POSTFIX;
|
||||
public static final String PIR_TRIGGER_UPDATE = PIR_TRIGGER + TIMESTAMP_POSTFIX;
|
||||
|
||||
public static final Set<Command> TRUE_COMMANDS = Set.of(OnOffType.ON, UpDownType.UP, OpenClosedType.OPEN);
|
||||
public static final Set<Class<?>> ON_OFF_CLASSES = Set.of(OnOffType.class, UpDownType.class, OpenClosedType.class);
|
||||
|
@ -20,7 +20,6 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.freeboxos.internal.api.ApiHandler;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.FreeboxOsSession;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.Category;
|
||||
@ -35,6 +34,7 @@ import org.openhab.binding.freeboxos.internal.handler.FreeplugHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.FxsHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.HostHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.KeyfobHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.PirHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.PlayerHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.RepeaterHandler;
|
||||
import org.openhab.binding.freeboxos.internal.handler.RevolutionHandler;
|
||||
@ -56,6 +56,7 @@ import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Deactivate;
|
||||
import org.osgi.service.component.annotations.Modified;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.slf4j.Logger;
|
||||
@ -76,7 +77,6 @@ public class FreeboxOsHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private final NetworkAddressService networkAddressService;
|
||||
private final AudioHTTPServer audioHTTPServer;
|
||||
private final HttpClient httpClient;
|
||||
private final ApiHandler apiHandler;
|
||||
private String callbackURL = "";
|
||||
|
||||
@ -88,13 +88,19 @@ public class FreeboxOsHandlerFactory extends BaseThingHandlerFactory {
|
||||
super.activate(componentContext);
|
||||
|
||||
this.audioHTTPServer = audioHTTPServer;
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
this.networkAddressService = networkAddressService;
|
||||
this.apiHandler = new ApiHandler(httpClient, timeZoneProvider);
|
||||
this.apiHandler = new ApiHandler(httpClientFactory, timeZoneProvider);
|
||||
|
||||
configChanged(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deactivate
|
||||
public void deactivate(ComponentContext componentContext) {
|
||||
super.deactivate(componentContext);
|
||||
apiHandler.dispose();
|
||||
}
|
||||
|
||||
@Modified
|
||||
public void configChanged(Map<String, Object> config) {
|
||||
String timeout = (String) config.getOrDefault(TIMEOUT, "8");
|
||||
@ -149,16 +155,18 @@ public class FreeboxOsHandlerFactory extends BaseThingHandlerFactory {
|
||||
return new ActivePlayerHandler(thing);
|
||||
} else if (THING_TYPE_PLAYER.equals(thingTypeUID)) {
|
||||
return new PlayerHandler(thing);
|
||||
} else if (Category.BASIC_SHUTTER.getThingTypeUID().equals(thingTypeUID)) {
|
||||
} else if (Category.BASIC_SHUTTER.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new BasicShutterHandler(thing);
|
||||
} else if (Category.SHUTTER.getThingTypeUID().equals(thingTypeUID)) {
|
||||
} else if (Category.SHUTTER.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new ShutterHandler(thing);
|
||||
} else if (Category.ALARM.getThingTypeUID().equals(thingTypeUID)) {
|
||||
} else if (Category.ALARM.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new AlarmHandler(thing);
|
||||
} else if (Category.KFB.getThingTypeUID().equals(thingTypeUID)) {
|
||||
} else if (Category.KFB.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new KeyfobHandler(thing);
|
||||
} else if (Category.CAMERA.getThingTypeUID().equals(thingTypeUID)) {
|
||||
} else if (Category.CAMERA.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new CameraHandler(thing);
|
||||
} else if (Category.PIR.thingTypeUID.equals(thingTypeUID)) {
|
||||
return new PirHandler(thing);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -32,11 +32,13 @@ import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpStatus.Code;
|
||||
import org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants;
|
||||
import org.openhab.binding.freeboxos.internal.api.deserialization.ForegroundAppDeserializer;
|
||||
import org.openhab.binding.freeboxos.internal.api.deserialization.ListDeserializer;
|
||||
import org.openhab.binding.freeboxos.internal.api.deserialization.StrictEnumTypeAdapterFactory;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.PlayerManager.ForegroundApp;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -58,9 +60,10 @@ import inet.ipaddr.mac.MACAddress;
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class ApiHandler {
|
||||
public static final String AUTH_HEADER = "X-Fbx-App-Auth";
|
||||
private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
private static final String CONTENT_TYPE = "application/json; charset=" + DEFAULT_CHARSET.name();
|
||||
private static final int RESPONSE_BUFFER_SIZE = 65536;
|
||||
public static final String AUTH_HEADER = "X-Fbx-App-Auth";
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(ApiHandler.class);
|
||||
private final HttpClient httpClient;
|
||||
@ -68,8 +71,7 @@ public class ApiHandler {
|
||||
|
||||
private long timeoutInMs = TimeUnit.SECONDS.toMillis(8);
|
||||
|
||||
public ApiHandler(HttpClient httpClient, TimeZoneProvider timeZoneProvider) {
|
||||
this.httpClient = httpClient;
|
||||
public ApiHandler(HttpClientFactory httpClientFactory, TimeZoneProvider timeZoneProvider) {
|
||||
this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||
.registerTypeAdapter(ZonedDateTime.class,
|
||||
(JsonDeserializer<ZonedDateTime>) (json, type, jsonDeserializationContext) -> {
|
||||
@ -86,6 +88,21 @@ public class ApiHandler {
|
||||
.registerTypeAdapter(ForegroundApp.class, new ForegroundAppDeserializer())
|
||||
.registerTypeAdapter(List.class, new ListDeserializer()).serializeNulls()
|
||||
.registerTypeAdapterFactory(new StrictEnumTypeAdapterFactory()).create();
|
||||
httpClient = httpClientFactory.createHttpClient(FreeboxOsBindingConstants.BINDING_ID);
|
||||
httpClient.setResponseBufferSize(RESPONSE_BUFFER_SIZE);
|
||||
try {
|
||||
httpClient.start();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to start httpClient: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
try {
|
||||
httpClient.stop();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to stop httpClient: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized <T> T executeUri(URI uri, HttpMethod method, Class<T> clazz, @Nullable String sessionToken,
|
||||
|
@ -14,8 +14,10 @@ package org.openhab.binding.freeboxos.internal.api.rest;
|
||||
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.BINDING_ID;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -102,17 +104,25 @@ public class HomeManager extends RestManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static record LogEntry(long timestamp, int value) {
|
||||
public static record LogEntry(Long timestamp, int value) {
|
||||
}
|
||||
|
||||
public static record Endpoint(int id, String name, String label, EpType epType, Visibility visibility, int refresh,
|
||||
ValueType valueType, EndpointUi ui, @Nullable String category, Object value, List<LogEntry> history) {
|
||||
ValueType valueType, EndpointUi ui, @Nullable String category, Object value,
|
||||
@Nullable List<LogEntry> history) {
|
||||
|
||||
private static final Comparator<LogEntry> HISTORY_COMPARATOR = Comparator.comparing(LogEntry::timestamp);
|
||||
|
||||
private enum Visibility {
|
||||
INTERNAL,
|
||||
NORMAL,
|
||||
DASHBOARD,
|
||||
UNKNOWN
|
||||
}
|
||||
|
||||
public Optional<LogEntry> getLastChange() {
|
||||
return history != null ? history.stream().max(HISTORY_COMPARATOR) : Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private enum Status {
|
||||
@ -129,16 +139,13 @@ public class HomeManager extends RestManager {
|
||||
ALARM,
|
||||
KFB,
|
||||
CAMERA,
|
||||
PIR,
|
||||
UNKNOWN;
|
||||
|
||||
private final ThingTypeUID thingTypeUID;
|
||||
public final ThingTypeUID thingTypeUID;
|
||||
|
||||
Category() {
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, name().toLowerCase());
|
||||
}
|
||||
|
||||
public ThingTypeUID getThingTypeUID() {
|
||||
return thingTypeUID;
|
||||
thingTypeUID = new ThingTypeUID(BINDING_ID, name().toLowerCase().replace('_', '-'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -148,6 +155,17 @@ public class HomeManager extends RestManager {
|
||||
|
||||
public static record HomeNode(int id, @Nullable String name, @Nullable String label, Category category,
|
||||
Status status, List<Endpoint> showEndpoints, Map<String, String> props, NodeType type) {
|
||||
|
||||
private static final Comparator<Endpoint> ENPOINT_COMPARATOR = Comparator.comparing(Endpoint::refresh);
|
||||
|
||||
public Optional<Endpoint> getMinRefresh() {
|
||||
return showEndpoints.stream().filter(ep -> EpType.SIGNAL.equals(ep.epType) && ep.refresh() != 0)
|
||||
.min(ENPOINT_COMPARATOR);
|
||||
}
|
||||
|
||||
public Optional<Endpoint> getEndpoint(int slotId) {
|
||||
return showEndpoints.stream().filter(ep -> ep.id == slotId).findAny();
|
||||
}
|
||||
}
|
||||
|
||||
public HomeManager(FreeboxOsSession session) throws FreeboxException {
|
||||
|
@ -41,7 +41,7 @@ public class NodeConfigurationBuilder {
|
||||
if (node.category() == Category.UNKNOWN) {
|
||||
return Optional.empty();
|
||||
}
|
||||
ThingUID thingUID = new ThingUID(node.category().getThingTypeUID(), bridgeUID, Integer.toString(node.id()));
|
||||
ThingUID thingUID = new ThingUID(node.category().thingTypeUID, bridgeUID, Integer.toString(node.id()));
|
||||
DiscoveryResultBuilder discoveryResultBuilder = DiscoveryResultBuilder.create(thingUID);
|
||||
discoveryResultBuilder.withProperty(ClientConfiguration.ID, node.id()).withLabel(node.label())
|
||||
.withRepresentationProperty(ClientConfiguration.ID).withBridge(bridgeUID);
|
||||
|
@ -14,8 +14,10 @@ package org.openhab.binding.freeboxos.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.Endpoint;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.EndpointState;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.QuantityType;
|
||||
@ -38,7 +40,7 @@ public class AlarmHandler extends HomeNodeHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(HomeManager homeManager, String channelId, EndpointState state) {
|
||||
protected State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint) {
|
||||
String value = state.value();
|
||||
|
||||
if (value == null) {
|
||||
@ -47,7 +49,7 @@ public class AlarmHandler extends HomeNodeHandler {
|
||||
|
||||
return switch (channelId) {
|
||||
case NODE_BATTERY -> DecimalType.valueOf(value);
|
||||
case ALARM_PIN -> StringType.valueOf(value);
|
||||
case ALARM_STATE, ALARM_PIN -> StringType.valueOf(value);
|
||||
case ALARM_SOUND, ALARM_VOLUME -> QuantityType.valueOf(value + " %");
|
||||
case ALARM_TIMEOUT1, ALARM_TIMEOUT2, ALARM_TIMEOUT3 -> QuantityType.valueOf(value + " s");
|
||||
default -> UnDefType.NULL;
|
||||
|
@ -15,6 +15,7 @@ package org.openhab.binding.freeboxos.internal.handler;
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
@ -50,7 +51,7 @@ public class BasicShutterHandler extends HomeNodeHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(HomeManager homeManager, String channelId, EndpointState state) {
|
||||
protected State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint) {
|
||||
String value = state.value();
|
||||
return value != null && channelId.equals(BASIC_SHUTTER_STATE)
|
||||
? state.asBoolean() ? OpenClosedType.CLOSED : OpenClosedType.OPEN
|
||||
|
@ -12,10 +12,12 @@
|
||||
*/
|
||||
package org.openhab.binding.freeboxos.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.TIMESTAMP_POSTFIX;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
@ -53,48 +55,52 @@ public abstract class HomeNodeHandler extends ApiConsumerHandler {
|
||||
HomeNode node = getManager(HomeManager.class).getHomeNode(getClientId());
|
||||
|
||||
// Gets the lowest refresh time or else, we'll keep configuration default
|
||||
node.showEndpoints().stream().filter(ep -> ep.epType() == EpType.SIGNAL).filter(ep -> ep.refresh() != 0)
|
||||
.min(Comparator.comparing(Endpoint::refresh)).map(Endpoint::refresh).ifPresent(rate -> {
|
||||
Configuration thingConfig = editConfiguration();
|
||||
thingConfig.put(ApiConsumerConfiguration.REFRESH_INTERVAL, Integer.toString(rate / 1000));
|
||||
updateConfiguration(thingConfig);
|
||||
});
|
||||
node.getMinRefresh().map(Endpoint::refresh).ifPresent(rate -> {
|
||||
Configuration thingConfig = editConfiguration();
|
||||
thingConfig.put(ApiConsumerConfiguration.REFRESH_INTERVAL, Integer.toString(rate / 1000));
|
||||
updateConfiguration(thingConfig);
|
||||
});
|
||||
|
||||
properties.putAll(node.props());
|
||||
|
||||
getThing().getChannels().forEach(channel -> {
|
||||
Configuration conf = channel.getConfiguration();
|
||||
node.type().endpoints().stream().filter(ep -> ep.name().equals(channel.getUID().getIdWithoutGroup()))
|
||||
String channelId = channel.getUID().getIdWithoutGroup();
|
||||
node.type().endpoints().stream().filter(ep -> ep.name().equals(channelId))
|
||||
.forEach(endPoint -> conf.put(endPoint.epType().asConfId(), endPoint.id()));
|
||||
internalConfigureChannel(channel.getUID().getIdWithoutGroup(), conf, node.type().endpoints());
|
||||
internalConfigureChannel(channelId, conf, node.type().endpoints());
|
||||
});
|
||||
}
|
||||
|
||||
protected void internalConfigureChannel(String channelId, Configuration conf, List<Endpoint> endpoints) {
|
||||
if (channelId.endsWith(TIMESTAMP_POSTFIX)) {
|
||||
String baseEndpoint = channelId.replace(TIMESTAMP_POSTFIX, "");
|
||||
endpoints.stream().filter(ep -> ep.name().equals(baseEndpoint)).forEach(ep -> {
|
||||
conf.put(ep.name(), ep.id());
|
||||
conf.put("signal", ep.id());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalPoll() throws FreeboxException {
|
||||
HomeManager homeManager = getManager(HomeManager.class);
|
||||
getThing().getChannels().stream().filter(channel -> isLinked(channel.getUID())).forEach(channel -> {
|
||||
State result = UnDefType.UNDEF;
|
||||
HomeNode node = homeManager.getHomeNode(getClientId());
|
||||
List<Channel> linkedChannels = getThing().getChannels().stream().filter(channel -> isLinked(channel.getUID()))
|
||||
.toList();
|
||||
|
||||
for (Channel channel : linkedChannels) {
|
||||
State result = null;
|
||||
Integer slotId = getSlotId(channel.getConfiguration(), EpType.SIGNAL.asConfId());
|
||||
if (slotId instanceof Integer) {
|
||||
try {
|
||||
EndpointState state = homeManager.getEndpointsState(getClientId(), slotId);
|
||||
if (state != null) {
|
||||
result = getChannelState(homeManager, channel.getUID().getIdWithoutGroup(), state);
|
||||
} else {
|
||||
result = getChannelState(homeManager, channel.getUID().getIdWithoutGroup());
|
||||
}
|
||||
} catch (FreeboxException e) {
|
||||
logger.warn("Error updating channel: {}", e.getMessage());
|
||||
EndpointState state = homeManager.getEndpointsState(getClientId(), slotId);
|
||||
Optional<Endpoint> endPoint = node.getEndpoint(slotId);
|
||||
if (state != null) {
|
||||
result = getChannelState(channel.getUID().getIdWithoutGroup(), state, endPoint);
|
||||
}
|
||||
} else {
|
||||
result = getChannelState(homeManager, channel.getUID().getIdWithoutGroup());
|
||||
}
|
||||
updateState(channel.getUID(), result);
|
||||
});
|
||||
updateState(channel.getUID(), result != null ? result : UnDefType.UNDEF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -126,9 +132,5 @@ public abstract class HomeNodeHandler extends ApiConsumerHandler {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected State getChannelState(HomeManager homeManager, String channelWG) {
|
||||
return UnDefType.UNDEF;
|
||||
}
|
||||
|
||||
protected abstract State getChannelState(HomeManager homeManager, String channelId, EndpointState state);
|
||||
protected abstract State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint);
|
||||
}
|
||||
|
@ -14,11 +14,19 @@ package org.openhab.binding.freeboxos.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.freeboxos.internal.api.FreeboxException;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.Endpoint;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.EndpointState;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
@ -40,7 +48,15 @@ public class KeyfobHandler extends HomeNodeHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(HomeManager homeManager, String channelId, EndpointState state) {
|
||||
protected State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint) {
|
||||
if (channelId.startsWith(KEYFOB_PUSHED)) {
|
||||
return Objects.requireNonNull(endPoint.map(ep -> ep
|
||||
.getLastChange().map(
|
||||
change -> (State) (KEYFOB_PUSHED.equals(channelId) ? new DecimalType(change.value())
|
||||
: new DateTimeType(ZonedDateTime
|
||||
.ofInstant(Instant.ofEpochSecond(change.timestamp()), ZoneOffset.UTC))))
|
||||
.orElse(UnDefType.UNDEF)).orElse(UnDefType.UNDEF));
|
||||
}
|
||||
String value = state.value();
|
||||
if (value != null) {
|
||||
switch (channelId) {
|
||||
|
@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2024 Contributors to the openHAB project
|
||||
*
|
||||
* See the NOTICE file(s) distributed with this work for additional
|
||||
* information.
|
||||
*
|
||||
* This program and the accompanying materials are made available under the
|
||||
* terms of the Eclipse Public License 2.0 which is available at
|
||||
* http://www.eclipse.org/legal/epl-2.0
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.openhab.binding.freeboxos.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.Endpoint;
|
||||
import org.openhab.binding.freeboxos.internal.api.rest.HomeManager.EndpointState;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
|
||||
/**
|
||||
* The {@link PirHandler} is responsible for handling everything associated to
|
||||
* any Freebox Home PIR motion detection thing type.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class PirHandler extends HomeNodeHandler {
|
||||
|
||||
public PirHandler(Thing thing) {
|
||||
super(thing);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint) {
|
||||
if (PIR_TAMPER_UPDATE.equals(channelId) || PIR_TRIGGER_UPDATE.equals(channelId)) {
|
||||
return Objects.requireNonNull(endPoint.map(ep -> ep.getLastChange()
|
||||
.map(change -> (State) new DateTimeType(
|
||||
ZonedDateTime.ofInstant(Instant.ofEpochSecond(change.timestamp()), ZoneOffset.UTC)))
|
||||
.orElse(UnDefType.UNDEF)).orElse(UnDefType.UNDEF));
|
||||
}
|
||||
|
||||
String value = state.value();
|
||||
|
||||
if (value == null) {
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
|
||||
return switch (channelId) {
|
||||
case NODE_BATTERY -> DecimalType.valueOf(value);
|
||||
case PIR_TAMPER -> state.asBoolean() ? OpenClosedType.OPEN : OpenClosedType.CLOSED;
|
||||
case PIR_TRIGGER -> OnOffType.from(value);
|
||||
default -> UnDefType.NULL;
|
||||
};
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@ package org.openhab.binding.freeboxos.internal.handler;
|
||||
import static org.openhab.binding.freeboxos.internal.FreeboxOsBindingConstants.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.freeboxos.internal.api.FreeboxException;
|
||||
@ -49,7 +50,7 @@ public class ShutterHandler extends HomeNodeHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected State getChannelState(HomeManager homeManager, String channelId, EndpointState state) {
|
||||
protected State getChannelState(String channelId, EndpointState state, Optional<Endpoint> endPoint) {
|
||||
String value = state.value();
|
||||
return value != null && channelId.equals(SHUTTER_POSITION) ? QuantityType.valueOf(value + " %")
|
||||
: UnDefType.NULL;
|
||||
|
@ -46,6 +46,14 @@ thing-type.freeboxos.host.label = Network Device
|
||||
thing-type.freeboxos.host.description = Provides network device reachability
|
||||
thing-type.freeboxos.kfb.label = Freebox Keyfob
|
||||
thing-type.freeboxos.kfb.description = A keyfob configured in your Freebox Server
|
||||
thing-type.freeboxos.kfb.channel.pushed-timestamp.label = Timestamp
|
||||
thing-type.freeboxos.kfb.channel.pushed-timestamp.description = Timestamp of the last action on the keyfob
|
||||
thing-type.freeboxos.pir.label = Freebox Home PIR
|
||||
thing-type.freeboxos.pir.description = A motion Sensor
|
||||
thing-type.freeboxos.pir.channel.tamper-timestamp.label = Tamper Timestamp
|
||||
thing-type.freeboxos.pir.channel.tamper-timestamp.description = Timestamp of the last cover tampered state change
|
||||
thing-type.freeboxos.pir.channel.trigger-timestamp.label = Trigger Timestamp
|
||||
thing-type.freeboxos.pir.channel.trigger-timestamp.description = Timestamp of the last state change
|
||||
thing-type.freeboxos.player.label = Freebox Player
|
||||
thing-type.freeboxos.player.description = The player is the device connected to your TV
|
||||
thing-type.freeboxos.repeater.label = Wifi Repeater
|
||||
@ -209,6 +217,13 @@ channel-type.freeboxos.afp-file-status.description = Status of Mac OS File Shari
|
||||
channel-type.freeboxos.airmedia-status.label = Air Media Enabled
|
||||
channel-type.freeboxos.airmedia-status.description = Indicates whether Air Media is enabled
|
||||
channel-type.freeboxos.alarm-pin.label = PIN Code
|
||||
channel-type.freeboxos.alarm-state.label = Alarm State
|
||||
channel-type.freeboxos.alarm-state.description = Current state of the alarm system
|
||||
channel-type.freeboxos.alarm-state.state.option.idle = Idle
|
||||
channel-type.freeboxos.alarm-state.state.option.alarm1_arming = Arming (Absent Mode)
|
||||
channel-type.freeboxos.alarm-state.state.option.alarm1_armed = Armed (Absent Mode)
|
||||
channel-type.freeboxos.alarm-state.state.option.alarm2_arming = Arming (Night Mode)
|
||||
channel-type.freeboxos.alarm-state.state.option.alarm2_armed = Armed (Night Mode)
|
||||
channel-type.freeboxos.alarm-timeout.label = Alarm Duration
|
||||
channel-type.freeboxos.alarm-volume.label = Alarm Volume
|
||||
channel-type.freeboxos.alternate-ring.label = Alternating Ring
|
||||
@ -282,6 +297,11 @@ channel-type.freeboxos.key-code.state.option.ok = OK
|
||||
channel-type.freeboxos.key-code.state.option.home = Home
|
||||
channel-type.freeboxos.keyfob-enable.label = Keyfob Enabled
|
||||
channel-type.freeboxos.keyfob-enable.description = Activates / deactivates the keyfob
|
||||
channel-type.freeboxos.kfb-pushed.label = Key Code Pushed
|
||||
channel-type.freeboxos.kfb-pushed.description = Last key pushed on the remote
|
||||
channel-type.freeboxos.kfb-pushed.state.option.1 = Arm Absent Mode
|
||||
channel-type.freeboxos.kfb-pushed.state.option.2 = Disarm
|
||||
channel-type.freeboxos.kfb-pushed.state.option.3 = Arm Night Mode
|
||||
channel-type.freeboxos.lcd-brightness.label = Screen Brightness
|
||||
channel-type.freeboxos.lcd-brightness.description = Brightness level of the screen in percent
|
||||
channel-type.freeboxos.lcd-forced.label = Forced Orientation
|
||||
@ -323,6 +343,8 @@ channel-type.freeboxos.package.description = Name of the package currently activ
|
||||
channel-type.freeboxos.phone-event.label = Phone Event
|
||||
channel-type.freeboxos.phone-event.description = Triggers when an event related to the phone has been detected
|
||||
channel-type.freeboxos.phone-number.label = Phone Number
|
||||
channel-type.freeboxos.pir-tamper.label = Cover Tamper
|
||||
channel-type.freeboxos.pir-trigger.label = Détection
|
||||
channel-type.freeboxos.player-status.label = Player Status
|
||||
channel-type.freeboxos.player-status.description = Status of the Freebox TV player
|
||||
channel-type.freeboxos.reachable.label = Reachable
|
||||
|
@ -496,6 +496,46 @@
|
||||
<state readOnly="true" pattern="%.2f dBm"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pir-trigger">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Détection</label>
|
||||
<category>oh:freeboxos:mouvement</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="pir-tamper">
|
||||
<item-type>Contact</item-type>
|
||||
<label>Cover Tamper</label>
|
||||
<category>oh:freeboxos:warning</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="kfb-pushed">
|
||||
<item-type>Number</item-type>
|
||||
<label>Key Code Pushed</label>
|
||||
<description>Last key pushed on the remote</description>
|
||||
<state readOnly="true" pattern="%d">
|
||||
<options>
|
||||
<option value="1">Arm Absent Mode</option>
|
||||
<option value="2">Disarm</option>
|
||||
<option value="3">Arm Night Mode</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="alarm-state">
|
||||
<item-type>String</item-type>
|
||||
<label>Alarm State</label>
|
||||
<description>Current state of the alarm system</description>
|
||||
<state readOnly="true" pattern="%s">
|
||||
<options>
|
||||
<option value="idle">Idle</option>
|
||||
<option value="alarm1_arming">Arming (Absent Mode)</option>
|
||||
<option value="alarm1_armed">Armed (Absent Mode)</option>
|
||||
<option value="alarm2_arming">Arming (Night Mode)</option>
|
||||
<option value="alarm2_armed">Armed (Night Mode)</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xdsl-ready">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Ready</label>
|
||||
|
@ -21,6 +21,33 @@
|
||||
<config-description-ref uri="thing-type:freeboxos:home-node"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="pir">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Freebox Home PIR</label>
|
||||
<description>A motion Sensor</description>
|
||||
|
||||
<channels>
|
||||
<channel id="trigger" typeId="pir-trigger"/>
|
||||
<channel id="trigger-timestamp" typeId="timestamp">
|
||||
<label>Trigger Timestamp</label>
|
||||
<description>Timestamp of the last state change</description>
|
||||
</channel>
|
||||
<channel id="tamper" typeId="pir-tamper"/>
|
||||
<channel id="tamper-timestamp" typeId="timestamp">
|
||||
<label>Tamper Timestamp</label>
|
||||
<description>Timestamp of the last cover tampered state change</description>
|
||||
</channel>
|
||||
<channel id="battery" typeId="system.battery-level"/>
|
||||
</channels>
|
||||
|
||||
<representation-property>id</representation-property>
|
||||
|
||||
<config-description-ref uri="thing-type:freeboxos:home-node"/>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="alarm">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="api"/>
|
||||
@ -30,6 +57,7 @@
|
||||
<description>The Alarm system configured in your Freebox Server</description>
|
||||
|
||||
<channels>
|
||||
<channel id="state" typeId="alarm-state"/>
|
||||
<channel id="pin" typeId="alarm-pin"/>
|
||||
<channel id="sound" typeId="alarm-volume">
|
||||
<label>Bips Volume</label>
|
||||
@ -64,6 +92,11 @@
|
||||
<description>A keyfob configured in your Freebox Server</description>
|
||||
|
||||
<channels>
|
||||
<channel id="pushed" typeId="kfb-pushed"/>
|
||||
<channel id="pushed-timestamp" typeId="timestamp">
|
||||
<label>Timestamp</label>
|
||||
<description>Timestamp of the last action on the keyfob</description>
|
||||
</channel>
|
||||
<channel id="enable" typeId="keyfob-enable"/>
|
||||
<channel id="battery" typeId="system.battery-level"/>
|
||||
</channels>
|
||||
|
Loading…
Reference in New Issue
Block a user