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());
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);
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;
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;
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;
private final NetworkAddressService networkAddressService;
private final AudioHTTPServer audioHTTPServer;
- private final HttpClient httpClient;
private final ApiHandler apiHandler;
private String callbackURL = "";
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");
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;
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;
*/
@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;
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) -> {
.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,
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;
}
}
- 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 {
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('_', '-'));
}
}
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 {
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);
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;
}
@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) {
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;
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;
}
@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
*/
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;
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
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);
}
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;
}
@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) {
--- /dev/null
+/**
+ * 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;
+ };
+ }
+}
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;
}
@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;
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
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
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
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
<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>
<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"/>
<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>
<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>