added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.freebox-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.4.0">
|
||||
<repository>mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features</repository>
|
||||
|
||||
<feature name="openhab-binding-freebox" description="Freebox Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<feature>openhab-transport-mdns</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.freebox/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,176 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal;
|
||||
|
||||
import static org.openhab.core.audio.AudioFormat.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxAirPlayDeviceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.handler.FreeboxThingHandler;
|
||||
import org.openhab.core.audio.AudioFormat;
|
||||
import org.openhab.core.audio.AudioHTTPServer;
|
||||
import org.openhab.core.audio.AudioSink;
|
||||
import org.openhab.core.audio.AudioStream;
|
||||
import org.openhab.core.audio.FixedLengthAudioStream;
|
||||
import org.openhab.core.audio.URLAudioStream;
|
||||
import org.openhab.core.audio.UnsupportedAudioFormatException;
|
||||
import org.openhab.core.audio.UnsupportedAudioStreamException;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.util.ThingHandlerHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This makes an AirPlay device to serve as an {@link AudioSink}-
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution for AudioSink and notifications
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FreeboxAirPlayAudioSink implements AudioSink {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxAirPlayAudioSink.class);
|
||||
|
||||
private static final AudioFormat MP3_96 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 96000, null);
|
||||
private static final AudioFormat MP3_112 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 112000, null);
|
||||
private static final AudioFormat MP3_128 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 128000, null);
|
||||
private static final AudioFormat MP3_160 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 160000, null);
|
||||
private static final AudioFormat MP3_192 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 192000, null);
|
||||
private static final AudioFormat MP3_224 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 224000, null);
|
||||
private static final AudioFormat MP3_256 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 256000, null);
|
||||
private static final AudioFormat MP3_320 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 320000, null);
|
||||
|
||||
private static final Set<AudioFormat> SUPPORTED_FORMATS = new HashSet<>();
|
||||
private static final HashSet<Class<? extends AudioStream>> SUPPORTED_STREAMS = new HashSet<>();
|
||||
private AudioHTTPServer audioHTTPServer;
|
||||
private FreeboxThingHandler handler;
|
||||
private @Nullable String callbackUrl;
|
||||
|
||||
static {
|
||||
SUPPORTED_STREAMS.add(AudioStream.class);
|
||||
}
|
||||
|
||||
public FreeboxAirPlayAudioSink(FreeboxThingHandler handler, AudioHTTPServer audioHTTPServer,
|
||||
@Nullable String callbackUrl) {
|
||||
this.handler = handler;
|
||||
this.audioHTTPServer = audioHTTPServer;
|
||||
this.callbackUrl = callbackUrl;
|
||||
Boolean acceptLowBitrate = (Boolean) handler.getThing().getConfiguration()
|
||||
.get(FreeboxAirPlayDeviceConfiguration.ACCEPT_ALL_MP3);
|
||||
SUPPORTED_FORMATS.add(WAV);
|
||||
if (acceptLowBitrate) {
|
||||
SUPPORTED_FORMATS.add(MP3);
|
||||
} else {
|
||||
// Only accept MP3 bitrates >= 96 kbps
|
||||
SUPPORTED_FORMATS.add(MP3_96);
|
||||
SUPPORTED_FORMATS.add(MP3_112);
|
||||
SUPPORTED_FORMATS.add(MP3_128);
|
||||
SUPPORTED_FORMATS.add(MP3_160);
|
||||
SUPPORTED_FORMATS.add(MP3_192);
|
||||
SUPPORTED_FORMATS.add(MP3_224);
|
||||
SUPPORTED_FORMATS.add(MP3_256);
|
||||
SUPPORTED_FORMATS.add(MP3_320);
|
||||
}
|
||||
SUPPORTED_FORMATS.add(OGG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return handler.getThing().getUID().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getLabel(@Nullable Locale locale) {
|
||||
return handler.getThing().getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(@Nullable AudioStream audioStream)
|
||||
throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
|
||||
if (!ThingHandlerHelper.isHandlerInitialized(handler)
|
||||
|| ((handler.getThing().getStatus() == ThingStatus.OFFLINE)
|
||||
&& ((handler.getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE)
|
||||
|| (handler.getThing().getStatusInfo()
|
||||
.getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (audioStream == null) {
|
||||
try {
|
||||
handler.stopMedia();
|
||||
} catch (FreeboxException e) {
|
||||
logger.warn("Exception while stopping audio stream playback: {}", e.getMessage());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
String url = null;
|
||||
if (audioStream instanceof URLAudioStream) {
|
||||
// it is an external URL, we can access it directly
|
||||
URLAudioStream urlAudioStream = (URLAudioStream) audioStream;
|
||||
url = urlAudioStream.getURL();
|
||||
} else {
|
||||
if (callbackUrl != null) {
|
||||
// we serve it on our own HTTP server
|
||||
String relativeUrl;
|
||||
if (audioStream instanceof FixedLengthAudioStream) {
|
||||
relativeUrl = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, 20);
|
||||
} else {
|
||||
relativeUrl = audioHTTPServer.serve(audioStream);
|
||||
}
|
||||
url = callbackUrl + relativeUrl;
|
||||
} else {
|
||||
logger.warn("We do not have any callback url, so AirPlay device cannot play the audio stream!");
|
||||
}
|
||||
}
|
||||
try {
|
||||
audioStream.close();
|
||||
} catch (IOException e) {
|
||||
logger.debug("Exception while closing audioStream", e);
|
||||
}
|
||||
try {
|
||||
logger.debug("AirPlay audio sink: process url {}", url);
|
||||
handler.playMedia(url);
|
||||
} catch (FreeboxException e) {
|
||||
logger.warn("Audio stream playback failed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<AudioFormat> getSupportedFormats() {
|
||||
return SUPPORTED_FORMATS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Class<? extends AudioStream>> getSupportedStreams() {
|
||||
return SUPPORTED_STREAMS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PercentType getVolume() {
|
||||
throw new UnsupportedOperationException("Volume can not be determined");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVolume(PercentType volume) {
|
||||
throw new UnsupportedOperationException("Volume can not be set");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxBinding} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FreeboxBindingConstants {
|
||||
|
||||
public static final String BINDING_ID = "freebox";
|
||||
|
||||
// List of all Bridge Type UIDs
|
||||
public static final ThingTypeUID FREEBOX_BRIDGE_TYPE_SERVER = new ThingTypeUID(BINDING_ID, "server");
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID FREEBOX_THING_TYPE_PHONE = new ThingTypeUID(BINDING_ID, "phone");
|
||||
public static final ThingTypeUID FREEBOX_THING_TYPE_NET_DEVICE = new ThingTypeUID(BINDING_ID, "net_device");
|
||||
public static final ThingTypeUID FREEBOX_THING_TYPE_NET_INTERFACE = new ThingTypeUID(BINDING_ID, "net_interface");
|
||||
public static final ThingTypeUID FREEBOX_THING_TYPE_AIRPLAY = new ThingTypeUID(BINDING_ID, "airplay");
|
||||
|
||||
// All supported Bridge types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_BRIDGE_TYPES_UIDS = Collections
|
||||
.singleton(FREEBOX_BRIDGE_TYPE_SERVER);
|
||||
|
||||
// All supported Thing types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(FREEBOX_THING_TYPE_PHONE, FREEBOX_THING_TYPE_NET_DEVICE,
|
||||
FREEBOX_THING_TYPE_NET_INTERFACE, FREEBOX_THING_TYPE_AIRPLAY).collect(Collectors.toSet()));
|
||||
|
||||
// List of properties
|
||||
public static final String API_BASE_URL = "apiBaseUrl";
|
||||
public static final String API_VERSION = "apiVersion";
|
||||
|
||||
// List of all Group Channel ids
|
||||
public static final String STATE = "state";
|
||||
public static final String ANY = "any";
|
||||
public static final String ACCEPTED = "accepted";
|
||||
public static final String MISSED = "missed";
|
||||
public static final String OUTGOING = "outgoing";
|
||||
|
||||
// List of all Channel ids
|
||||
public static final String FWVERSION = "fwversion";
|
||||
public static final String UPTIME = "uptime";
|
||||
public static final String RESTARTED = "restarted";
|
||||
public static final String TEMPCPUM = "tempcpum";
|
||||
public static final String TEMPCPUB = "tempcpub";
|
||||
public static final String TEMPSWITCH = "tempswitch";
|
||||
public static final String FANSPEED = "fanspeed";
|
||||
public static final String LCDBRIGHTNESS = "lcd_brightness";
|
||||
public static final String LCDORIENTATION = "lcd_orientation";
|
||||
public static final String LCDFORCED = "lcd_forced";
|
||||
public static final String WIFISTATUS = "wifi_status";
|
||||
public static final String XDSLSTATUS = "xdsl_status";
|
||||
public static final String FTTHSTATUS = "ftth_status";
|
||||
public static final String LINESTATUS = "line_status";
|
||||
public static final String IPV4 = "ipv4";
|
||||
public static final String RATEUP = "rate_up";
|
||||
public static final String RATEDOWN = "rate_down";
|
||||
public static final String BYTESUP = "bytes_up";
|
||||
public static final String BYTESDOWN = "bytes_down";
|
||||
public static final String ONHOOK = "onhook";
|
||||
public static final String RINGING = "ringing";
|
||||
public static final String CALLNUMBER = "call_number";
|
||||
public static final String CALLDURATION = "call_duration";
|
||||
public static final String CALLTIMESTAMP = "call_timestamp";
|
||||
public static final String CALLSTATUS = "call_status";
|
||||
public static final String CALLNAME = "call_name";
|
||||
public static final String REBOOT = "reboot";
|
||||
public static final String FTPSTATUS = "ftp_status";
|
||||
public static final String AIRMEDIASTATUS = "airmedia_status";
|
||||
public static final String UPNPAVSTATUS = "upnpav_status";
|
||||
public static final String SAMBAFILESTATUS = "sambafileshare_status";
|
||||
public static final String SAMBAPRINTERSTATUS = "sambaprintershare_status";
|
||||
public static final String REACHABLE = "reachable";
|
||||
public static final String PLAYURL = "playurl";
|
||||
public static final String STOP = "stop";
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiver;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHost;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxDataListener} is notified by the bridge thing handler
|
||||
* with updated data from the Freebox server.
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
* @author Laurent Garnier - add discovery configuration
|
||||
* @author Laurent Garnier - use new internal classes
|
||||
*/
|
||||
public interface FreeboxDataListener {
|
||||
|
||||
/**
|
||||
* Update the discovery configuration.
|
||||
*
|
||||
* @param configProperties the configuration
|
||||
*/
|
||||
public void applyConfig(Map<String, Object> configProperties);
|
||||
|
||||
/**
|
||||
* This method is called just after the bridge thing handler fetched new data
|
||||
* from the Freebox server.
|
||||
*
|
||||
* @param bridge the Freebox server bridge.
|
||||
* @param lanHosts the LAN data received from the Freebox server.
|
||||
* @param airPlayDevices the list of AirPlay devices received from the Freebox server.
|
||||
*/
|
||||
public void onDataFetched(ThingUID bridge, List<FreeboxLanHost> lanHosts,
|
||||
List<FreeboxAirMediaReceiver> airPlayDevices);
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.freebox.internal.discovery.FreeboxDiscoveryService;
|
||||
import org.openhab.binding.freebox.internal.handler.FreeboxHandler;
|
||||
import org.openhab.binding.freebox.internal.handler.FreeboxThingHandler;
|
||||
import org.openhab.core.audio.AudioHTTPServer;
|
||||
import org.openhab.core.audio.AudioSink;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.net.HttpServiceUtil;
|
||||
import org.openhab.core.net.NetworkAddressService;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
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.Reference;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
* @author Laurent Garnier - several thing types and handlers + discovery service
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(service = ThingHandlerFactory.class, configurationPid = "binding.freebox")
|
||||
public class FreeboxHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Stream
|
||||
.concat(FreeboxBindingConstants.SUPPORTED_BRIDGE_TYPES_UIDS.stream(),
|
||||
FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.stream())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxHandlerFactory.class);
|
||||
|
||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
private final Map<ThingUID, ServiceRegistration<AudioSink>> audioSinkRegistrations = new ConcurrentHashMap<>();
|
||||
|
||||
private final AudioHTTPServer audioHTTPServer;
|
||||
private final NetworkAddressService networkAddressService;
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
// url (scheme+server+port) to use for playing notification sounds
|
||||
private @Nullable String callbackUrl;
|
||||
|
||||
@Activate
|
||||
public FreeboxHandlerFactory(final @Reference AudioHTTPServer audioHTTPServer,
|
||||
final @Reference NetworkAddressService networkAddressService,
|
||||
final @Reference TimeZoneProvider timeZoneProvider) {
|
||||
this.audioHTTPServer = audioHTTPServer;
|
||||
this.networkAddressService = networkAddressService;
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate(ComponentContext componentContext) {
|
||||
super.activate(componentContext);
|
||||
Dictionary<String, Object> properties = componentContext.getProperties();
|
||||
callbackUrl = (String) properties.get("callbackUrl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration,
|
||||
@Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) {
|
||||
if (thingTypeUID.equals(FreeboxBindingConstants.FREEBOX_BRIDGE_TYPE_SERVER)) {
|
||||
return super.createThing(thingTypeUID, configuration, thingUID, null);
|
||||
} else if (FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
ThingUID newThingUID;
|
||||
if (bridgeUID != null && thingUID != null) {
|
||||
newThingUID = new ThingUID(thingTypeUID, bridgeUID, thingUID.getId());
|
||||
} else {
|
||||
newThingUID = thingUID;
|
||||
}
|
||||
return super.createThing(thingTypeUID, configuration, newThingUID, bridgeUID);
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
"The thing type " + thingTypeUID + " is not supported by the Freebox binding.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (thingTypeUID.equals(FreeboxBindingConstants.FREEBOX_BRIDGE_TYPE_SERVER)) {
|
||||
FreeboxHandler handler = new FreeboxHandler((Bridge) thing);
|
||||
registerDiscoveryService(handler);
|
||||
return handler;
|
||||
} else if (FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
|
||||
FreeboxThingHandler handler = new FreeboxThingHandler(thing, timeZoneProvider);
|
||||
if (FreeboxBindingConstants.FREEBOX_THING_TYPE_AIRPLAY.equals(thingTypeUID)) {
|
||||
registerAudioSink(handler);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof FreeboxHandler) {
|
||||
unregisterDiscoveryService(thingHandler.getThing());
|
||||
} else if (thingHandler instanceof FreeboxThingHandler) {
|
||||
unregisterAudioSink(thingHandler.getThing());
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void registerDiscoveryService(FreeboxHandler bridgeHandler) {
|
||||
FreeboxDiscoveryService discoveryService = new FreeboxDiscoveryService(bridgeHandler);
|
||||
discoveryService.activate(null);
|
||||
discoveryServiceRegs.put(bridgeHandler.getThing().getUID(),
|
||||
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
|
||||
}
|
||||
|
||||
private synchronized void unregisterDiscoveryService(Thing thing) {
|
||||
ServiceRegistration<?> serviceReg = discoveryServiceRegs.remove(thing.getUID());
|
||||
if (serviceReg != null) {
|
||||
// remove discovery service, if bridge handler is removed
|
||||
FreeboxDiscoveryService service = (FreeboxDiscoveryService) bundleContext
|
||||
.getService(serviceReg.getReference());
|
||||
serviceReg.unregister();
|
||||
if (service != null) {
|
||||
service.deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void registerAudioSink(FreeboxThingHandler thingHandler) {
|
||||
String callbackUrl = createCallbackUrl();
|
||||
FreeboxAirPlayAudioSink audioSink = new FreeboxAirPlayAudioSink(thingHandler, audioHTTPServer, callbackUrl);
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceRegistration<AudioSink> reg = (ServiceRegistration<AudioSink>) bundleContext
|
||||
.registerService(AudioSink.class.getName(), audioSink, new Hashtable<>());
|
||||
audioSinkRegistrations.put(thingHandler.getThing().getUID(), reg);
|
||||
}
|
||||
|
||||
private synchronized void unregisterAudioSink(Thing thing) {
|
||||
ServiceRegistration<AudioSink> reg = audioSinkRegistrations.remove(thing.getUID());
|
||||
if (reg != null) {
|
||||
reg.unregister();
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable String createCallbackUrl() {
|
||||
if (callbackUrl != null) {
|
||||
return callbackUrl;
|
||||
} else {
|
||||
String ipAddress = networkAddressService.getPrimaryIpv4HostAddress();
|
||||
if (ipAddress == null) {
|
||||
logger.warn("No network interface could be found.");
|
||||
return null;
|
||||
}
|
||||
|
||||
// we do not use SSL as it can cause certificate validation issues.
|
||||
int port = HttpServiceUtil.getHttpServicePort(bundleContext);
|
||||
if (port == -1) {
|
||||
logger.warn("Cannot find port of the http service.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return "http://" + ipAddress + ":" + port;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,498 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiver;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiverRequest;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiversResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAuthorizationStatus;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAuthorizationStatusResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAuthorizeRequest;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAuthorizeResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAuthorizeResult;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxCallEntry;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxCallEntryResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxConnectionStatus;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxConnectionStatusResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxDiscoveryResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxEmptyResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxFtpConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxFtpConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxFtthStatusResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHost;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHostsResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanInterface;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanInterfacesResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLcdConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLcdConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLoginResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxOpenSessionRequest;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxOpenSessionResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxPhoneStatus;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxPhoneStatusResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSambaConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSambaConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSystemConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSystemConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxUPnPAVConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxUPnPAVConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxWifiGlobalConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxWifiGlobalConfigResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxXdslStatusResponse;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.util.HexUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.FieldNamingPolicy;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxApiManager} is responsible for the communication with the Freebox.
|
||||
* It implements the different HTTP API calls provided by the Freebox
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxApiManager {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxApiManager.class);
|
||||
|
||||
private static final int HTTP_CALL_DEFAULT_TIMEOUT_MS = (int) TimeUnit.SECONDS.toMillis(10);
|
||||
private static final String AUTH_HEADER = "X-Fbx-App-Auth";
|
||||
private static final String HTTP_CALL_CONTENT_TYPE = "application/json; charset=utf-8";
|
||||
|
||||
private String appId;
|
||||
private String appName;
|
||||
private String appVersion;
|
||||
private String deviceName;
|
||||
private String baseAddress;
|
||||
private String appToken;
|
||||
private String sessionToken;
|
||||
private Gson gson;
|
||||
|
||||
public FreeboxApiManager(String appId, String appName, String appVersion, String deviceName) {
|
||||
this.appId = appId;
|
||||
this.appName = appName;
|
||||
this.appVersion = appVersion;
|
||||
this.deviceName = deviceName;
|
||||
this.gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
|
||||
}
|
||||
|
||||
public FreeboxDiscoveryResponse checkApi(String fqdn, boolean secureHttp) {
|
||||
String url = String.format("%s://%s/api_version", secureHttp ? "https" : "http", fqdn);
|
||||
try {
|
||||
String jsonResponse = HttpUtil.executeUrl("GET", url, HTTP_CALL_DEFAULT_TIMEOUT_MS);
|
||||
return gson.fromJson(jsonResponse, FreeboxDiscoveryResponse.class);
|
||||
} catch (IOException | JsonSyntaxException e) {
|
||||
logger.debug("checkApi with {} failed: {}", url, e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean authorize(boolean useHttps, String fqdn, String apiBaseUrl, String apiVersion, String appToken) {
|
||||
String[] versionSplit = apiVersion.split("\\.");
|
||||
String majorVersion = "5";
|
||||
if (versionSplit.length > 0) {
|
||||
majorVersion = versionSplit[0];
|
||||
}
|
||||
this.baseAddress = (useHttps ? "https://" : "http://") + fqdn + apiBaseUrl + "v" + majorVersion + "/";
|
||||
|
||||
boolean granted = false;
|
||||
try {
|
||||
String token = appToken;
|
||||
if (token == null || token.isEmpty()) {
|
||||
FreeboxAuthorizeRequest request = new FreeboxAuthorizeRequest(appId, appName, appVersion, deviceName);
|
||||
FreeboxAuthorizeResult response = executePostUrl("login/authorize/", gson.toJson(request),
|
||||
FreeboxAuthorizeResponse.class, false, false, true);
|
||||
token = response.getAppToken();
|
||||
int trackId = response.getTrackId();
|
||||
FreeboxAuthorizationStatus result;
|
||||
do {
|
||||
Thread.sleep(2000);
|
||||
result = executeGetUrl("login/authorize/" + trackId, FreeboxAuthorizationStatusResponse.class,
|
||||
false);
|
||||
} while (result.isStatusPending());
|
||||
granted = result.isStatusGranted();
|
||||
} else {
|
||||
granted = true;
|
||||
}
|
||||
if (!granted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.appToken = token;
|
||||
openSession();
|
||||
return true;
|
||||
} catch (FreeboxException | InterruptedException e) {
|
||||
logger.debug("Error while opening a session", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void openSession() throws FreeboxException {
|
||||
if (appToken == null) {
|
||||
throw new FreeboxException("No app token to open a new session");
|
||||
}
|
||||
sessionToken = null;
|
||||
String challenge = executeGetUrl("login/", FreeboxLoginResponse.class, false).getChallenge();
|
||||
FreeboxOpenSessionRequest request = new FreeboxOpenSessionRequest(appId, hmacSha1(appToken, challenge));
|
||||
sessionToken = executePostUrl("login/session/", gson.toJson(request), FreeboxOpenSessionResponse.class, false,
|
||||
false, true).getSessionToken();
|
||||
}
|
||||
|
||||
public synchronized void closeSession() {
|
||||
if (sessionToken != null) {
|
||||
try {
|
||||
executePostUrl("login/logout/", null, FreeboxEmptyResponse.class, false);
|
||||
} catch (FreeboxException e) {
|
||||
}
|
||||
sessionToken = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAppToken() {
|
||||
return appToken;
|
||||
}
|
||||
|
||||
public synchronized String getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
public FreeboxConnectionStatus getConnectionStatus() throws FreeboxException {
|
||||
return executeGetUrl("connection/", FreeboxConnectionStatusResponse.class);
|
||||
}
|
||||
|
||||
public String getxDslStatus() throws FreeboxException {
|
||||
return executeGetUrl("connection/xdsl/", FreeboxXdslStatusResponse.class).getStatus();
|
||||
}
|
||||
|
||||
public boolean getFtthPresent() throws FreeboxException {
|
||||
return executeGetUrl("connection/ftth/", FreeboxFtthStatusResponse.class).getSfpPresent();
|
||||
}
|
||||
|
||||
public boolean isWifiEnabled() throws FreeboxException {
|
||||
return executeGetUrl("wifi/config/", FreeboxWifiGlobalConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean enableWifi(boolean enable) throws FreeboxException {
|
||||
FreeboxWifiGlobalConfig config = new FreeboxWifiGlobalConfig();
|
||||
config.setEnabled(enable);
|
||||
return executePutUrl("wifi/config/", gson.toJson(config), FreeboxWifiGlobalConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean isFtpEnabled() throws FreeboxException {
|
||||
return executeGetUrl("ftp/config/", FreeboxFtpConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean enableFtp(boolean enable) throws FreeboxException {
|
||||
FreeboxFtpConfig config = new FreeboxFtpConfig();
|
||||
config.setEnabled(enable);
|
||||
return executePutUrl("ftp/config/", gson.toJson(config), FreeboxFtpConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean isAirMediaEnabled() throws FreeboxException {
|
||||
return executeGetUrl("airmedia/config/", FreeboxAirMediaConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean enableAirMedia(boolean enable) throws FreeboxException {
|
||||
FreeboxAirMediaConfig config = new FreeboxAirMediaConfig();
|
||||
config.setEnabled(enable);
|
||||
return executePutUrl("airmedia/config/", gson.toJson(config), FreeboxAirMediaConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean isUPnPAVEnabled() throws FreeboxException {
|
||||
return executeGetUrl("upnpav/config/", FreeboxUPnPAVConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public boolean enableUPnPAV(boolean enable) throws FreeboxException {
|
||||
FreeboxUPnPAVConfig config = new FreeboxUPnPAVConfig();
|
||||
config.setEnabled(enable);
|
||||
return executePutUrl("upnpav/config/", gson.toJson(config), FreeboxUPnPAVConfigResponse.class).isEnabled();
|
||||
}
|
||||
|
||||
public FreeboxSambaConfig getSambaConfig() throws FreeboxException {
|
||||
return executeGetUrl("netshare/samba/", FreeboxSambaConfigResponse.class);
|
||||
}
|
||||
|
||||
public boolean enableSambaFileShare(boolean enable) throws FreeboxException {
|
||||
FreeboxSambaConfig config = new FreeboxSambaConfig();
|
||||
config.setFileShareEnabled(enable);
|
||||
return executePutUrl("netshare/samba/", gson.toJson(config), FreeboxSambaConfigResponse.class)
|
||||
.isFileShareEnabled();
|
||||
}
|
||||
|
||||
public boolean enableSambaPrintShare(boolean enable) throws FreeboxException {
|
||||
FreeboxSambaConfig config = new FreeboxSambaConfig();
|
||||
config.setPrintShareEnabled(enable);
|
||||
return executePutUrl("netshare/samba/", gson.toJson(config), FreeboxSambaConfigResponse.class)
|
||||
.isPrintShareEnabled();
|
||||
}
|
||||
|
||||
public FreeboxLcdConfig getLcdConfig() throws FreeboxException {
|
||||
return executeGetUrl("lcd/config/", FreeboxLcdConfigResponse.class);
|
||||
}
|
||||
|
||||
public int setLcdBrightness(int brightness) throws FreeboxException {
|
||||
FreeboxLcdConfig config = getLcdConfig();
|
||||
int newValue = Math.min(100, brightness);
|
||||
newValue = Math.max(newValue, 0);
|
||||
config.setBrightness(newValue);
|
||||
return executePutUrl("lcd/config/", gson.toJson(config), FreeboxLcdConfigResponse.class).getBrightness();
|
||||
}
|
||||
|
||||
public int increaseLcdBrightness() throws FreeboxException {
|
||||
FreeboxLcdConfig config = getLcdConfig();
|
||||
config.setBrightness(Math.min(100, config.getBrightness() + 1));
|
||||
return executePutUrl("lcd/config/", gson.toJson(config), FreeboxLcdConfigResponse.class).getBrightness();
|
||||
}
|
||||
|
||||
public int decreaseLcdBrightness() throws FreeboxException {
|
||||
FreeboxLcdConfig config = getLcdConfig();
|
||||
config.setBrightness(Math.max(0, config.getBrightness() - 1));
|
||||
return executePutUrl("lcd/config/", gson.toJson(config), FreeboxLcdConfigResponse.class).getBrightness();
|
||||
}
|
||||
|
||||
public FreeboxLcdConfig setLcdOrientation(int orientation) throws FreeboxException {
|
||||
FreeboxLcdConfig config = getLcdConfig();
|
||||
int newValue = Math.min(360, orientation);
|
||||
newValue = Math.max(newValue, 0);
|
||||
config.setOrientation(newValue);
|
||||
config.setOrientationForced(true);
|
||||
return executePutUrl("lcd/config/", gson.toJson(config), FreeboxLcdConfigResponse.class);
|
||||
}
|
||||
|
||||
public boolean setLcdOrientationForced(boolean forced) throws FreeboxException {
|
||||
FreeboxLcdConfig config = getLcdConfig();
|
||||
config.setOrientationForced(forced);
|
||||
return executePutUrl("lcd/config/", gson.toJson(config), FreeboxLcdConfigResponse.class).isOrientationForced();
|
||||
}
|
||||
|
||||
public FreeboxSystemConfig getSystemConfig() throws FreeboxException {
|
||||
return executeGetUrl("system/", FreeboxSystemConfigResponse.class);
|
||||
}
|
||||
|
||||
public boolean isInLanBridgeMode() throws FreeboxException {
|
||||
return executeGetUrl("lan/config/", FreeboxLanConfigResponse.class).isInBridgeMode();
|
||||
}
|
||||
|
||||
public List<FreeboxLanHost> getLanHosts() throws FreeboxException {
|
||||
List<FreeboxLanHost> hosts = new ArrayList<>();
|
||||
List<FreeboxLanInterface> interfaces = executeGetUrl("lan/browser/interfaces/",
|
||||
FreeboxLanInterfacesResponse.class);
|
||||
if (interfaces != null) {
|
||||
for (FreeboxLanInterface lanInterface : interfaces) {
|
||||
if (lanInterface.getHostCount() > 0) {
|
||||
List<FreeboxLanHost> lanHosts = getLanHostsFromInterface(lanInterface.getName());
|
||||
if (lanHosts != null) {
|
||||
hosts.addAll(lanHosts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hosts;
|
||||
}
|
||||
|
||||
private List<FreeboxLanHost> getLanHostsFromInterface(String lanInterface) throws FreeboxException {
|
||||
return executeGetUrl("lan/browser/" + encodeUrl(lanInterface) + "/", FreeboxLanHostsResponse.class);
|
||||
}
|
||||
|
||||
public FreeboxPhoneStatus getPhoneStatus() throws FreeboxException {
|
||||
// This API is undocumented but working
|
||||
// It is extracted from the freeboxos-java library
|
||||
// https://github.com/MatMaul/freeboxos-java/blob/master/src/org/matmaul/freeboxos/phone/PhoneManager.java#L17
|
||||
return executeGetUrl("phone/?_dc=1415032391207", FreeboxPhoneStatusResponse.class).get(0);
|
||||
}
|
||||
|
||||
public List<FreeboxCallEntry> getCallEntries() throws FreeboxException {
|
||||
return executeGetUrl("call/log/", FreeboxCallEntryResponse.class);
|
||||
}
|
||||
|
||||
public List<FreeboxAirMediaReceiver> getAirMediaReceivers() throws FreeboxException {
|
||||
return executeGetUrl("airmedia/receivers/", FreeboxAirMediaReceiversResponse.class, true, true, false);
|
||||
}
|
||||
|
||||
public void playMedia(String url, String airPlayName, String airPlayPassword) throws FreeboxException {
|
||||
FreeboxAirMediaReceiverRequest request = new FreeboxAirMediaReceiverRequest();
|
||||
request.setStartAction();
|
||||
request.setVideoMediaType();
|
||||
if (airPlayPassword != null && !airPlayPassword.isEmpty()) {
|
||||
request.setPassword(airPlayPassword);
|
||||
}
|
||||
request.setMedia(url);
|
||||
executePostUrl("airmedia/receivers/" + encodeUrl(airPlayName) + "/", gson.toJson(request),
|
||||
FreeboxEmptyResponse.class, true, false, true);
|
||||
}
|
||||
|
||||
public void stopMedia(String airPlayName, String airPlayPassword) throws FreeboxException {
|
||||
FreeboxAirMediaReceiverRequest request = new FreeboxAirMediaReceiverRequest();
|
||||
request.setStopAction();
|
||||
request.setVideoMediaType();
|
||||
if (airPlayPassword != null && !airPlayPassword.isEmpty()) {
|
||||
request.setPassword(airPlayPassword);
|
||||
}
|
||||
executePostUrl("airmedia/receivers/" + encodeUrl(airPlayName) + "/", gson.toJson(request),
|
||||
FreeboxEmptyResponse.class, true, false, true);
|
||||
}
|
||||
|
||||
public void reboot() throws FreeboxException {
|
||||
executePostUrl("system/reboot/", null, FreeboxEmptyResponse.class);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executeGetUrl(String relativeUrl, Class<T> responseClass)
|
||||
throws FreeboxException {
|
||||
return executeUrl("GET", relativeUrl, null, responseClass, true, false, false);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executeGetUrl(String relativeUrl, Class<T> responseClass,
|
||||
boolean retryAuth) throws FreeboxException {
|
||||
return executeUrl("GET", relativeUrl, null, responseClass, retryAuth, false, false);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executeGetUrl(String relativeUrl, Class<T> responseClass,
|
||||
boolean retryAuth, boolean patchTableReponse, boolean doNotLogData) throws FreeboxException {
|
||||
return executeUrl("GET", relativeUrl, null, responseClass, retryAuth, patchTableReponse, doNotLogData);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executePostUrl(String relativeUrl, String requestContent,
|
||||
Class<T> responseClass) throws FreeboxException {
|
||||
return executeUrl("POST", relativeUrl, requestContent, responseClass, true, false, false);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executePostUrl(String relativeUrl, String requestContent,
|
||||
Class<T> responseClass, boolean retryAuth) throws FreeboxException {
|
||||
return executeUrl("POST", relativeUrl, requestContent, responseClass, retryAuth, false, false);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executePostUrl(String relativeUrl, String requestContent,
|
||||
Class<T> responseClass, boolean retryAuth, boolean patchTableReponse, boolean doNotLogData)
|
||||
throws FreeboxException {
|
||||
return executeUrl("POST", relativeUrl, requestContent, responseClass, retryAuth, patchTableReponse,
|
||||
doNotLogData);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executePutUrl(String relativeUrl, String requestContent,
|
||||
Class<T> responseClass) throws FreeboxException {
|
||||
return executeUrl("PUT", relativeUrl, requestContent, responseClass, true, false, false);
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F executeUrl(String httpMethod, String relativeUrl, String requestContent,
|
||||
Class<T> responseClass, boolean retryAuth, boolean patchTableReponse, boolean doNotLogData)
|
||||
throws FreeboxException {
|
||||
try {
|
||||
Properties headers = null;
|
||||
String token = getSessionToken();
|
||||
if (token != null) {
|
||||
headers = new Properties();
|
||||
headers.setProperty(AUTH_HEADER, token);
|
||||
}
|
||||
InputStream stream = null;
|
||||
String contentType = null;
|
||||
if (requestContent != null) {
|
||||
stream = new ByteArrayInputStream(requestContent.getBytes(StandardCharsets.UTF_8));
|
||||
contentType = HTTP_CALL_CONTENT_TYPE;
|
||||
}
|
||||
logger.debug("executeUrl {} {} requestContent {}", httpMethod, relativeUrl,
|
||||
doNotLogData ? "***" : requestContent);
|
||||
String jsonResponse = HttpUtil.executeUrl(httpMethod, baseAddress + relativeUrl, headers, stream,
|
||||
contentType, HTTP_CALL_DEFAULT_TIMEOUT_MS);
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
stream = null;
|
||||
}
|
||||
|
||||
if (patchTableReponse) {
|
||||
// Replace empty result by an empty table result
|
||||
jsonResponse = jsonResponse.replace("\"result\":{}", "\"result\":[]");
|
||||
}
|
||||
|
||||
return evaluateJsonReesponse(jsonResponse, responseClass, doNotLogData);
|
||||
} catch (FreeboxException e) {
|
||||
if (retryAuth && e.isAuthRequired()) {
|
||||
logger.debug("Authentication required: open a new session and retry the request");
|
||||
openSession();
|
||||
return executeUrl(httpMethod, relativeUrl, requestContent, responseClass, false, patchTableReponse,
|
||||
doNotLogData);
|
||||
}
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new FreeboxException(httpMethod + " request " + relativeUrl + ": execution failed: " + e.getMessage(),
|
||||
e);
|
||||
} catch (JsonSyntaxException e) {
|
||||
throw new FreeboxException(
|
||||
httpMethod + " request " + relativeUrl + ": response parsing failed: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends FreeboxResponse<F>, F> F evaluateJsonReesponse(String jsonResponse, Class<T> responseClass,
|
||||
boolean doNotLogData) throws JsonSyntaxException, FreeboxException {
|
||||
logger.debug("evaluateJsonReesponse Json {}", doNotLogData ? "***" : jsonResponse);
|
||||
// First check only if the result is successful
|
||||
FreeboxResponse<Object> partialResponse = gson.fromJson(jsonResponse, FreeboxEmptyResponse.class);
|
||||
partialResponse.evaluate();
|
||||
// Parse the full response in case of success
|
||||
T fullResponse = gson.fromJson(jsonResponse, responseClass);
|
||||
fullResponse.evaluate();
|
||||
F result = fullResponse.getResult();
|
||||
return result;
|
||||
}
|
||||
|
||||
private String encodeUrl(String url) throws FreeboxException {
|
||||
try {
|
||||
return URLEncoder.encode(url, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new FreeboxException("Encoding the URL \"" + url + "\" in UTF-8 failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String hmacSha1(String key, String value) throws FreeboxException {
|
||||
try {
|
||||
// Get an hmac_sha1 key from the raw key bytes
|
||||
byte[] keyBytes = key.getBytes();
|
||||
SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
|
||||
|
||||
// Get an hmac_sha1 Mac instance and initialize with the signing key
|
||||
Mac mac = Mac.getInstance("HmacSHA1");
|
||||
mac.init(signingKey);
|
||||
|
||||
// Compute the hmac on input data bytes
|
||||
byte[] rawHmac = mac.doFinal(value.getBytes());
|
||||
|
||||
// Convert raw bytes to a String
|
||||
return HexUtils.bytesToHex(rawHmac).toLowerCase();
|
||||
} catch (IllegalArgumentException | NoSuchAlgorithmException | InvalidKeyException | IllegalStateException e) {
|
||||
throw new FreeboxException("Computing the hmac-sha1 of the challenge and the app token failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxResponse;
|
||||
|
||||
/**
|
||||
* Exception for errors when using the Freebox API
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected FreeboxResponse<?> response;
|
||||
|
||||
public FreeboxException(String msg) {
|
||||
this(msg, null, null);
|
||||
}
|
||||
|
||||
public FreeboxException(String msg, Throwable cause) {
|
||||
this(msg, cause, null);
|
||||
}
|
||||
|
||||
public FreeboxException(String msg, FreeboxResponse<?> response) {
|
||||
this(msg, null, response);
|
||||
}
|
||||
|
||||
public FreeboxException(FreeboxResponse<?> response) {
|
||||
this(response.getMsg(), null, response);
|
||||
}
|
||||
|
||||
public FreeboxException(String msg, Throwable cause, FreeboxResponse<?> response) {
|
||||
super(msg, cause);
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public FreeboxResponse<?> getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public boolean isAuthRequired() {
|
||||
return getResponse() != null && getResponse().isAuthRequired();
|
||||
}
|
||||
|
||||
public boolean isMissingRights() {
|
||||
return getResponse() != null && getResponse().isMissingRights();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.io.net.http.TlsCertificateProvider;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* Provides a TrustManager for the Freebox SSL certificate
|
||||
*
|
||||
* @author Laurent Garnier - Initial Contribution
|
||||
*/
|
||||
@Component
|
||||
@NonNullByDefault
|
||||
public class FreeboxTlsCertificateProvider implements TlsCertificateProvider {
|
||||
|
||||
@Override
|
||||
public String getHostName() {
|
||||
return "mafreebox.freebox.fr";
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getCertificate() {
|
||||
URL resource = Thread.currentThread().getContextClassLoader().getResource("freeboxECCRootCA.crt");
|
||||
if (resource != null) {
|
||||
return resource;
|
||||
} else {
|
||||
throw new IllegalStateException("Certifcate resource not found or not accessible");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaConfig} is the Java class used to map the "AirMediaConfig"
|
||||
* structure used by the AirMedia configuration API
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaConfig {
|
||||
private Boolean enabled;
|
||||
private String password;
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaConfigResponse} is the Java class used to map the
|
||||
* response of the AirMedia configuration API
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaConfigResponse extends FreeboxResponse<FreeboxAirMediaConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in AirMedia configuration API response", this);
|
||||
}
|
||||
if (getResult().isEnabled() == null) {
|
||||
throw new FreeboxException("No AirMedia status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaReceiver} is the Java class used to map the "AirMediaReceiver"
|
||||
* structure used by the available AirMedia receivers API
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaReceiver {
|
||||
private String name;
|
||||
private boolean passwordProtected;
|
||||
private FreeboxAirMediaReceiverCapabilities capabilities;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public boolean isPasswordProtected() {
|
||||
return passwordProtected;
|
||||
}
|
||||
|
||||
public FreeboxAirMediaReceiverCapabilities getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
public boolean isPhotoCapable() {
|
||||
return capabilities.isPhotoCapable();
|
||||
}
|
||||
|
||||
public boolean isScreenCapable() {
|
||||
return capabilities.isScreenCapable();
|
||||
}
|
||||
|
||||
public boolean isVideoCapable() {
|
||||
return capabilities.isVideoCapable();
|
||||
}
|
||||
|
||||
public boolean isAudioCapable() {
|
||||
return capabilities.isAudioCapable();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaReceiverCapabilities} is the Java class used to map the
|
||||
* structure used inside the response of the available AirMedia receivers API to provide
|
||||
* the receiver capabilities
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaReceiverCapabilities {
|
||||
private boolean photo;
|
||||
private boolean screen;
|
||||
private boolean video;
|
||||
private boolean audio;
|
||||
|
||||
public boolean isPhotoCapable() {
|
||||
return photo;
|
||||
}
|
||||
|
||||
public boolean isScreenCapable() {
|
||||
return screen;
|
||||
}
|
||||
|
||||
public boolean isVideoCapable() {
|
||||
return video;
|
||||
}
|
||||
|
||||
public boolean isAudioCapable() {
|
||||
return audio;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaReceiverRequest} is the Java class used to map the "AirMediaReceiverRequest"
|
||||
* structure used by the sending request to an AirMedia receiver API
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaReceiverRequest {
|
||||
|
||||
private static enum MediaAction {
|
||||
START("start"),
|
||||
STOP("stop");
|
||||
|
||||
private String action;
|
||||
|
||||
private MediaAction(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
private static enum MediaType {
|
||||
VIDEO("video"),
|
||||
PHOTO("photo");
|
||||
|
||||
private String mediaType;
|
||||
|
||||
private MediaType(String mediaType) {
|
||||
this.mediaType = mediaType;
|
||||
}
|
||||
|
||||
public String getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
}
|
||||
|
||||
private String action;
|
||||
private String mediaType;
|
||||
private String password;
|
||||
private Integer position;
|
||||
private String media;
|
||||
|
||||
public void setStartAction() {
|
||||
this.action = MediaAction.START.getAction();
|
||||
}
|
||||
|
||||
public void setStopAction() {
|
||||
this.action = MediaAction.STOP.getAction();
|
||||
}
|
||||
|
||||
public void setVideoMediaType() {
|
||||
this.mediaType = MediaType.VIDEO.getMediaType();
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setPosition(Integer position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public void setMedia(String media) {
|
||||
this.media = media;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirMediaReceiversResponse} is the Java class used to map the
|
||||
* response of the available AirMedia receivers API
|
||||
* https://dev.freebox.fr/sdk/os/airmedia/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirMediaReceiversResponse extends FreeboxResponse<List<FreeboxAirMediaReceiver>> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in available AirMedia receivers API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAuthorizationStatus} is the Java class used to map the
|
||||
* structure used by the response of the track authorization progress API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAuthorizationStatus {
|
||||
|
||||
private static enum AuthorizationStatus {
|
||||
UNKNOWN("unknown"),
|
||||
PENDING("pending"),
|
||||
TIMEOUT("timeout"),
|
||||
GRANTED("granted"),
|
||||
DENIED("denied");
|
||||
|
||||
private String status;
|
||||
|
||||
private AuthorizationStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
private String status;
|
||||
private String challenge;
|
||||
|
||||
public boolean isStatusPending() {
|
||||
return AuthorizationStatus.PENDING.getStatus().equalsIgnoreCase(status);
|
||||
}
|
||||
|
||||
public boolean isStatusGranted() {
|
||||
return AuthorizationStatus.GRANTED.getStatus().equalsIgnoreCase(status);
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public String getChallenge() {
|
||||
return challenge;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAuthorizationStatusResponse} is the Java class used to map the
|
||||
* response of the track authorization progress API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAuthorizationStatusResponse extends FreeboxResponse<FreeboxAuthorizationStatus> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in track authorization progress API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAuthorizeRequest} is the Java class used to map the
|
||||
* structure used by the request of the request authorization API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAuthorizeRequest {
|
||||
private String appId;
|
||||
private String appName;
|
||||
private String appVersion;
|
||||
private String deviceName;
|
||||
|
||||
public FreeboxAuthorizeRequest(String appId, String appName, String appVersion, String deviceName) {
|
||||
this.appId = appId;
|
||||
this.appName = appName;
|
||||
this.appVersion = appVersion;
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAuthorizeResponse} is the Java class used to map the
|
||||
* response of the request authorization API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAuthorizeResponse extends FreeboxResponse<FreeboxAuthorizeResult> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in request authorization API response", this);
|
||||
}
|
||||
if ((getResult().getAppToken() == null) || getResult().getAppToken().isEmpty()) {
|
||||
throw new FreeboxException("No app token in response", this);
|
||||
}
|
||||
if (getResult().getTrackId() == null) {
|
||||
throw new FreeboxException("No track id in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAuthorizeResult} is the Java class used to map the
|
||||
* structure used by the response of the request authorization API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAuthorizeResult {
|
||||
private String appToken;
|
||||
private Integer trackId;
|
||||
|
||||
public String getAppToken() {
|
||||
return appToken;
|
||||
}
|
||||
|
||||
public Integer getTrackId() {
|
||||
return trackId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxCallEntry} is the Java class used to map the "CallEntry"
|
||||
* structure used by the call API
|
||||
* https://dev.freebox.fr/sdk/os/call/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxCallEntry {
|
||||
private static final String CALL_ENTRY_TYPE_ACCEPTED = "accepted";
|
||||
private static final String CALL_ENTRY_TYPE_MISSED = "missed";
|
||||
private static final String CALL_ENTRY_TYPE_OUTGOING = "outgoing";
|
||||
|
||||
private int id;
|
||||
private String type;
|
||||
private long datetime;
|
||||
private String number;
|
||||
private String name;
|
||||
private int duration;
|
||||
@SerializedName("new")
|
||||
private boolean newCall;
|
||||
private int contactId;
|
||||
|
||||
public Calendar getTimeStamp() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTimeInMillis(datetime * 1000);
|
||||
return c;
|
||||
}
|
||||
|
||||
public boolean isAccepted() {
|
||||
return CALL_ENTRY_TYPE_ACCEPTED.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
public boolean isMissed() {
|
||||
return CALL_ENTRY_TYPE_MISSED.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
public boolean isOutGoing() {
|
||||
return CALL_ENTRY_TYPE_OUTGOING.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public long getDatetime() {
|
||||
return datetime;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
public boolean isNewCall() {
|
||||
return newCall;
|
||||
}
|
||||
|
||||
public int getContactId() {
|
||||
return contactId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxCallEntryResponse} is the Java class used to map the
|
||||
* response of the call API
|
||||
* https://dev.freebox.fr/sdk/os/call/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxCallEntryResponse extends FreeboxResponse<List<FreeboxCallEntry>> {
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxConnectionStatus} is the Java class used to map the "ConnectionStatus"
|
||||
* structure used by the connection API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxConnectionStatus {
|
||||
private String state;
|
||||
private String type;
|
||||
private String media;
|
||||
private String ipv4;
|
||||
private String ipv6;
|
||||
private long rateUp;
|
||||
private long rateDown;
|
||||
private long bandwidthUp;
|
||||
private long bandwidthDown;
|
||||
private long bytesUp;
|
||||
private long bytesDown;
|
||||
private Long[] ipv4PortRange;
|
||||
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getMedia() {
|
||||
return media;
|
||||
}
|
||||
|
||||
public String getIpv4() {
|
||||
return ipv4;
|
||||
}
|
||||
|
||||
public String getIpv6() {
|
||||
return ipv6;
|
||||
}
|
||||
|
||||
public long getRateUp() {
|
||||
return rateUp;
|
||||
}
|
||||
|
||||
public long getRateDown() {
|
||||
return rateDown;
|
||||
}
|
||||
|
||||
public long getBandwidthUp() {
|
||||
return bandwidthUp;
|
||||
}
|
||||
|
||||
public long getBandwidthDown() {
|
||||
return bandwidthDown;
|
||||
}
|
||||
|
||||
public long getBytesUp() {
|
||||
return bytesUp;
|
||||
}
|
||||
|
||||
public long getBytesDown() {
|
||||
return bytesDown;
|
||||
}
|
||||
|
||||
public Long getIpvPortMin() {
|
||||
return ipv4PortRange[0];
|
||||
}
|
||||
|
||||
public Long getIpvPortMax() {
|
||||
return ipv4PortRange[1];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxConnectionStatusResponse} is the Java class used to map the
|
||||
* response of the connection API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxConnectionStatusResponse extends FreeboxResponse<FreeboxConnectionStatus> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in connection API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxDiscoveryResponse} is the Java class used to map the
|
||||
* structure used by the response of the request authorization API
|
||||
* https://dev.freebox.fr/sdk/os/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxDiscoveryResponse {
|
||||
private String uid;
|
||||
private String deviceName;
|
||||
private String apiVersion;
|
||||
private String apiBaseUrl;
|
||||
private String deviceType;
|
||||
private String apiDomain;
|
||||
private Boolean httpsAvailable;
|
||||
private Integer httpsPort;
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public String getApiVersion() {
|
||||
return apiVersion;
|
||||
}
|
||||
|
||||
public String getApiBaseUrl() {
|
||||
return apiBaseUrl;
|
||||
}
|
||||
|
||||
public String getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public String getApiDomain() {
|
||||
return apiDomain;
|
||||
}
|
||||
|
||||
public Boolean isHttpsAvailable() {
|
||||
return httpsAvailable;
|
||||
}
|
||||
|
||||
public Integer getHttpsPort() {
|
||||
return httpsPort;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxEmptyResponse} is the Java class used to map an empty response
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxEmptyResponse extends FreeboxResponse<Object> {
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxFtpConfig} is the Java class used to map the "FtpConfig"
|
||||
* structure used by the FTP configuration API
|
||||
* https://dev.freebox.fr/sdk/os/ftp/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxFtpConfig {
|
||||
private Boolean enabled;
|
||||
private Boolean allowAnonymous;
|
||||
private Boolean allowAnonymousWrite;
|
||||
private String password;
|
||||
private Boolean allowRemoteAccess;
|
||||
private Boolean weakPassword;
|
||||
private Integer portCtrl;
|
||||
private Integer portData;
|
||||
private String remoteDomain;
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Boolean isAllowAnonymous() {
|
||||
return allowAnonymous;
|
||||
}
|
||||
|
||||
public void setAllowAnonymous(Boolean allowAnonymous) {
|
||||
this.allowAnonymous = allowAnonymous;
|
||||
}
|
||||
|
||||
public Boolean isAllowAnonymousWrite() {
|
||||
return allowAnonymousWrite;
|
||||
}
|
||||
|
||||
public void setAllowAnonymousWrite(Boolean allowAnonymousWrite) {
|
||||
this.allowAnonymousWrite = allowAnonymousWrite;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public Boolean isAllowRemoteAccess() {
|
||||
return allowRemoteAccess;
|
||||
}
|
||||
|
||||
public void setAllowRemoteAccess(Boolean allowRemoteAccess) {
|
||||
this.allowRemoteAccess = allowRemoteAccess;
|
||||
}
|
||||
|
||||
public Boolean isWeakPassword() {
|
||||
return weakPassword;
|
||||
}
|
||||
|
||||
public void setWeakPassword(Boolean weakPassword) {
|
||||
this.weakPassword = weakPassword;
|
||||
}
|
||||
|
||||
public Integer getPortCtrl() {
|
||||
return portCtrl;
|
||||
}
|
||||
|
||||
public void setPortCtrl(Integer portCtrl) {
|
||||
this.portCtrl = portCtrl;
|
||||
}
|
||||
|
||||
public Integer getPortData() {
|
||||
return portData;
|
||||
}
|
||||
|
||||
public void setPortData(Integer portData) {
|
||||
this.portData = portData;
|
||||
}
|
||||
|
||||
public String getRemoteDomain() {
|
||||
return remoteDomain;
|
||||
}
|
||||
|
||||
public void setRemoteDomain(String remoteDomain) {
|
||||
this.remoteDomain = remoteDomain;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxFtpConfigResponse} is the Java class used to map the
|
||||
* response of the FTP configuration API
|
||||
* https://dev.freebox.fr/sdk/os/ftp/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxFtpConfigResponse extends FreeboxResponse<FreeboxFtpConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in FTP configuration API response", this);
|
||||
}
|
||||
if (getResult().isEnabled() == null) {
|
||||
throw new FreeboxException("No FTP status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxFtthStatus} is the Java class used to map the "FtthStatus"
|
||||
* structure used by the response of the connection Ftth status API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class FreeboxFtthStatus {
|
||||
private boolean sfp_present;
|
||||
private boolean sfp_alim_ok;
|
||||
private boolean sfp_has_power_report;
|
||||
private boolean sfp_has_signal;
|
||||
private boolean link;
|
||||
private String sfp_serial;
|
||||
private String sfp_model;
|
||||
private String sfp_vendor;
|
||||
private long sfp_pwr_tx;
|
||||
private long sfp_pwr_rx;
|
||||
|
||||
public boolean getSfpPresent() {
|
||||
return sfp_present;
|
||||
}
|
||||
|
||||
public boolean getSfpAlimOk() {
|
||||
return sfp_alim_ok;
|
||||
}
|
||||
|
||||
public boolean getSfpHasPowerReport() {
|
||||
return sfp_has_power_report;
|
||||
}
|
||||
|
||||
public boolean getSfpHasSignal() {
|
||||
return sfp_has_signal;
|
||||
}
|
||||
|
||||
public boolean getLink() {
|
||||
return link;
|
||||
}
|
||||
|
||||
public String getSfpSerial() {
|
||||
return sfp_serial;
|
||||
}
|
||||
|
||||
public String getSfpModel() {
|
||||
return sfp_model;
|
||||
}
|
||||
|
||||
public String getSfpVendor() {
|
||||
return sfp_vendor;
|
||||
}
|
||||
|
||||
public long getSfpPwrTx() {
|
||||
return sfp_pwr_tx;
|
||||
}
|
||||
|
||||
public long getSfpPwrRx() {
|
||||
return sfp_pwr_rx;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxFtthStatusResponse} is the Java class used to map the
|
||||
* response of the connection Ftth status API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
public class FreeboxFtthStatusResponse extends FreeboxResponse<FreeboxFtthStatus> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in connection Ftth status API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanConfig} is the Java class used to map the "LanConfig"
|
||||
* structure used by the LAN configuration API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanConfig {
|
||||
private static final String LAN_BRIDGE_MODE = "bridge";
|
||||
|
||||
private String ip;
|
||||
private String name;
|
||||
private String nameDns;
|
||||
private String nameMdns;
|
||||
private String nameNetbios;
|
||||
private String type;
|
||||
|
||||
public boolean isInBridgeMode() {
|
||||
return LAN_BRIDGE_MODE.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getNameDns() {
|
||||
return nameDns;
|
||||
}
|
||||
|
||||
public String getNameMdns() {
|
||||
return nameMdns;
|
||||
}
|
||||
|
||||
public String getNameNetbios() {
|
||||
return nameNetbios;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanConfigResponse} is the Java class used to map the
|
||||
* response of the LAN configuration API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanConfigResponse extends FreeboxResponse<FreeboxLanConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in LAN configuration API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanHost} is the Java class used to map the "LanHost"
|
||||
* structure used by the Lan Hosts Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanHost {
|
||||
private String id;
|
||||
private String primaryName;
|
||||
private String hostType;
|
||||
private boolean primaryNameManual;
|
||||
private FreeboxLanHostL2Ident l2ident;
|
||||
private String vendorName;
|
||||
private boolean persistent;
|
||||
private boolean reachable;
|
||||
private long lastTimeReachable;
|
||||
private boolean active;
|
||||
private long lastActivity;
|
||||
private List<FreeboxLanHostName> names;
|
||||
private List<FreeboxLanHostL3Connectivity> l3connectivities;
|
||||
|
||||
public String getMAC() {
|
||||
return (l2ident != null && l2ident.isMacAddress()) ? l2ident.getId() : null;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getPrimaryName() {
|
||||
return primaryName;
|
||||
}
|
||||
|
||||
public String getHostType() {
|
||||
return hostType;
|
||||
}
|
||||
|
||||
public boolean isPrimaryNameManual() {
|
||||
return primaryNameManual;
|
||||
}
|
||||
|
||||
public FreeboxLanHostL2Ident getL2Ident() {
|
||||
return l2ident;
|
||||
}
|
||||
|
||||
public String getVendorName() {
|
||||
return vendorName;
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return persistent;
|
||||
}
|
||||
|
||||
public boolean isReachable() {
|
||||
return reachable;
|
||||
}
|
||||
|
||||
public long getLastTimeReachable() {
|
||||
return lastTimeReachable;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public long getLastActivity() {
|
||||
return lastActivity;
|
||||
}
|
||||
|
||||
public List<FreeboxLanHostName> getNames() {
|
||||
return names;
|
||||
}
|
||||
|
||||
public List<FreeboxLanHostL3Connectivity> getL3Connectivities() {
|
||||
return l3connectivities;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanHostL2Ident} is the Java class used to map the "LanHostL2Ident"
|
||||
* structure used by the Lan Hosts Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanHostL2Ident {
|
||||
private static final String L2_TYPE_MAC_ADDRESS = "mac_address";
|
||||
|
||||
private String id;
|
||||
private String type;
|
||||
|
||||
public boolean isMacAddress() {
|
||||
return L2_TYPE_MAC_ADDRESS.equalsIgnoreCase(type);
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanHostL3Connectivity} is the Java class used to map the "LanHostL3Connectivity"
|
||||
* structure used by the Lan Hosts Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanHostL3Connectivity {
|
||||
private String addr;
|
||||
private String af;
|
||||
private boolean active;
|
||||
private boolean reachable;
|
||||
private long lastActivity;
|
||||
private long lastTimeReachable;
|
||||
|
||||
public String getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
public String getAf() {
|
||||
return af;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public boolean isReachable() {
|
||||
return reachable;
|
||||
}
|
||||
|
||||
public long getLastActivity() {
|
||||
return lastActivity;
|
||||
}
|
||||
|
||||
public long getLastTimeReachable() {
|
||||
return lastTimeReachable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanHostName} is the Java class used to map the "LanHostName"
|
||||
* structure used by the Lan Hosts Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanHostName {
|
||||
private String name;
|
||||
private String source;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanHostsResponse} is the Java class used to map the
|
||||
* response of Lan Hosts Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanHostsResponse extends FreeboxResponse<List<FreeboxLanHost>> {
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanInterface} is the Java class used to map the
|
||||
* structure used by the Lan Interface Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanInterface {
|
||||
private String name;
|
||||
private int hostCount;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getHostCount() {
|
||||
return hostCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLanInterfacesResponse} is the Java class used to map the
|
||||
* response of Lan Interface Browser API
|
||||
* https://dev.freebox.fr/sdk/os/lan/#lan-browser
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLanInterfacesResponse extends FreeboxResponse<List<FreeboxLanInterface>> {
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLcdConfig} is the Java class used to map the "LcdConfig"
|
||||
* structure used by the LCD configuration API
|
||||
* https://dev.freebox.fr/sdk/os/lcd/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLcdConfig {
|
||||
private int brightness;
|
||||
private boolean orientationForced;
|
||||
private int orientation;
|
||||
|
||||
public int getBrightness() {
|
||||
return brightness;
|
||||
}
|
||||
|
||||
public void setBrightness(int brightness) {
|
||||
this.brightness = brightness;
|
||||
}
|
||||
|
||||
public boolean isOrientationForced() {
|
||||
return orientationForced;
|
||||
}
|
||||
|
||||
public void setOrientationForced(boolean orientationForced) {
|
||||
this.orientationForced = orientationForced;
|
||||
}
|
||||
|
||||
public int getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
public void setOrientation(int orientation) {
|
||||
this.orientation = orientation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLcdConfigResponse} is the Java class used to map the
|
||||
* response of the LCD configuration API
|
||||
* https://dev.freebox.fr/sdk/os/lcd/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLcdConfigResponse extends FreeboxResponse<FreeboxLcdConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in LCD configuration API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLoginResponse} is the Java class used to map the
|
||||
* response of the login API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLoginResponse extends FreeboxResponse<FreeboxLoginResult> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in login API response", this);
|
||||
}
|
||||
if ((getResult().getChallenge() == null) || getResult().getChallenge().isEmpty()) {
|
||||
throw new FreeboxException("No challenge in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxLoginResult} is the Java class used to map the
|
||||
* structure used by the response of the login API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxLoginResult {
|
||||
private Boolean loggedIn;
|
||||
private String challenge;
|
||||
|
||||
public Boolean isLoggedIn() {
|
||||
return loggedIn;
|
||||
}
|
||||
|
||||
public String getChallenge() {
|
||||
return challenge;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxOpenSessionRequest} is the Java class used to map the
|
||||
* structure used by the request of the open session API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxOpenSessionRequest {
|
||||
private String appId;
|
||||
private String password;
|
||||
|
||||
public FreeboxOpenSessionRequest(String appId, String password) {
|
||||
this.appId = appId;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxOpenSessionResponse} is the Java class used to map the
|
||||
* response of the open session API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxOpenSessionResponse extends FreeboxResponse<FreeboxOpenSessionResult> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in open session API response", this);
|
||||
}
|
||||
if ((getResult().getSessionToken() == null) || getResult().getSessionToken().isEmpty()) {
|
||||
throw new FreeboxException("No session token in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxOpenSessionResult} is the Java class used to map the
|
||||
* structure used by the response of the open session API
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxOpenSessionResult {
|
||||
private String sessionToken;
|
||||
private String challenge;
|
||||
private FreeboxPermissions permissions;
|
||||
|
||||
public String getSessionToken() {
|
||||
return sessionToken;
|
||||
}
|
||||
|
||||
public String getChallenge() {
|
||||
return challenge;
|
||||
}
|
||||
|
||||
public FreeboxPermissions getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxPermissions} is the Java class used to map the
|
||||
* structure used inside the response of the open session API to provide
|
||||
* the permissions
|
||||
* https://dev.freebox.fr/sdk/os/login/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxPermissions {
|
||||
private Boolean settings;
|
||||
private Boolean contacts;
|
||||
private Boolean calls;
|
||||
private Boolean explorer;
|
||||
private Boolean downloader;
|
||||
private Boolean parental;
|
||||
private Boolean pvr;
|
||||
private Boolean tv;
|
||||
|
||||
public Boolean isSettingsAllowed() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public Boolean isContactsAllowed() {
|
||||
return contacts;
|
||||
}
|
||||
|
||||
public Boolean isCallsAllowed() {
|
||||
return calls;
|
||||
}
|
||||
|
||||
public Boolean isExplorerAllowed() {
|
||||
return explorer;
|
||||
}
|
||||
|
||||
public Boolean isDownloaderAllowed() {
|
||||
return downloader;
|
||||
}
|
||||
|
||||
public Boolean isParentalAllowed() {
|
||||
return parental;
|
||||
}
|
||||
|
||||
public Boolean isPvrAllowed() {
|
||||
return pvr;
|
||||
}
|
||||
|
||||
public Boolean istTvAllowed() {
|
||||
return tv;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxPhoneStatus} is the Java class used to map the
|
||||
* structure used by the phone API
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxPhoneStatus {
|
||||
private boolean isRinging;
|
||||
private boolean onHook;
|
||||
|
||||
public boolean isRinging() {
|
||||
return isRinging;
|
||||
}
|
||||
|
||||
public boolean isOnHook() {
|
||||
return onHook;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxPhoneStatusResponse} is the Java class used to map the
|
||||
* response of the phone API
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxPhoneStatusResponse extends FreeboxResponse<List<FreeboxPhoneStatus>> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null || getResult().isEmpty()) {
|
||||
throw new FreeboxException("No phone status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxResponse} is the Java class used to map the "APIResponse"
|
||||
* structure used by the API
|
||||
* https://dev.freebox.fr/sdk/os/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxResponse<T> {
|
||||
private static final String AUTHORIZATION_REQUIRED = "auth_required";
|
||||
private static final String INSUFFICIENT_RIGHTS = "insufficient_rights";
|
||||
|
||||
private Boolean success;
|
||||
private String errorCode;
|
||||
private String uid;
|
||||
private String msg;
|
||||
private String missingRight;
|
||||
private T result;
|
||||
|
||||
public void evaluate() throws FreeboxException {
|
||||
if (!isSuccess()) {
|
||||
throw new FreeboxException(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAuthRequired() {
|
||||
return AUTHORIZATION_REQUIRED.equalsIgnoreCase(errorCode);
|
||||
}
|
||||
|
||||
public boolean isMissingRights() {
|
||||
return INSUFFICIENT_RIGHTS.equalsIgnoreCase(errorCode);
|
||||
}
|
||||
|
||||
public Boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public String getMissingRight() {
|
||||
return missingRight;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxSambaConfig} is the Java class used to map the "SambaConfig"
|
||||
* structure used by the Samba configuration API
|
||||
* https://dev.freebox.fr/sdk/os/network_share/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxSambaConfig {
|
||||
private Boolean fileShareEnabled;
|
||||
private Boolean printShareEnabled;
|
||||
private Boolean logonEnabled;
|
||||
private String logonUser;
|
||||
private String logonPassword;
|
||||
private String workgroup;
|
||||
|
||||
public Boolean isFileShareEnabled() {
|
||||
return fileShareEnabled;
|
||||
}
|
||||
|
||||
public void setFileShareEnabled(Boolean fileShareEnabled) {
|
||||
this.fileShareEnabled = fileShareEnabled;
|
||||
}
|
||||
|
||||
public Boolean isPrintShareEnabled() {
|
||||
return printShareEnabled;
|
||||
}
|
||||
|
||||
public void setPrintShareEnabled(Boolean printShareEnabled) {
|
||||
this.printShareEnabled = printShareEnabled;
|
||||
}
|
||||
|
||||
public Boolean isLogonEnabled() {
|
||||
return logonEnabled;
|
||||
}
|
||||
|
||||
public void setLogonEnabled(Boolean logonEnabled) {
|
||||
this.logonEnabled = logonEnabled;
|
||||
}
|
||||
|
||||
public String getLogonUser() {
|
||||
return logonUser;
|
||||
}
|
||||
|
||||
public void setLogonUser(String logonUser) {
|
||||
this.logonUser = logonUser;
|
||||
}
|
||||
|
||||
public String getWorkgroup() {
|
||||
return workgroup;
|
||||
}
|
||||
|
||||
public void setWorkgroup(String workgroup) {
|
||||
this.workgroup = workgroup;
|
||||
}
|
||||
|
||||
public void setLogonPassword(String logonPassword) {
|
||||
this.logonPassword = logonPassword;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxSambaConfigResponse} is the Java class used to map the
|
||||
* response of the Samba configuration API
|
||||
* https://dev.freebox.fr/sdk/os/network_share/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxSambaConfigResponse extends FreeboxResponse<FreeboxSambaConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in Samba configuration API response", this);
|
||||
}
|
||||
if (getResult().isFileShareEnabled() == null) {
|
||||
throw new FreeboxException("No file sharing status in response", this);
|
||||
}
|
||||
if (getResult().isPrintShareEnabled() == null) {
|
||||
throw new FreeboxException("No printer sharing status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxSensor} is the Java class used to map the fans and sensors part of the "SystemConfig"
|
||||
* structure used by the system API
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxSensor {
|
||||
private String id;
|
||||
private String name;
|
||||
private int value;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxSystemConfig} is the Java class used to map the "SystemConfig"
|
||||
* structure used by the system API
|
||||
* https://dev.freebox.fr/sdk/os/system/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxSystemConfig {
|
||||
private String firmwareVersion;
|
||||
private String mac;
|
||||
private String serial;
|
||||
private String uptime;
|
||||
private long uptimeVal;
|
||||
private String boardName;
|
||||
private int tempCpum;
|
||||
private int tempSw;
|
||||
private int tempCpub;
|
||||
private int fanRpm;
|
||||
private boolean boxAuthenticated;
|
||||
private String diskStatus;
|
||||
private String boxFlavor;
|
||||
private String userMainStorage;
|
||||
private List<FreeboxSensor> fans;
|
||||
private List<FreeboxSensor> sensors;
|
||||
|
||||
public String getFirmwareVersion() {
|
||||
return firmwareVersion;
|
||||
}
|
||||
|
||||
public String getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public String getSerial() {
|
||||
return serial;
|
||||
}
|
||||
|
||||
public String getUptime() {
|
||||
return uptime;
|
||||
}
|
||||
|
||||
public long getUptimeVal() {
|
||||
return uptimeVal;
|
||||
}
|
||||
|
||||
public String getBoardName() {
|
||||
return boardName;
|
||||
}
|
||||
|
||||
public int getTempCpum() {
|
||||
if (sensors != null) {
|
||||
for (FreeboxSensor sensor : sensors) {
|
||||
if ("temp_cpum".equals(sensor.getId())) {
|
||||
return sensor.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return tempCpum;
|
||||
}
|
||||
|
||||
public int getTempSw() {
|
||||
if (sensors != null) {
|
||||
for (FreeboxSensor sensor : sensors) {
|
||||
if ("temp_sw".equals(sensor.getId())) {
|
||||
return sensor.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return tempSw;
|
||||
}
|
||||
|
||||
public int getTempCpub() {
|
||||
if (sensors != null) {
|
||||
for (FreeboxSensor sensor : sensors) {
|
||||
if ("temp_cpub".equals(sensor.getId())) {
|
||||
return sensor.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return tempCpub;
|
||||
}
|
||||
|
||||
public int getFanRpm() {
|
||||
if (fans != null) {
|
||||
for (FreeboxSensor fan : fans) {
|
||||
if ("fan0_speed".equals(fan.getId())) {
|
||||
return fan.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return fanRpm;
|
||||
}
|
||||
|
||||
public boolean isBoxAuthenticated() {
|
||||
return boxAuthenticated;
|
||||
}
|
||||
|
||||
public String getDiskStatus() {
|
||||
return diskStatus;
|
||||
}
|
||||
|
||||
public String getBoxFlavor() {
|
||||
return boxFlavor;
|
||||
}
|
||||
|
||||
public String getUserMainStorage() {
|
||||
return userMainStorage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxSystemConfigResponse} is the Java class used to map the
|
||||
* response of the system API
|
||||
* https://dev.freebox.fr/sdk/os/system/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxSystemConfigResponse extends FreeboxResponse<FreeboxSystemConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in system API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxUPnPAVConfig} is the Java class used to map the "UPnPAVConfig"
|
||||
* structure used by the UPnP AV configuration API
|
||||
* https://dev.freebox.fr/sdk/os/upnpav/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxUPnPAVConfig {
|
||||
private Boolean enabled;
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxUPnPAVConfigResponse} is the Java class used to map the
|
||||
* response of the UPnP AV configuration API
|
||||
* https://dev.freebox.fr/sdk/os/upnpav/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxUPnPAVConfigResponse extends FreeboxResponse<FreeboxUPnPAVConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in UPnP AV configuration API response", this);
|
||||
}
|
||||
if (getResult().isEnabled() == null) {
|
||||
throw new FreeboxException("No UPnP AV status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxWifiGlobalConfig} is the Java class used to map the "WifiGlobalConfig"
|
||||
* structure used by the Wifi global configuration API
|
||||
* https://dev.freebox.fr/sdk/os/wifi/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxWifiGlobalConfig {
|
||||
private Boolean enabled;
|
||||
private String macFilterState;
|
||||
|
||||
public Boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getMacFilterState() {
|
||||
return macFilterState;
|
||||
}
|
||||
|
||||
public void setMacFilterState(String macFilterState) {
|
||||
this.macFilterState = macFilterState;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxWifiGlobalConfigResponse} is the Java class used to map the
|
||||
* response of the Wifi global configuration API
|
||||
* https://dev.freebox.fr/sdk/os/wifi/# *
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxWifiGlobalConfigResponse extends FreeboxResponse<FreeboxWifiGlobalConfig> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in Wifi global configuration API response", this);
|
||||
}
|
||||
if (getResult().isEnabled() == null) {
|
||||
throw new FreeboxException("No Wifi status in response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxXdslStatus} is the Java class used to map the "XdslStatus"
|
||||
* structure used by the response of the connection xDSL status API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxXdslStatus {
|
||||
public static class InternalXdslStatus {
|
||||
private String status;
|
||||
private String protocol;
|
||||
private String modulation;
|
||||
private long uptime;
|
||||
}
|
||||
|
||||
private InternalXdslStatus status;
|
||||
|
||||
public String getStatus() {
|
||||
return status.status;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return status.protocol;
|
||||
}
|
||||
|
||||
public String getModulation() {
|
||||
return status.modulation;
|
||||
}
|
||||
|
||||
public long getUptime() {
|
||||
return status.uptime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api.model;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxXdslStatusResponse} is the Java class used to map the
|
||||
* response of the connection xDSL status API
|
||||
* https://dev.freebox.fr/sdk/os/connection/#
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxXdslStatusResponse extends FreeboxResponse<FreeboxXdslStatus> {
|
||||
@Override
|
||||
public void evaluate() throws FreeboxException {
|
||||
super.evaluate();
|
||||
if (getResult() == null) {
|
||||
throw new FreeboxException("Missing result data in connection xDSL status API response", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.config;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxAirPlayDeviceConfiguration} is responsible for holding
|
||||
* configuration informations associated to a Freebox AirPlay Device thing type
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxAirPlayDeviceConfiguration {
|
||||
|
||||
public static final String NAME = "name";
|
||||
public static final String PASSWORD = "password";
|
||||
public static final String ACCEPT_ALL_MP3 = "acceptAllMp3";
|
||||
|
||||
public String name;
|
||||
public String password;
|
||||
public Boolean acceptAllMp3;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.config;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxNetDeviceConfiguration} is responsible for holding
|
||||
* configuration informations associated to a Freebox Network Device
|
||||
* thing type
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxNetDeviceConfiguration {
|
||||
|
||||
public static final String MAC_ADDRESS = "macAddress";
|
||||
|
||||
public String macAddress;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.config;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxNetInterfaceConfiguration} is responsible for holding
|
||||
* configuration informations associated to a Freebox Network Interface
|
||||
* thing type
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxNetInterfaceConfiguration {
|
||||
|
||||
public static final String IP_ADDRESS = "ipAddress";
|
||||
|
||||
public String ipAddress;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.config;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxPhoneConfiguration} is responsible for holding
|
||||
* configuration informations associated to a Freebox Phone thing type
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
public class FreeboxPhoneConfiguration {
|
||||
|
||||
public static final String REFRESH_PHONE_INTERVAL = "refreshPhoneInterval";
|
||||
public static final String REFRESH_PHONE_CALLS_INTERVAL = "refreshPhoneCallsInterval";
|
||||
|
||||
public Integer refreshPhoneInterval;
|
||||
public Integer refreshPhoneCallsInterval;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.config;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxServerConfiguration} is responsible for holding
|
||||
* configuration informations needed to access/poll the freebox server
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
* @author Laurent Garnier - add discovery settings
|
||||
*/
|
||||
public class FreeboxServerConfiguration {
|
||||
|
||||
public static final String FQDN = "fqdn";
|
||||
public static final String APP_TOKEN = "appToken";
|
||||
public static final String REFRESH_INTERVAL = "refreshInterval";
|
||||
public static final String USE_ONLY_HTTP = "useOnlyHttp";
|
||||
public static final String DISCOVER_PHONE = "discoverPhone";
|
||||
public static final String DISCOVER_NET_DEVICE = "discoverNetDevice";
|
||||
public static final String DISCOVER_NET_INTERFACE = "discoverNetInterface";
|
||||
public static final String DISCOVER_AIRPLAY_RECEIVER = "discoverAirPlayReceiver";
|
||||
|
||||
public String fqdn;
|
||||
public String appToken;
|
||||
public Integer refreshInterval;
|
||||
public Boolean useOnlyHttp;
|
||||
public Boolean discoverPhone;
|
||||
public Boolean discoverNetDevice;
|
||||
public Boolean discoverNetInterface;
|
||||
public Boolean discoverAirPlayReceiver;
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.console;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.freebox.internal.handler.FreeboxHandler;
|
||||
import org.openhab.core.io.console.Console;
|
||||
import org.openhab.core.io.console.extensions.AbstractConsoleCommandExtension;
|
||||
import org.openhab.core.io.console.extensions.ConsoleCommandExtension;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingRegistry;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxCommandExtension} is responsible for handling console commands
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
|
||||
@NonNullByDefault
|
||||
@Component(service = ConsoleCommandExtension.class)
|
||||
public class FreeboxCommandExtension extends AbstractConsoleCommandExtension {
|
||||
|
||||
private static final String APP_TOKEN = "apptoken";
|
||||
|
||||
private final ThingRegistry thingRegistry;
|
||||
|
||||
@Activate
|
||||
public FreeboxCommandExtension(final @Reference ThingRegistry thingRegistry) {
|
||||
super("freebox", "Interact with the freebox binding.");
|
||||
this.thingRegistry = thingRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String[] args, Console console) {
|
||||
if (args.length == 2) {
|
||||
Thing thing = null;
|
||||
try {
|
||||
ThingUID thingUID = new ThingUID(args[0]);
|
||||
thing = thingRegistry.get(thingUID);
|
||||
} catch (IllegalArgumentException e) {
|
||||
thing = null;
|
||||
}
|
||||
ThingHandler thingHandler = null;
|
||||
FreeboxHandler handler = null;
|
||||
if (thing != null) {
|
||||
thingHandler = thing.getHandler();
|
||||
if (thingHandler instanceof FreeboxHandler) {
|
||||
handler = (FreeboxHandler) thingHandler;
|
||||
}
|
||||
}
|
||||
if (thing == null) {
|
||||
console.println("Bad thing id '" + args[0] + "'");
|
||||
printUsage(console);
|
||||
} else if (thingHandler == null) {
|
||||
console.println("No handler initialized for the thing id '" + args[0] + "'");
|
||||
printUsage(console);
|
||||
} else if (handler == null) {
|
||||
console.println("'" + args[0] + "' is not a freebox bridge id");
|
||||
printUsage(console);
|
||||
} else {
|
||||
switch (args[1]) {
|
||||
case APP_TOKEN:
|
||||
String token = handler.getAppToken();
|
||||
console.println("Your application token is " + (token != null ? token : "undefined"));
|
||||
break;
|
||||
default:
|
||||
printUsage(console);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printUsage(console);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUsages() {
|
||||
return Arrays.asList(buildCommandUsage("<bridgeUID> " + APP_TOKEN, "show the application token"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNull;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.freebox.internal.FreeboxBindingConstants;
|
||||
import org.openhab.binding.freebox.internal.FreeboxDataListener;
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiver;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHost;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHostL3Connectivity;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxAirPlayDeviceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxNetDeviceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxNetInterfaceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxServerConfiguration;
|
||||
import org.openhab.binding.freebox.internal.handler.FreeboxHandler;
|
||||
import org.openhab.core.config.discovery.AbstractDiscoveryService;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxDiscoveryService} is responsible for discovering all things
|
||||
* except the Freebox Server thing itself
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
* @author Laurent Garnier - add discovery settings
|
||||
* @author Laurent Garnier - use new internal API manager
|
||||
*/
|
||||
public class FreeboxDiscoveryService extends AbstractDiscoveryService implements FreeboxDataListener {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxDiscoveryService.class);
|
||||
|
||||
private static final int SEARCH_TIME = 10;
|
||||
|
||||
private static final String PHONE_ID = "wired";
|
||||
|
||||
private FreeboxHandler bridgeHandler;
|
||||
private boolean discoverPhone;
|
||||
private boolean discoverNetDevice;
|
||||
private boolean discoverNetInterface;
|
||||
private boolean discoverAirPlayReceiver;
|
||||
|
||||
/**
|
||||
* Creates a FreeboxDiscoveryService with background discovery disabled.
|
||||
*/
|
||||
public FreeboxDiscoveryService(FreeboxHandler freeboxBridgeHandler) {
|
||||
super(FreeboxBindingConstants.SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME, false);
|
||||
this.bridgeHandler = freeboxBridgeHandler;
|
||||
this.discoverPhone = true;
|
||||
this.discoverNetDevice = true;
|
||||
this.discoverNetInterface = true;
|
||||
this.discoverAirPlayReceiver = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activate(@Nullable Map<@NonNull String, @Nullable Object> configProperties) {
|
||||
super.activate(configProperties);
|
||||
applyConfig(configProperties);
|
||||
bridgeHandler.registerDataListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
bridgeHandler.unregisterDataListener(this);
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyConfig(Map<String, Object> configProperties) {
|
||||
if (configProperties != null) {
|
||||
Object property = configProperties.get(FreeboxServerConfiguration.DISCOVER_PHONE);
|
||||
if (property != null) {
|
||||
discoverPhone = ((Boolean) property).booleanValue();
|
||||
}
|
||||
property = configProperties.get(FreeboxServerConfiguration.DISCOVER_NET_DEVICE);
|
||||
if (property != null) {
|
||||
discoverNetDevice = ((Boolean) property).booleanValue();
|
||||
}
|
||||
property = configProperties.get(FreeboxServerConfiguration.DISCOVER_NET_INTERFACE);
|
||||
if (property != null) {
|
||||
discoverNetInterface = ((Boolean) property).booleanValue();
|
||||
}
|
||||
property = configProperties.get(FreeboxServerConfiguration.DISCOVER_AIRPLAY_RECEIVER);
|
||||
if (property != null) {
|
||||
discoverAirPlayReceiver = ((Boolean) property).booleanValue();
|
||||
}
|
||||
}
|
||||
logger.debug("Freebox discovery - discoverPhone : {}", discoverPhone);
|
||||
logger.debug("Freebox discovery - discoverNetDevice : {}", discoverNetDevice);
|
||||
logger.debug("Freebox discovery - discoverNetInterface : {}", discoverNetInterface);
|
||||
logger.debug("Freebox discovery - discoverAirPlayReceiver : {}", discoverAirPlayReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.debug("Starting Freebox discovery scan");
|
||||
if (bridgeHandler.getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
try {
|
||||
List<FreeboxLanHost> lanHosts = bridgeHandler.getApiManager().getLanHosts();
|
||||
List<FreeboxAirMediaReceiver> airPlayDevices = bridgeHandler.getApiManager().getAirMediaReceivers();
|
||||
onDataFetched(bridgeHandler.getThing().getUID(), lanHosts, airPlayDevices);
|
||||
} catch (FreeboxException e) {
|
||||
logger.warn("Error while requesting data for things discovery", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDataFetched(ThingUID bridge, List<FreeboxLanHost> lanHosts,
|
||||
List<FreeboxAirMediaReceiver> airPlayDevices) {
|
||||
if (bridge == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ThingUID thingUID;
|
||||
DiscoveryResult discoveryResult;
|
||||
|
||||
if (discoverPhone) {
|
||||
// Phone
|
||||
thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_PHONE, bridge, PHONE_ID);
|
||||
logger.trace("Adding new Freebox Phone {} to inbox", thingUID);
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withBridge(bridge).withLabel("Wired phone")
|
||||
.build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
|
||||
if (lanHosts != null && (discoverNetDevice || discoverNetInterface)) {
|
||||
// Network devices
|
||||
for (FreeboxLanHost host : lanHosts) {
|
||||
String mac = host.getMAC();
|
||||
String primaryName = host.getPrimaryName();
|
||||
String vendorName = host.getVendorName();
|
||||
if (mac != null && !mac.isEmpty()) {
|
||||
if (discoverNetDevice) {
|
||||
String uid = mac.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_NET_DEVICE, bridge, uid);
|
||||
String name = (primaryName == null || primaryName.isEmpty()) ? ("Freebox Network Device " + mac)
|
||||
: primaryName;
|
||||
logger.trace("Adding new Freebox Network Device {} to inbox", thingUID);
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
if (vendorName != null && !vendorName.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_VENDOR, vendorName);
|
||||
}
|
||||
properties.put(FreeboxNetDeviceConfiguration.MAC_ADDRESS, mac);
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridge).withLabel(name).build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
|
||||
// Network interfaces
|
||||
if (host.getL3Connectivities() != null && discoverNetInterface) {
|
||||
for (FreeboxLanHostL3Connectivity l3 : host.getL3Connectivities()) {
|
||||
String addr = l3.getAddr();
|
||||
if (addr != null && !addr.isEmpty()) {
|
||||
String uid = addr.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_NET_INTERFACE,
|
||||
bridge, uid);
|
||||
String name = addr;
|
||||
if (primaryName != null && !primaryName.isEmpty()) {
|
||||
name += " (" + (primaryName + ")");
|
||||
}
|
||||
logger.trace("Adding new Freebox Network Interface {} to inbox", thingUID);
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
if (vendorName != null && !vendorName.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_VENDOR, vendorName);
|
||||
}
|
||||
properties.put(FreeboxNetInterfaceConfiguration.IP_ADDRESS, addr);
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridge).withLabel(name).build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (airPlayDevices != null && discoverAirPlayReceiver) {
|
||||
// AirPlay devices
|
||||
for (FreeboxAirMediaReceiver device : airPlayDevices) {
|
||||
String name = device.getName();
|
||||
boolean videoCapable = device.isVideoCapable();
|
||||
logger.debug("AirPlay Device name {} video capable {}", name, videoCapable);
|
||||
// The Freebox API allows pushing media only to receivers with photo or video capabilities
|
||||
// but not to receivers with only audio capability; so receivers without video capability
|
||||
// are ignored by the discovery
|
||||
if (name != null && !name.isEmpty() && videoCapable) {
|
||||
String uid = name.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
thingUID = new ThingUID(FreeboxBindingConstants.FREEBOX_THING_TYPE_AIRPLAY, bridge, uid);
|
||||
logger.trace("Adding new Freebox AirPlay Device {} to inbox", thingUID);
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
properties.put(FreeboxAirPlayDeviceConfiguration.NAME, name);
|
||||
discoveryResult = DiscoveryResultBuilder.create(thingUID).withProperties(properties)
|
||||
.withBridge(bridge).withLabel(name + " (AirPlay)").build();
|
||||
thingDiscovered(discoveryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.discovery;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.jmdns.ServiceInfo;
|
||||
|
||||
import org.openhab.binding.freebox.internal.FreeboxBindingConstants;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxServerConfiguration;
|
||||
import org.openhab.core.config.discovery.DiscoveryResult;
|
||||
import org.openhab.core.config.discovery.DiscoveryResultBuilder;
|
||||
import org.openhab.core.config.discovery.mdns.MDNSDiscoveryParticipant;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxServerDiscoveryParticipant} is responsible for discovering
|
||||
* the Freebox Server (bridge) thing using mDNS discovery service
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@Component(immediate = true)
|
||||
public class FreeboxServerDiscoveryParticipant implements MDNSDiscoveryParticipant {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxServerDiscoveryParticipant.class);
|
||||
|
||||
private static final String SERVICE_TYPE = "_fbx-api._tcp.local.";
|
||||
|
||||
@Override
|
||||
public Set<ThingTypeUID> getSupportedThingTypeUIDs() {
|
||||
return FreeboxBindingConstants.SUPPORTED_BRIDGE_TYPES_UIDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServiceType() {
|
||||
return SERVICE_TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThingUID getThingUID(ServiceInfo service) {
|
||||
if ((service.getType() != null) && service.getType().equals(getServiceType())
|
||||
&& (service.getPropertyString("uid") != null)) {
|
||||
return new ThingUID(FreeboxBindingConstants.FREEBOX_BRIDGE_TYPE_SERVER,
|
||||
service.getPropertyString("uid").replaceAll("[^A-Za-z0-9_]", "_"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveryResult createResult(ServiceInfo service) {
|
||||
logger.debug("createResult ServiceInfo: {}", service);
|
||||
DiscoveryResult result = null;
|
||||
String ip = null;
|
||||
if (service.getHostAddresses() != null && service.getHostAddresses().length > 0
|
||||
&& !service.getHostAddresses()[0].isEmpty()) {
|
||||
ip = service.getHostAddresses()[0];
|
||||
}
|
||||
ThingUID thingUID = getThingUID(service);
|
||||
if (thingUID != null && ip != null) {
|
||||
logger.info("Created a DiscoveryResult for Freebox Server {} on IP {}", thingUID, ip);
|
||||
Map<String, Object> properties = new HashMap<>(1);
|
||||
properties.put(FreeboxServerConfiguration.FQDN, ip + ":" + service.getPort());
|
||||
properties.put(FreeboxServerConfiguration.USE_ONLY_HTTP, "true");
|
||||
if (service.getPropertyString("device_type") != null) {
|
||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, service.getPropertyString("device_type"));
|
||||
}
|
||||
if (service.getPropertyString("api_base_url") != null) {
|
||||
properties.put(FreeboxBindingConstants.API_BASE_URL, service.getPropertyString("api_base_url"));
|
||||
}
|
||||
if (service.getPropertyString("api_version") != null) {
|
||||
properties.put(FreeboxBindingConstants.API_VERSION, service.getPropertyString("api_version"));
|
||||
}
|
||||
result = DiscoveryResultBuilder.create(thingUID).withProperties(properties).withLabel(service.getName())
|
||||
.build();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,722 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freebox.internal.FreeboxBindingConstants.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.freebox.internal.FreeboxDataListener;
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxApiManager;
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiver;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxConnectionStatus;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxDiscoveryResponse;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHost;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLcdConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSambaConfig;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxSystemConfig;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxServerConfiguration;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.library.types.DecimalType;
|
||||
import org.openhab.core.library.types.IncreaseDecreaseType;
|
||||
import org.openhab.core.library.types.OnOffType;
|
||||
import org.openhab.core.library.types.OpenClosedType;
|
||||
import org.openhab.core.library.types.PercentType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.library.types.UpDownType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.binding.BaseBridgeHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.framework.FrameworkUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
* @author Laurent Garnier - updated to a bridge handler and delegate few things to another handler
|
||||
* @author Laurent Garnier - update discovery configuration
|
||||
* @author Laurent Garnier - use new internal API manager
|
||||
*/
|
||||
public class FreeboxHandler extends BaseBridgeHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxHandler.class);
|
||||
|
||||
private ScheduledFuture<?> authorizeJob;
|
||||
private ScheduledFuture<?> globalJob;
|
||||
private FreeboxApiManager apiManager;
|
||||
private long uptime;
|
||||
private List<FreeboxDataListener> dataListeners = new CopyOnWriteArrayList<>();
|
||||
private FreeboxServerConfiguration configuration;
|
||||
|
||||
public FreeboxHandler(Bridge bridge) {
|
||||
super(bridge);
|
||||
|
||||
Bundle bundle = FrameworkUtil.getBundle(getClass());
|
||||
String appId = bundle.getSymbolicName();
|
||||
String appName = bundle.getHeaders().get("Bundle-Name");
|
||||
String appVersion = String.format("%d.%d", bundle.getVersion().getMajor(), bundle.getVersion().getMinor());
|
||||
String deviceName = bundle.getHeaders().get("Bundle-Vendor");
|
||||
this.apiManager = new FreeboxApiManager(appId, appName, appVersion, deviceName);
|
||||
uptime = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
if (getThing().getStatus() == ThingStatus.UNKNOWN || (getThing().getStatus() == ThingStatus.OFFLINE
|
||||
&& getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR)) {
|
||||
return;
|
||||
}
|
||||
switch (channelUID.getId()) {
|
||||
case LCDBRIGHTNESS:
|
||||
setBrightness(channelUID, command);
|
||||
break;
|
||||
case LCDORIENTATION:
|
||||
setOrientation(channelUID, command);
|
||||
break;
|
||||
case LCDFORCED:
|
||||
setForced(channelUID, command);
|
||||
break;
|
||||
case WIFISTATUS:
|
||||
setWifiStatus(channelUID, command);
|
||||
break;
|
||||
case FTPSTATUS:
|
||||
setFtpStatus(channelUID, command);
|
||||
break;
|
||||
case AIRMEDIASTATUS:
|
||||
setAirMediaStatus(channelUID, command);
|
||||
break;
|
||||
case UPNPAVSTATUS:
|
||||
setUPnPAVStatus(channelUID, command);
|
||||
break;
|
||||
case SAMBAFILESTATUS:
|
||||
setSambaFileStatus(channelUID, command);
|
||||
break;
|
||||
case SAMBAPRINTERSTATUS:
|
||||
setSambaPrinterStatus(channelUID, command);
|
||||
break;
|
||||
case REBOOT:
|
||||
reboot(channelUID, command);
|
||||
break;
|
||||
default:
|
||||
logger.debug("Thing {}: unexpected command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("initializing Freebox Server handler for thing {}", getThing().getUID());
|
||||
|
||||
configuration = getConfigAs(FreeboxServerConfiguration.class);
|
||||
|
||||
// Update the discovery configuration
|
||||
Map<String, Object> configDiscovery = new HashMap<>();
|
||||
configDiscovery.put(FreeboxServerConfiguration.DISCOVER_PHONE, configuration.discoverPhone);
|
||||
configDiscovery.put(FreeboxServerConfiguration.DISCOVER_NET_DEVICE, configuration.discoverNetDevice);
|
||||
configDiscovery.put(FreeboxServerConfiguration.DISCOVER_NET_INTERFACE, configuration.discoverNetInterface);
|
||||
configDiscovery.put(FreeboxServerConfiguration.DISCOVER_AIRPLAY_RECEIVER,
|
||||
configuration.discoverAirPlayReceiver);
|
||||
for (FreeboxDataListener dataListener : dataListeners) {
|
||||
dataListener.applyConfig(configDiscovery);
|
||||
}
|
||||
|
||||
if (configuration.fqdn != null && !configuration.fqdn.isEmpty()) {
|
||||
if (configuration.appToken == null || configuration.appToken.isEmpty()) {
|
||||
updateStatus(ThingStatus.UNKNOWN, ThingStatusDetail.CONFIGURATION_PENDING,
|
||||
"Please accept pairing request directly on your freebox");
|
||||
} else {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
logger.debug("Binding will schedule a job to establish a connection...");
|
||||
if (authorizeJob == null || authorizeJob.isCancelled()) {
|
||||
authorizeJob = scheduler.schedule(this::authorize, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"Freebox Server FQDN not set in the thing configuration");
|
||||
}
|
||||
}
|
||||
|
||||
private void pollServerState() {
|
||||
logger.debug("Polling server state...");
|
||||
|
||||
boolean commOk = true;
|
||||
commOk &= fetchSystemConfig();
|
||||
commOk &= fetchLCDConfig();
|
||||
commOk &= fetchWifiConfig();
|
||||
commOk &= (fetchxDslStatus() || fetchFtthPresent());
|
||||
commOk &= fetchConnectionStatus();
|
||||
commOk &= fetchFtpConfig();
|
||||
commOk &= fetchAirMediaConfig();
|
||||
commOk &= fetchUPnPAVConfig();
|
||||
commOk &= fetchSambaConfig();
|
||||
List<FreeboxLanHost> lanHosts = fetchLanHosts();
|
||||
commOk &= (lanHosts != null);
|
||||
List<FreeboxAirMediaReceiver> airPlayDevices = fetchAirPlayDevices();
|
||||
commOk &= (airPlayDevices != null);
|
||||
|
||||
// Trigger a new discovery of things
|
||||
for (FreeboxDataListener dataListener : dataListeners) {
|
||||
dataListener.onDataFetched(getThing().getUID(), lanHosts, airPlayDevices);
|
||||
}
|
||||
|
||||
if (commOk) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
private void authorize() {
|
||||
logger.debug("Authorize job...");
|
||||
|
||||
String fqdn = configuration.fqdn;
|
||||
FreeboxDiscoveryResponse result = null;
|
||||
boolean httpsRequestOk = false;
|
||||
if (!Boolean.TRUE.equals(configuration.useOnlyHttp)) {
|
||||
result = apiManager.checkApi(fqdn, true);
|
||||
httpsRequestOk = (result != null);
|
||||
}
|
||||
if (!httpsRequestOk) {
|
||||
result = apiManager.checkApi(fqdn, false);
|
||||
}
|
||||
String apiBaseUrl = result == null ? null : result.getApiBaseUrl();
|
||||
String apiVersion = result == null ? null : result.getApiVersion();
|
||||
String deviceType = result == null ? null : result.getDeviceType();
|
||||
String apiDomain = result == null ? null : result.getApiDomain();
|
||||
Integer httpsPort = result == null ? null : result.getHttpsPort();
|
||||
boolean useHttps = false;
|
||||
String errorMsg = null;
|
||||
if (result == null) {
|
||||
errorMsg = "Can't connect to " + fqdn;
|
||||
} else if (apiBaseUrl == null || apiBaseUrl.isEmpty()) {
|
||||
errorMsg = fqdn + " does not deliver any API base URL";
|
||||
} else if (apiVersion == null || apiVersion.isEmpty()) {
|
||||
errorMsg = fqdn + " does not deliver any API version";
|
||||
} else if (Boolean.TRUE.equals(result.isHttpsAvailable()) && !Boolean.TRUE.equals(configuration.useOnlyHttp)) {
|
||||
if (httpsPort == null || apiDomain == null || apiDomain.isEmpty()) {
|
||||
if (httpsRequestOk) {
|
||||
useHttps = true;
|
||||
} else {
|
||||
logger.debug("{} does not deliver API domain or HTTPS port; use HTTP API", fqdn);
|
||||
}
|
||||
} else if (apiManager.checkApi(String.format("%s:%d", apiDomain, httpsPort), true) != null) {
|
||||
useHttps = true;
|
||||
fqdn = String.format("%s:%d", apiDomain, httpsPort);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorMsg != null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg);
|
||||
} else if (!apiManager.authorize(useHttps, fqdn, apiBaseUrl, apiVersion, configuration.appToken)) {
|
||||
if (configuration.appToken == null || configuration.appToken.isEmpty()) {
|
||||
errorMsg = "Pairing request rejected or timeout";
|
||||
} else {
|
||||
errorMsg = "Check your app token in the thing configuration; opening session with " + fqdn + " using "
|
||||
+ (useHttps ? "HTTPS" : "HTTP") + " API version " + apiVersion + " failed";
|
||||
}
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, errorMsg);
|
||||
} else {
|
||||
logger.debug("Thing {}: session opened with {} using {} API version {}", getThing().getUID(), fqdn,
|
||||
(useHttps ? "HTTPS" : "HTTP"), apiVersion);
|
||||
String appToken = apiManager.getAppToken();
|
||||
if ((configuration.appToken == null || configuration.appToken.isEmpty()) && appToken != null) {
|
||||
logger.debug("Store new app token in the thing configuration");
|
||||
configuration.appToken = appToken;
|
||||
Configuration thingConfig = editConfiguration();
|
||||
thingConfig.put(FreeboxServerConfiguration.APP_TOKEN, appToken);
|
||||
updateConfiguration(thingConfig);
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
if (globalJob == null || globalJob.isCancelled()) {
|
||||
long pollingInterval = configuration.refreshInterval;
|
||||
logger.debug("Scheduling server state update every {} seconds...", pollingInterval);
|
||||
globalJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
pollServerState();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Server state job failed: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}, 1, pollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String> properties = editProperties();
|
||||
if (apiBaseUrl != null && !apiBaseUrl.isEmpty()) {
|
||||
properties.put(API_BASE_URL, apiBaseUrl);
|
||||
}
|
||||
if (apiVersion != null && !apiVersion.isEmpty()) {
|
||||
properties.put(API_VERSION, apiVersion);
|
||||
}
|
||||
if (deviceType != null && !deviceType.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, deviceType);
|
||||
}
|
||||
updateProperties(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Disposing Freebox Server handler for thing {}", getThing().getUID());
|
||||
if (authorizeJob != null && !authorizeJob.isCancelled()) {
|
||||
authorizeJob.cancel(true);
|
||||
authorizeJob = null;
|
||||
}
|
||||
if (globalJob != null && !globalJob.isCancelled()) {
|
||||
globalJob.cancel(true);
|
||||
globalJob = null;
|
||||
}
|
||||
apiManager.closeSession();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
public FreeboxApiManager getApiManager() {
|
||||
return apiManager;
|
||||
}
|
||||
|
||||
public String getAppToken() {
|
||||
return configuration == null ? null : configuration.appToken;
|
||||
}
|
||||
|
||||
public boolean registerDataListener(FreeboxDataListener dataListener) {
|
||||
if (dataListener == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a null dataListener.");
|
||||
}
|
||||
return dataListeners.add(dataListener);
|
||||
}
|
||||
|
||||
public boolean unregisterDataListener(FreeboxDataListener dataListener) {
|
||||
if (dataListener == null) {
|
||||
throw new IllegalArgumentException("It's not allowed to pass a null dataListener.");
|
||||
}
|
||||
return dataListeners.remove(dataListener);
|
||||
}
|
||||
|
||||
private boolean fetchConnectionStatus() {
|
||||
try {
|
||||
FreeboxConnectionStatus connectionStatus = apiManager.getConnectionStatus();
|
||||
String state = connectionStatus.getState();
|
||||
if (state != null && !state.isEmpty()) {
|
||||
updateChannelStringState(LINESTATUS, state);
|
||||
}
|
||||
String ipv4 = connectionStatus.getIpv4();
|
||||
if (ipv4 != null && !ipv4.isEmpty()) {
|
||||
updateChannelStringState(IPV4, ipv4);
|
||||
}
|
||||
updateChannelDecimalState(RATEUP, connectionStatus.getRateUp());
|
||||
updateChannelDecimalState(RATEDOWN, connectionStatus.getRateDown());
|
||||
updateChannelDecimalState(BYTESUP, connectionStatus.getBytesUp());
|
||||
updateChannelDecimalState(BYTESDOWN, connectionStatus.getBytesDown());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchConnectionStatus: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchxDslStatus() {
|
||||
try {
|
||||
String status = apiManager.getxDslStatus();
|
||||
if (status != null && !status.isEmpty()) {
|
||||
updateChannelStringState(XDSLSTATUS, status);
|
||||
}
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchxDslStatus: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchFtthPresent() {
|
||||
try {
|
||||
boolean status = apiManager.getFtthPresent();
|
||||
updateChannelSwitchState(FTTHSTATUS, status);
|
||||
return status;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchxFtthStatus: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchWifiConfig() {
|
||||
try {
|
||||
updateChannelSwitchState(WIFISTATUS, apiManager.isWifiEnabled());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchWifiConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchFtpConfig() {
|
||||
try {
|
||||
updateChannelSwitchState(FTPSTATUS, apiManager.isFtpEnabled());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchFtpConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchAirMediaConfig() {
|
||||
try {
|
||||
if (!apiManager.isInLanBridgeMode()) {
|
||||
updateChannelSwitchState(AIRMEDIASTATUS, apiManager.isAirMediaEnabled());
|
||||
}
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchAirMediaConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchUPnPAVConfig() {
|
||||
try {
|
||||
if (!apiManager.isInLanBridgeMode()) {
|
||||
updateChannelSwitchState(UPNPAVSTATUS, apiManager.isUPnPAVEnabled());
|
||||
}
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchUPnPAVConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchSambaConfig() {
|
||||
try {
|
||||
FreeboxSambaConfig config = apiManager.getSambaConfig();
|
||||
updateChannelSwitchState(SAMBAFILESTATUS, config.isFileShareEnabled());
|
||||
updateChannelSwitchState(SAMBAPRINTERSTATUS, config.isPrintShareEnabled());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchSambaConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchLCDConfig() {
|
||||
try {
|
||||
FreeboxLcdConfig config = apiManager.getLcdConfig();
|
||||
updateChannelDecimalState(LCDBRIGHTNESS, config.getBrightness());
|
||||
updateChannelDecimalState(LCDORIENTATION, config.getOrientation());
|
||||
updateChannelSwitchState(LCDFORCED, config.isOrientationForced());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchLCDConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fetchSystemConfig() {
|
||||
try {
|
||||
FreeboxSystemConfig config = apiManager.getSystemConfig();
|
||||
Map<String, String> properties = editProperties();
|
||||
String value = config.getSerial();
|
||||
if (value != null && !value.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_SERIAL_NUMBER, value);
|
||||
}
|
||||
value = config.getBoardName();
|
||||
if (value != null && !value.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_HARDWARE_VERSION, value);
|
||||
}
|
||||
value = config.getFirmwareVersion();
|
||||
if (value != null && !value.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_FIRMWARE_VERSION, value);
|
||||
updateChannelStringState(FWVERSION, value);
|
||||
}
|
||||
value = config.getMac();
|
||||
if (value != null && !value.isEmpty()) {
|
||||
properties.put(Thing.PROPERTY_MAC_ADDRESS, value);
|
||||
}
|
||||
updateProperties(properties);
|
||||
|
||||
long newUptime = config.getUptimeVal();
|
||||
updateChannelSwitchState(RESTARTED, newUptime < uptime);
|
||||
uptime = newUptime;
|
||||
|
||||
updateChannelDecimalState(UPTIME, uptime);
|
||||
updateChannelDecimalState(TEMPCPUM, config.getTempCpum());
|
||||
updateChannelDecimalState(TEMPCPUB, config.getTempCpub());
|
||||
updateChannelDecimalState(TEMPSWITCH, config.getTempSw());
|
||||
updateChannelDecimalState(FANSPEED, config.getFanRpm());
|
||||
return true;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchSystemConfig: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized List<FreeboxLanHost> fetchLanHosts() {
|
||||
try {
|
||||
List<FreeboxLanHost> hosts = apiManager.getLanHosts();
|
||||
if (hosts == null) {
|
||||
hosts = new ArrayList<>();
|
||||
}
|
||||
|
||||
// The update of channels is delegated to each thing handler
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof FreeboxThingHandler) {
|
||||
((FreeboxThingHandler) handler).updateNetInfo(hosts);
|
||||
}
|
||||
}
|
||||
|
||||
return hosts;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchLanHosts: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized List<FreeboxAirMediaReceiver> fetchAirPlayDevices() {
|
||||
try {
|
||||
List<FreeboxAirMediaReceiver> devices = apiManager.getAirMediaReceivers();
|
||||
if (devices == null) {
|
||||
devices = new ArrayList<>();
|
||||
}
|
||||
|
||||
// The update of channels is delegated to each thing handler
|
||||
for (Thing thing : getThing().getThings()) {
|
||||
ThingHandler handler = thing.getHandler();
|
||||
if (handler instanceof FreeboxThingHandler) {
|
||||
((FreeboxThingHandler) handler).updateAirPlayDevice(devices);
|
||||
}
|
||||
}
|
||||
|
||||
return devices;
|
||||
} catch (FreeboxException e) {
|
||||
logger.debug("Thing {}: exception in fetchAirPlayDevices: {}", getThing().getUID(), e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void setBrightness(ChannelUID channelUID, Command command) {
|
||||
try {
|
||||
if (command instanceof IncreaseDecreaseType) {
|
||||
if (command == IncreaseDecreaseType.INCREASE) {
|
||||
updateChannelDecimalState(LCDBRIGHTNESS, apiManager.increaseLcdBrightness());
|
||||
} else {
|
||||
updateChannelDecimalState(LCDBRIGHTNESS, apiManager.decreaseLcdBrightness());
|
||||
}
|
||||
} else if (command instanceof OnOffType) {
|
||||
updateChannelDecimalState(LCDBRIGHTNESS,
|
||||
apiManager.setLcdBrightness((command == OnOffType.ON) ? 100 : 0));
|
||||
} else if (command instanceof DecimalType) {
|
||||
updateChannelDecimalState(LCDBRIGHTNESS,
|
||||
apiManager.setLcdBrightness(((DecimalType) command).intValue()));
|
||||
} else if (command instanceof PercentType) {
|
||||
updateChannelDecimalState(LCDBRIGHTNESS,
|
||||
apiManager.setLcdBrightness(((PercentType) command).intValue()));
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchLCDConfig();
|
||||
}
|
||||
}
|
||||
|
||||
private void setOrientation(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof DecimalType) {
|
||||
try {
|
||||
FreeboxLcdConfig config = apiManager.setLcdOrientation(((DecimalType) command).intValue());
|
||||
updateChannelDecimalState(LCDORIENTATION, config.getOrientation());
|
||||
updateChannelSwitchState(LCDFORCED, config.isOrientationForced());
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchLCDConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setForced(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
updateChannelSwitchState(LCDFORCED, apiManager.setLcdOrientationForced(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchLCDConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setWifiStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
updateChannelSwitchState(WIFISTATUS, apiManager.enableWifi(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchWifiConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setFtpStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
updateChannelSwitchState(FTPSTATUS, apiManager.enableFtp(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchFtpConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setAirMediaStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
if (!apiManager.isInLanBridgeMode()) {
|
||||
updateChannelSwitchState(AIRMEDIASTATUS, apiManager.enableAirMedia(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} else {
|
||||
logger.debug("Thing {}: command {} from channel {} unavailable when in bridge mode",
|
||||
getThing().getUID(), command, channelUID.getId());
|
||||
}
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchAirMediaConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setUPnPAVStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
if (!apiManager.isInLanBridgeMode()) {
|
||||
updateChannelSwitchState(UPNPAVSTATUS, apiManager.enableUPnPAV(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} else {
|
||||
logger.debug("Thing {}: command {} from channel {} unavailable when in bridge mode",
|
||||
getThing().getUID(), command, channelUID.getId());
|
||||
}
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchUPnPAVConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setSambaFileStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
updateChannelSwitchState(SAMBAFILESTATUS, apiManager.enableSambaFileShare(command.equals(OnOffType.ON)
|
||||
|| command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)));
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchSambaConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setSambaPrinterStatus(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType || command instanceof OpenClosedType || command instanceof UpDownType) {
|
||||
try {
|
||||
updateChannelSwitchState(SAMBAPRINTERSTATUS,
|
||||
apiManager.enableSambaPrintShare(command.equals(OnOffType.ON) || command.equals(UpDownType.UP)
|
||||
|| command.equals(OpenClosedType.OPEN)));
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
fetchSambaConfig();
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void reboot(ChannelUID channelUID, Command command) {
|
||||
if (command.equals(OnOffType.ON) || command.equals(UpDownType.UP) || command.equals(OpenClosedType.OPEN)) {
|
||||
try {
|
||||
apiManager.reboot();
|
||||
} catch (FreeboxException e) {
|
||||
logCommandException(e, channelUID, command);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChannelStringState(String channel, String state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), channel), new StringType(state));
|
||||
}
|
||||
|
||||
private void updateChannelSwitchState(String channel, boolean state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), channel), state ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
private void updateChannelDecimalState(String channel, int state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), channel), new DecimalType(state));
|
||||
}
|
||||
|
||||
private void updateChannelDecimalState(String channel, long state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), channel), new DecimalType(state));
|
||||
}
|
||||
|
||||
public void logCommandException(FreeboxException e, ChannelUID channelUID, Command command) {
|
||||
if (e.isMissingRights()) {
|
||||
logger.debug("Thing {}: missing right {} while handling command {} from channel {}", getThing().getUID(),
|
||||
e.getResponse().getMissingRight(), command, channelUID.getId());
|
||||
} else {
|
||||
logger.debug("Thing {}: error while handling command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,425 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.handler;
|
||||
|
||||
import static org.openhab.binding.freebox.internal.FreeboxBindingConstants.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.openhab.binding.freebox.internal.api.FreeboxException;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxAirMediaReceiver;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxCallEntry;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHost;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxLanHostL3Connectivity;
|
||||
import org.openhab.binding.freebox.internal.api.model.FreeboxPhoneStatus;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxAirPlayDeviceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxNetDeviceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxNetInterfaceConfiguration;
|
||||
import org.openhab.binding.freebox.internal.config.FreeboxPhoneConfiguration;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
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.StringType;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.ChannelUID;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingStatus;
|
||||
import org.openhab.core.thing.ThingStatusDetail;
|
||||
import org.openhab.core.thing.ThingStatusInfo;
|
||||
import org.openhab.core.thing.binding.BaseThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The {@link FreeboxThingHandler} is responsible for handling everything associated to
|
||||
* any Freebox thing types except the bridge thing type.
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
* @author Laurent Garnier - use new internal API manager
|
||||
*/
|
||||
public class FreeboxThingHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(FreeboxThingHandler.class);
|
||||
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
|
||||
private ScheduledFuture<?> phoneJob;
|
||||
private ScheduledFuture<?> callsJob;
|
||||
private FreeboxHandler bridgeHandler;
|
||||
private Calendar lastPhoneCheck;
|
||||
private String netAddress;
|
||||
private String airPlayName;
|
||||
private String airPlayPassword;
|
||||
|
||||
public FreeboxThingHandler(Thing thing, TimeZoneProvider timeZoneProvider) {
|
||||
super(thing);
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
return;
|
||||
}
|
||||
if (getThing().getStatus() == ThingStatus.UNKNOWN || (getThing().getStatus() == ThingStatus.OFFLINE
|
||||
&& (getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_OFFLINE
|
||||
|| getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.BRIDGE_UNINITIALIZED
|
||||
|| getThing().getStatusInfo().getStatusDetail() == ThingStatusDetail.CONFIGURATION_ERROR))) {
|
||||
return;
|
||||
}
|
||||
if (bridgeHandler == null) {
|
||||
return;
|
||||
}
|
||||
switch (channelUID.getId()) {
|
||||
case PLAYURL:
|
||||
playMedia(channelUID, command);
|
||||
break;
|
||||
case STOP:
|
||||
stopMedia(channelUID, command);
|
||||
break;
|
||||
default:
|
||||
logger.debug("Thing {}: unexpected command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("initializing handler for thing {}", getThing().getUID());
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
initializeThing(null, null);
|
||||
} else {
|
||||
initializeThing(bridge.getHandler(), bridge.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bridgeStatusChanged(ThingStatusInfo bridgeStatusInfo) {
|
||||
logger.debug("bridgeStatusChanged {}", bridgeStatusInfo);
|
||||
Bridge bridge = getBridge();
|
||||
if (bridge == null) {
|
||||
initializeThing(null, bridgeStatusInfo.getStatus());
|
||||
} else {
|
||||
initializeThing(bridge.getHandler(), bridgeStatusInfo.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeThing(ThingHandler bridgeHandler, ThingStatus bridgeStatus) {
|
||||
if (bridgeHandler != null && bridgeStatus != null) {
|
||||
if (bridgeStatus == ThingStatus.ONLINE) {
|
||||
this.bridgeHandler = (FreeboxHandler) bridgeHandler;
|
||||
|
||||
if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_PHONE)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
lastPhoneCheck = Calendar.getInstance();
|
||||
if (phoneJob == null || phoneJob.isCancelled()) {
|
||||
long pollingInterval = getConfigAs(FreeboxPhoneConfiguration.class).refreshPhoneInterval;
|
||||
if (pollingInterval > 0) {
|
||||
logger.debug("Scheduling phone state job every {} seconds...", pollingInterval);
|
||||
phoneJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
pollPhoneState();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Phone state job failed: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
e.getMessage());
|
||||
}
|
||||
}, 1, pollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
if (callsJob == null || callsJob.isCancelled()) {
|
||||
long pollingInterval = getConfigAs(FreeboxPhoneConfiguration.class).refreshPhoneCallsInterval;
|
||||
if (pollingInterval > 0) {
|
||||
logger.debug("Scheduling phone calls job every {} seconds...", pollingInterval);
|
||||
callsJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
try {
|
||||
pollPhoneCalls();
|
||||
} catch (Exception e) {
|
||||
logger.debug("Phone calls job failed: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||
e.getMessage());
|
||||
}
|
||||
}, 1, pollingInterval, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
} else if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_DEVICE)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
netAddress = getConfigAs(FreeboxNetDeviceConfiguration.class).macAddress;
|
||||
netAddress = (netAddress == null) ? "" : netAddress;
|
||||
} else if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_INTERFACE)) {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
netAddress = getConfigAs(FreeboxNetInterfaceConfiguration.class).ipAddress;
|
||||
netAddress = (netAddress == null) ? "" : netAddress;
|
||||
} else if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_AIRPLAY)) {
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
airPlayName = getConfigAs(FreeboxAirPlayDeviceConfiguration.class).name;
|
||||
airPlayName = (airPlayName == null) ? "" : airPlayName;
|
||||
airPlayPassword = getConfigAs(FreeboxAirPlayDeviceConfiguration.class).password;
|
||||
airPlayPassword = (airPlayPassword == null) ? "" : airPlayPassword;
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_UNINITIALIZED);
|
||||
}
|
||||
}
|
||||
|
||||
private void pollPhoneState() {
|
||||
logger.debug("Polling phone state...");
|
||||
try {
|
||||
FreeboxPhoneStatus phoneStatus = bridgeHandler.getApiManager().getPhoneStatus();
|
||||
updateGroupChannelSwitchState(STATE, ONHOOK, phoneStatus.isOnHook());
|
||||
updateGroupChannelSwitchState(STATE, RINGING, phoneStatus.isRinging());
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (FreeboxException e) {
|
||||
if (e.isMissingRights()) {
|
||||
logger.debug("Phone state job: missing right {}", e.getResponse().getMissingRight());
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
logger.debug("Phone state job failed: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void pollPhoneCalls() {
|
||||
logger.debug("Polling phone calls...");
|
||||
try {
|
||||
List<FreeboxCallEntry> callEntries = bridgeHandler.getApiManager().getCallEntries();
|
||||
if (callEntries != null) {
|
||||
PhoneCallComparator comparator = new PhoneCallComparator();
|
||||
Collections.sort(callEntries, comparator);
|
||||
|
||||
for (FreeboxCallEntry call : callEntries) {
|
||||
Calendar callEndTime = call.getTimeStamp();
|
||||
callEndTime.add(Calendar.SECOND, call.getDuration());
|
||||
if ((call.getDuration() > 0) && callEndTime.after(lastPhoneCheck)) {
|
||||
updateCall(call, ANY);
|
||||
|
||||
if (call.isAccepted()) {
|
||||
updateCall(call, ACCEPTED);
|
||||
} else if (call.isMissed()) {
|
||||
updateCall(call, MISSED);
|
||||
} else if (call.isOutGoing()) {
|
||||
updateCall(call, OUTGOING);
|
||||
}
|
||||
|
||||
lastPhoneCheck = callEndTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} catch (FreeboxException e) {
|
||||
if (e.isMissingRights()) {
|
||||
logger.debug("Phone calls job: missing right {}", e.getResponse().getMissingRight());
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
logger.debug("Phone calls job failed: {}", e.getMessage(), e);
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Disposing handler for thing {}", getThing().getUID());
|
||||
if (phoneJob != null && !phoneJob.isCancelled()) {
|
||||
phoneJob.cancel(true);
|
||||
phoneJob = null;
|
||||
}
|
||||
if (callsJob != null && !callsJob.isCancelled()) {
|
||||
callsJob.cancel(true);
|
||||
callsJob = null;
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
private void updateCall(FreeboxCallEntry call, String channelGroup) {
|
||||
if (channelGroup != null) {
|
||||
updateGroupChannelStringState(channelGroup, CALLNUMBER, call.getNumber());
|
||||
updateGroupChannelDecimalState(channelGroup, CALLDURATION, call.getDuration());
|
||||
ZonedDateTime zoned = ZonedDateTime.ofInstant(Instant.ofEpochMilli(call.getTimeStamp().getTimeInMillis()),
|
||||
timeZoneProvider.getTimeZone());
|
||||
updateGroupChannelDateTimeState(channelGroup, CALLTIMESTAMP, zoned);
|
||||
updateGroupChannelStringState(channelGroup, CALLNAME, call.getName());
|
||||
if (channelGroup.equals(ANY)) {
|
||||
updateGroupChannelStringState(channelGroup, CALLSTATUS, call.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateNetInfo(List<FreeboxLanHost> hosts) {
|
||||
if (!getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_DEVICE)
|
||||
&& !getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_INTERFACE)) {
|
||||
return;
|
||||
}
|
||||
if (getThing().getStatus() != ThingStatus.ONLINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean found = false;
|
||||
boolean reachable = false;
|
||||
String vendor = null;
|
||||
if (hosts != null) {
|
||||
for (FreeboxLanHost host : hosts) {
|
||||
if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_DEVICE)
|
||||
&& netAddress.equals(host.getMAC())) {
|
||||
found = true;
|
||||
reachable = host.isReachable();
|
||||
vendor = host.getVendorName();
|
||||
break;
|
||||
}
|
||||
if (host.getL3Connectivities() != null) {
|
||||
for (FreeboxLanHostL3Connectivity l3 : host.getL3Connectivities()) {
|
||||
if (getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_NET_INTERFACE)
|
||||
&& netAddress.equals(l3.getAddr())) {
|
||||
found = true;
|
||||
if (l3.isReachable()) {
|
||||
reachable = true;
|
||||
vendor = host.getVendorName();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
updateState(new ChannelUID(getThing().getUID(), REACHABLE), reachable ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
if (vendor != null && !vendor.isEmpty()) {
|
||||
updateProperty(Thing.PROPERTY_VENDOR, vendor);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAirPlayDevice(List<FreeboxAirMediaReceiver> receivers) {
|
||||
if (!getThing().getThingTypeUID().equals(FREEBOX_THING_TYPE_AIRPLAY)) {
|
||||
return;
|
||||
}
|
||||
if (airPlayName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The Freebox API allows pushing media only to receivers with photo or video capabilities
|
||||
// but not to receivers with only audio capability
|
||||
boolean found = false;
|
||||
boolean usable = false;
|
||||
if (receivers != null) {
|
||||
for (FreeboxAirMediaReceiver receiver : receivers) {
|
||||
if (airPlayName.equals(receiver.getName())) {
|
||||
found = true;
|
||||
usable = receiver.isVideoCapable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "AirPlay device not found");
|
||||
} else if (!usable) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"AirPlay device without video capability");
|
||||
} else {
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
}
|
||||
|
||||
public void playMedia(String url) throws FreeboxException {
|
||||
if (bridgeHandler != null && url != null) {
|
||||
stopMedia();
|
||||
bridgeHandler.getApiManager().playMedia(url, airPlayName, airPlayPassword);
|
||||
}
|
||||
}
|
||||
|
||||
private void playMedia(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof StringType) {
|
||||
try {
|
||||
playMedia(command.toString());
|
||||
} catch (FreeboxException e) {
|
||||
bridgeHandler.logCommandException(e, channelUID, command);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void stopMedia() throws FreeboxException {
|
||||
if (bridgeHandler != null) {
|
||||
bridgeHandler.getApiManager().stopMedia(airPlayName, airPlayPassword);
|
||||
}
|
||||
}
|
||||
|
||||
private void stopMedia(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof OnOffType) {
|
||||
try {
|
||||
stopMedia();
|
||||
} catch (FreeboxException e) {
|
||||
bridgeHandler.logCommandException(e, channelUID, command);
|
||||
}
|
||||
} else {
|
||||
logger.debug("Thing {}: invalid command {} from channel {}", getThing().getUID(), command,
|
||||
channelUID.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateGroupChannelSwitchState(String group, String channel, boolean state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), group, channel), state ? OnOffType.ON : OnOffType.OFF);
|
||||
}
|
||||
|
||||
private void updateGroupChannelStringState(String group, String channel, String state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), group, channel), new StringType(state));
|
||||
}
|
||||
|
||||
private void updateGroupChannelDecimalState(String group, String channel, int state) {
|
||||
updateState(new ChannelUID(getThing().getUID(), group, channel), new DecimalType(state));
|
||||
}
|
||||
|
||||
private void updateGroupChannelDateTimeState(String group, String channel, ZonedDateTime zonedDateTime) {
|
||||
updateState(new ChannelUID(getThing().getUID(), group, channel), new DateTimeType(zonedDateTime));
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparator of phone calls by ascending end date and time
|
||||
*/
|
||||
private class PhoneCallComparator implements Comparator<FreeboxCallEntry> {
|
||||
|
||||
@Override
|
||||
public int compare(FreeboxCallEntry call1, FreeboxCallEntry call2) {
|
||||
int result = 0;
|
||||
Calendar callEndTime1 = call1.getTimeStamp();
|
||||
callEndTime1.add(Calendar.SECOND, call1.getDuration());
|
||||
Calendar callEndTime2 = call2.getTimeStamp();
|
||||
callEndTime2.add(Calendar.SECOND, call2.getDuration());
|
||||
if (callEndTime1.before(callEndTime2)) {
|
||||
result = -1;
|
||||
} else if (callEndTime1.after(callEndTime2)) {
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="freebox" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:binding="https://openhab.org/schemas/binding/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/binding/v1.0.0 https://openhab.org/schemas/binding-1.0.0.xsd">
|
||||
|
||||
<name>Freebox Binding</name>
|
||||
<description>The Freebox binding requests your Freebox Server for various operational informations.</description>
|
||||
<author>Gaël L'hopital</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,571 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="freebox"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:thing="https://openhab.org/schemas/thing-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/thing-description/v1.0.0 https://openhab.org/schemas/thing-description-1.0.0.xsd">
|
||||
|
||||
<bridge-type id="server">
|
||||
<label>Freebox Server</label>
|
||||
<description>Provides various informations regarding the status of the Freebox Server</description>
|
||||
|
||||
<channels>
|
||||
<channel id="fwversion" typeId="fwversion"/>
|
||||
<channel id="uptime" typeId="uptime"/>
|
||||
<channel id="restarted" typeId="restarted"/>
|
||||
<channel id="tempcpum" typeId="tempcpum"/>
|
||||
<channel id="tempcpub" typeId="tempcpub"/>
|
||||
<channel id="tempswitch" typeId="tempswitch"/>
|
||||
<channel id="fanspeed" typeId="fanspeed"/>
|
||||
<channel id="reboot" typeId="reboot"/>
|
||||
<channel id="lcd_brightness" typeId="lcd_brightness"/>
|
||||
<channel id="lcd_orientation" typeId="lcd_orientation"/>
|
||||
<channel id="lcd_forced" typeId="lcd_forced"/>
|
||||
<channel id="wifi_status" typeId="wifi_status"/>
|
||||
<channel id="ftp_status" typeId="ftp_status"/>
|
||||
<channel id="airmedia_status" typeId="airmedia_status"/>
|
||||
<channel id="upnpav_status" typeId="upnpav_status"/>
|
||||
<channel id="sambafileshare_status" typeId="sambafileshare_status"/>
|
||||
<channel id="sambaprintershare_status" typeId="sambaprintershare_status"/>
|
||||
<channel id="xdsl_status" typeId="xdsl_status"/>
|
||||
<channel id="ftth_status" typeId="ftth_status"/>
|
||||
<channel id="line_status" typeId="line_status"/>
|
||||
<channel id="ipv4" typeId="ipv4"/>
|
||||
<channel id="rate_up" typeId="rate_up"/>
|
||||
<channel id="rate_down" typeId="rate_down"/>
|
||||
<channel id="bytes_up" typeId="bytes_up"/>
|
||||
<channel id="bytes_down" typeId="bytes_down"/>
|
||||
</channels>
|
||||
|
||||
<properties>
|
||||
<property name="vendor">Freebox SAS</property>
|
||||
</properties>
|
||||
|
||||
<config-description>
|
||||
<parameter name="fqdn" type="text">
|
||||
<label>Freebox Server FQDN</label>
|
||||
<context>network-address</context>
|
||||
<description>The IP address / FQDN of the Freebox Server (can include port number)</description>
|
||||
<default>mafreebox.freebox.fr</default>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
|
||||
<parameter name="appToken" type="text">
|
||||
<label>Application Token</label>
|
||||
<context>password</context>
|
||||
<description>Token generated by the Freebox server</description>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
|
||||
<parameter name="refreshInterval" type="integer" min="1" unit="s">
|
||||
<label>Refresh Interval</label>
|
||||
<description>The refresh interval in seconds which is used to poll given Freebox Server</description>
|
||||
<default>30</default>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
|
||||
<parameter name="useOnlyHttp" type="boolean">
|
||||
<label>Use Only HTTP API</label>
|
||||
<description>Use HTTP API even if HTTPS is available</description>
|
||||
<default>false</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
<parameter name="discoverPhone" type="boolean">
|
||||
<label>Enable Phone Discovery</label>
|
||||
<description>Enable the discovery of phone things</description>
|
||||
<default>true</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
<parameter name="discoverNetDevice" type="boolean">
|
||||
<label>Enable Network Device Discovery</label>
|
||||
<description>Enable the discovery of network device things</description>
|
||||
<default>true</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
<parameter name="discoverNetInterface" type="boolean">
|
||||
<label>Enable Network Interface Discovery</label>
|
||||
<description>Enable the discovery of network interface things</description>
|
||||
<default>true</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
<parameter name="discoverAirPlayReceiver" type="boolean">
|
||||
<label>Enable AirPlay Receiver Discovery</label>
|
||||
<description>Enable the discovery of AirPlay receiver things</description>
|
||||
<default>true</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
</bridge-type>
|
||||
|
||||
<thing-type id="phone">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="server"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Phone</label>
|
||||
<description>Provides various informations regarding the phone state and the phone calls</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="state" typeId="state"/>
|
||||
<channel-group id="any" typeId="any"/>
|
||||
<channel-group id="accepted" typeId="accepted"/>
|
||||
<channel-group id="missed" typeId="missed"/>
|
||||
<channel-group id="outgoing" typeId="outgoing"/>
|
||||
</channel-groups>
|
||||
|
||||
<config-description>
|
||||
<parameter name="refreshPhoneInterval" type="integer" min="0" unit="s">
|
||||
<label>Phone State Refresh Interval</label>
|
||||
<description>The refresh interval in seconds which is used to poll given Freebox Server for phone state</description>
|
||||
<default>2</default>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
|
||||
<parameter name="refreshPhoneCallsInterval" type="integer" min="0" unit="s">
|
||||
<label>Phone Calls Refresh Interval</label>
|
||||
<description>The refresh interval in seconds which is used to poll given Freebox Server for phone calls</description>
|
||||
<default>60</default>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="net_device">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="server"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Network Device</label>
|
||||
<description>Provides network device reachability</description>
|
||||
|
||||
<channels>
|
||||
<channel id="reachable" typeId="reachable"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="macAddress" type="text">
|
||||
<label>MAC Address</label>
|
||||
<description>The MAC address of the network device</description>
|
||||
<default></default>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="net_interface">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="server"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>Network Interface</label>
|
||||
<description>Provides network interface reachability</description>
|
||||
|
||||
<channels>
|
||||
<channel id="reachable" typeId="reachable"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="ipAddress" type="text">
|
||||
<label>IP Address</label>
|
||||
<description>The IP address (v4 or v6) of the network interface</description>
|
||||
<default></default>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<thing-type id="airplay">
|
||||
<supported-bridge-type-refs>
|
||||
<bridge-type-ref id="server"/>
|
||||
</supported-bridge-type-refs>
|
||||
|
||||
<label>AirPlay Receiver</label>
|
||||
<description>Provides media control from one AirPlay device</description>
|
||||
|
||||
<channels>
|
||||
<channel id="playurl" typeId="playurl"/>
|
||||
<channel id="stop" typeId="stop"/>
|
||||
</channels>
|
||||
|
||||
<config-description>
|
||||
<parameter name="name" type="text">
|
||||
<label>Name</label>
|
||||
<description>Name of the AirPlay device</description>
|
||||
<required>true</required>
|
||||
</parameter>
|
||||
<parameter name="password" type="text">
|
||||
<context>password</context>
|
||||
<label>Password</label>
|
||||
<description>AirPlay password</description>
|
||||
<default></default>
|
||||
<required>false</required>
|
||||
</parameter>
|
||||
<parameter name="acceptAllMp3" type="boolean">
|
||||
<label>Accept All MP3</label>
|
||||
<description>Accept any bitrate for MP3 audio or only bitrates greater than 64 kbps</description>
|
||||
<default>true</default>
|
||||
<required>false</required>
|
||||
<advanced>true</advanced>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
<channel-group-type id="state">
|
||||
<label>Phone</label>
|
||||
<description>The phone state</description>
|
||||
<channels>
|
||||
<channel id="onhook" typeId="onhook"/>
|
||||
<channel id="ringing" typeId="ringing"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="any">
|
||||
<label>Call</label>
|
||||
<description>The last phone call</description>
|
||||
<channels>
|
||||
<channel id="call_number" typeId="call_number"/>
|
||||
<channel id="call_duration" typeId="call_duration"/>
|
||||
<channel id="call_timestamp" typeId="call_timestamp"/>
|
||||
<channel id="call_status" typeId="call_status"/>
|
||||
<channel id="call_name" typeId="call_name"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="accepted">
|
||||
<label>Accepted Call</label>
|
||||
<description>The last accepted phone call</description>
|
||||
<channels>
|
||||
<channel id="call_number" typeId="caller_number"/>
|
||||
<channel id="call_duration" typeId="call_duration"/>
|
||||
<channel id="call_timestamp" typeId="call_timestamp"/>
|
||||
<channel id="call_name" typeId="caller_name"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="missed">
|
||||
<label>Missed Call</label>
|
||||
<description>The last missed phone call</description>
|
||||
<channels>
|
||||
<channel id="call_number" typeId="caller_number"/>
|
||||
<channel id="call_duration" typeId="call_duration"/>
|
||||
<channel id="call_timestamp" typeId="call_timestamp"/>
|
||||
<channel id="call_name" typeId="caller_name"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="outgoing">
|
||||
<label>Outgoing Call</label>
|
||||
<description>The last outgoing phone call</description>
|
||||
<channels>
|
||||
<channel id="call_number" typeId="called_number"/>
|
||||
<channel id="call_duration" typeId="call_duration"/>
|
||||
<channel id="call_timestamp" typeId="call_timestamp"/>
|
||||
<channel id="call_name" typeId="called_name"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-type id="fwversion" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>Firmware Version</label>
|
||||
<description>Version of the Freebox Server Firmware</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="uptime" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Server Uptime</label>
|
||||
<description>Time since last reboot of the Freebox Server</description>
|
||||
<state readOnly="true" pattern="%d s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="restarted" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Just Restarted</label>
|
||||
<description>Has the Freebox server have restarted during the last poll period</description>
|
||||
<category>Alarm</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="reboot">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Reboot Freebox</label>
|
||||
<description>Reboots the Freebox server</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="tempcpum" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>CPUm Temperature</label>
|
||||
<description>Actual measured CPU Marvell temperature of the Freebox Server</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%d °C"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="tempcpub" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>CPUb Temperature</label>
|
||||
<description>Actual measured CPU Broadcom (xDSL) temperature of the Freebox Server</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%d °C"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="tempswitch" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Switch Temperature</label>
|
||||
<description>Actual measured switch temperature of the Freebox Server</description>
|
||||
<category>Temperature</category>
|
||||
<state readOnly="true" pattern="%d °C"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="fanspeed" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Fan Speed</label>
|
||||
<description>Actual measured fan speed (rpm) of the Freebox Server</description>
|
||||
<state readOnly="true" pattern="%d rpm"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lcd_brightness" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Screen Brightness</label>
|
||||
<description>Brightness level of the screen in percent</description>
|
||||
<category>DimmableLight</category>
|
||||
<state pattern="%d %%"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lcd_orientation">
|
||||
<item-type>Number</item-type>
|
||||
<label>Screen Orientation</label>
|
||||
<description>Screen Orientation in degrees</description>
|
||||
<state pattern="%d °">
|
||||
<options>
|
||||
<option value="0">Horizontal</option>
|
||||
<option value="90">Turned left</option>
|
||||
<option value="180">Reversed</option>
|
||||
<option value="270">Turned right</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="lcd_forced" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Forced Orientation</label>
|
||||
<description>Indicates whether the screen orientation forced</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="wifi_status">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Wifi Enabled</label>
|
||||
<description>Indicates whether the wifi network is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ftp_status" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>FTP Server Enabled</label>
|
||||
<description>Indicates whether the FTP server is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="airmedia_status" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Air Media Enabled</label>
|
||||
<description>Indicates whether Air Media is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="upnpav_status" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>UPnP AV Enabled</label>
|
||||
<description>Indicates whether UPnP AV is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="sambafileshare_status" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Window File Sharing Enabled</label>
|
||||
<description>Indicates whether Window File Sharing is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="sambaprintershare_status" advanced="true">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Window Printer Sharing Enabled</label>
|
||||
<description>Indicates whether Window Printer Sharing is enabled</description>
|
||||
<category>Switch</category>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="xdsl_status">
|
||||
<item-type>String</item-type>
|
||||
<label>xDSL Status</label>
|
||||
<description>Status of the xDSL line</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ftth_status">
|
||||
<item-type>Switch</item-type>
|
||||
<label>FTTH Status</label>
|
||||
<description>Status of the Fiber Optic line</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="line_status">
|
||||
<item-type>String</item-type>
|
||||
<label>Line Status</label>
|
||||
<description>Status of network line connexion</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ipv4" advanced="true">
|
||||
<item-type>String</item-type>
|
||||
<label>IP Address</label>
|
||||
<description>Public IP Address of the Freebox Server</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="rate_up" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Upload Rate</label>
|
||||
<description>Current upload rate in byte/s</description>
|
||||
<state readOnly="true" pattern="%d b/s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="rate_down" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Download Rate</label>
|
||||
<description>Current download rate in byte/s</description>
|
||||
<state readOnly="true" pattern="%d b/s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="bytes_up" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Uploaded</label>
|
||||
<description>Total uploaded bytes since last connection</description>
|
||||
<state readOnly="true" pattern="%d bytes"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="bytes_down" advanced="true">
|
||||
<item-type>Number</item-type>
|
||||
<label>Downloaded</label>
|
||||
<description>Total downloaded bytes since last connection</description>
|
||||
<state readOnly="true" pattern="%d bytes"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="onhook">
|
||||
<item-type>Switch</item-type>
|
||||
<label>On-hook</label>
|
||||
<description>Indicates whether the phone is on hook</description>
|
||||
<category>Switch</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="ringing">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Ringing</label>
|
||||
<description>Is the phone ringing</description>
|
||||
<category>Alarm</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="call_number">
|
||||
<item-type>String</item-type>
|
||||
<label>Phone Number</label>
|
||||
<description>Called number for outgoing calls. Caller number for incoming calls</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="called_number">
|
||||
<item-type>String</item-type>
|
||||
<label>Phone Number</label>
|
||||
<description>Called number</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="caller_number">
|
||||
<item-type>String</item-type>
|
||||
<label>Phone Number</label>
|
||||
<description>Caller number</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="call_duration">
|
||||
<item-type>Number</item-type>
|
||||
<label>Duration</label>
|
||||
<description>Call duration in seconds</description>
|
||||
<state readOnly="true" pattern="%d s"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="call_timestamp">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Timestamp</label>
|
||||
<description>Call creation timestamp</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="call_status">
|
||||
<item-type>String</item-type>
|
||||
<label>Call Type</label>
|
||||
<description>Call Type (ingoing, outgoing, missed)</description>
|
||||
<state readOnly="true">
|
||||
<options>
|
||||
<option value="ingoing">Ingoing call</option>
|
||||
<option value="outgoing">Outgoing call</option>
|
||||
<option value="missing">Missed call</option>
|
||||
</options>
|
||||
</state>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="call_name">
|
||||
<item-type>String</item-type>
|
||||
<label>Call Name</label>
|
||||
<description>Called name for outgoing calls. Caller name for incoming calls</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="called_name">
|
||||
<item-type>String</item-type>
|
||||
<label>Called Name</label>
|
||||
<description>Called name</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="caller_name">
|
||||
<item-type>String</item-type>
|
||||
<label>Caller Name</label>
|
||||
<description>Caller name</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="reachable">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Reachable</label>
|
||||
<description>Indicates whether the network device is reachable</description>
|
||||
<category>Switch</category>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="playurl">
|
||||
<item-type>String</item-type>
|
||||
<label>Play Audio or Video URL</label>
|
||||
<description>Play an audio or video media from the given URL</description>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="stop">
|
||||
<item-type>Switch</item-type>
|
||||
<label>Stop Playback</label>
|
||||
<description>Stop the media playback</description>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICWTCCAd+gAwIBAgIJAMaRcLnIgyukMAoGCCqGSM49BAMCMGExCzAJBgNVBAYT
|
||||
AkZSMQ8wDQYDVQQIDAZGcmFuY2UxDjAMBgNVBAcMBVBhcmlzMRMwEQYDVQQKDApG
|
||||
cmVlYm94IFNBMRwwGgYDVQQDDBNGcmVlYm94IEVDQyBSb290IENBMB4XDTE1MDkw
|
||||
MTE4MDIwN1oXDTM1MDgyNzE4MDIwN1owYTELMAkGA1UEBhMCRlIxDzANBgNVBAgM
|
||||
BkZyYW5jZTEOMAwGA1UEBwwFUGFyaXMxEzARBgNVBAoMCkZyZWVib3ggU0ExHDAa
|
||||
BgNVBAMME0ZyZWVib3ggRUNDIFJvb3QgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
|
||||
AASCjD6ZKn5ko6cU5Vxh8GA1KqRi6p2GQzndxHtuUmwY8RvBbhZ0GIL7bQ4f08ae
|
||||
JOv0ycWjEW0fyOnAw6AYdsN6y1eNvH2DVfoXQyGoCSvXQNAUxla+sJuLGICRYiZz
|
||||
mnijYzBhMB0GA1UdDgQWBBTIB3c2GlbV6EIh2ErEMJvFxMz/QTAfBgNVHSMEGDAW
|
||||
gBTIB3c2GlbV6EIh2ErEMJvFxMz/QTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
|
||||
/wQEAwIBhjAKBggqhkjOPQQDAgNoADBlAjA8tzEMRVX8vrFuOGDhvZr7OSJjbBr8
|
||||
gl2I70LeVNGEXZsAThUkqj5Rg9bV8xw3aSMCMQCDjB5CgsLH8EdZmiksdBRRKM2r
|
||||
vxo6c0dSSNrr7dDN+m2/dRvgoIpGL2GauOGqDFY=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2020 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.freebox.internal.api;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Laurent Garnier - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class FreeboxApiManagerTest {
|
||||
|
||||
@Test
|
||||
public void hmacSha1Test() throws Exception {
|
||||
String expected = "25dad1bb5604321f12b755cc9d755d1480cf7989";
|
||||
String actual = FreeboxApiManager.hmacSha1("Token1234", "Challenge");
|
||||
Assert.assertEquals(expected, actual);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user