mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[XMLTV] Preparing for Crowdin and code refining. (#11594)
* Preparing for Crowdin and code refining. Signed-off-by: Gaël L'hopital <gael@lhopital.org> * Satisfying SAT Signed-off-by: Gaël L'hopital <gael@lhopital.org> * Preventing two potential NPE Signed-off-by: Gaël L'hopital <gael@lhopital.org> * Code review comments taken in account Signed-off-by: clinique <gael@lhopital.org> * Reverting description removal Signed-off-by: clinique <gael@lhopital.org> * Forgot spotless apply Signed-off-by: clinique <gael@lhopital.org>
This commit is contained in:
parent
4a3a9d5873
commit
2eb0ff5502
@ -8,7 +8,7 @@ The building of the XMLTV file itself is taken in charge by so called "grabbers"
|
||||
|
||||
Some websites provides updated XMLTV files than can be directly downloaded.
|
||||
|
||||
Here is a sample for France : https://www.xmltv.fr/
|
||||
Here is a sample for France and Switzerland : https://xmltv.ch/
|
||||
|
||||
This binding takes an XMLTV file as input and creates a thing for each channel contained in it.
|
||||
XmlTV channels are called Media Channels in this binding in order to avoid messing with openHAB Channels.
|
||||
|
@ -12,10 +12,7 @@
|
||||
*/
|
||||
package org.openhab.binding.xmltv.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;
|
||||
@ -36,7 +33,6 @@ public class XmlTVBindingConstants {
|
||||
public static final ThingTypeUID XMLTV_CHANNEL_THING_TYPE = new ThingTypeUID(BINDING_ID, "channel");
|
||||
|
||||
// Channel groups
|
||||
public static final String GROUP_CURRENT_PROGRAMME = "currentprog";
|
||||
public static final String GROUP_NEXT_PROGRAMME = "nextprog";
|
||||
public static final String GROUP_CHANNEL_PROPERTIES = "channelprops";
|
||||
|
||||
@ -56,6 +52,6 @@ public class XmlTVBindingConstants {
|
||||
public static final String CHANNEL_PROGRAMME_TIMELEFT = "timeLeft";
|
||||
|
||||
// Supported Thing types
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
|
||||
.unmodifiableSet(Stream.of(XMLTV_FILE_BRIDGE_TYPE, XMLTV_CHANNEL_THING_TYPE).collect(Collectors.toSet()));
|
||||
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(XMLTV_FILE_BRIDGE_TYPE,
|
||||
XMLTV_CHANNEL_THING_TYPE);
|
||||
}
|
||||
|
@ -14,19 +14,18 @@ package org.openhab.binding.xmltv.internal;
|
||||
|
||||
import static org.openhab.binding.xmltv.internal.XmlTVBindingConstants.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.xmltv.internal.discovery.XmlTVDiscoveryService;
|
||||
import org.openhab.binding.xmltv.internal.handler.ChannelHandler;
|
||||
import org.openhab.binding.xmltv.internal.handler.XmlTVHandler;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Tv;
|
||||
import org.openhab.core.config.core.Configuration;
|
||||
import org.openhab.core.config.discovery.DiscoveryService;
|
||||
import org.openhab.core.i18n.TimeZoneProvider;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
@ -34,10 +33,9 @@ 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.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link XmlTVHandlerFactory} is responsible for creating things and thing
|
||||
@ -48,8 +46,16 @@ import org.slf4j.LoggerFactory;
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.xmltv", service = ThingHandlerFactory.class)
|
||||
public class XmlTVHandlerFactory extends BaseThingHandlerFactory {
|
||||
private final Logger logger = LoggerFactory.getLogger(XmlTVHandlerFactory.class);
|
||||
private final Map<ThingUID, ServiceRegistration<?>> discoveryServiceRegs = new HashMap<>();
|
||||
private final XMLInputFactory xif = XMLInputFactory.newFactory();
|
||||
private final TimeZoneProvider timeZoneProvider;
|
||||
private final Unmarshaller unmarshaller;
|
||||
|
||||
@Activate
|
||||
public XmlTVHandlerFactory(final @Reference TimeZoneProvider timeZoneProvider) throws JAXBException {
|
||||
this.timeZoneProvider = timeZoneProvider;
|
||||
this.unmarshaller = JAXBContext.newInstance(Tv.class).createUnmarshaller();
|
||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
@ -79,37 +85,11 @@ public class XmlTVHandlerFactory extends BaseThingHandlerFactory {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (XMLTV_FILE_BRIDGE_TYPE.equals(thingTypeUID)) {
|
||||
try {
|
||||
XmlTVHandler bridgeHandler = new XmlTVHandler((Bridge) thing);
|
||||
registerDeviceDiscoveryService(bridgeHandler);
|
||||
return bridgeHandler;
|
||||
} catch (JAXBException e) {
|
||||
logger.error("Unable to create XmlTVHandler : {}", e.getMessage());
|
||||
}
|
||||
return new XmlTVHandler((Bridge) thing, xif, unmarshaller);
|
||||
} else if (XMLTV_CHANNEL_THING_TYPE.equals(thingTypeUID)) {
|
||||
return new ChannelHandler(thing);
|
||||
return new ChannelHandler(thing, timeZoneProvider.getTimeZone());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeHandler(ThingHandler thingHandler) {
|
||||
if (thingHandler instanceof XmlTVHandler) {
|
||||
Thing thing = thingHandler.getThing();
|
||||
unregisterDeviceDiscoveryService(thing);
|
||||
}
|
||||
super.removeHandler(thingHandler);
|
||||
}
|
||||
|
||||
private synchronized void registerDeviceDiscoveryService(XmlTVHandler bridgeHandler) {
|
||||
XmlTVDiscoveryService discoveryService = new XmlTVDiscoveryService(bridgeHandler);
|
||||
discoveryServiceRegs.put(bridgeHandler.getThing().getUID(),
|
||||
bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
|
||||
}
|
||||
|
||||
private synchronized void unregisterDeviceDiscoveryService(Thing thing) {
|
||||
ServiceRegistration<?> serviceReg = discoveryServiceRegs.remove(thing.getUID());
|
||||
serviceReg.unregister();
|
||||
}
|
||||
}
|
||||
|
@ -12,16 +12,19 @@
|
||||
*/
|
||||
package org.openhab.binding.xmltv.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link XmlChannelConfiguration} class contains fields mapping
|
||||
* Channel thing configuration parameters.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class XmlChannelConfiguration {
|
||||
public static final String CHANNEL_ID = "channelId";
|
||||
|
||||
public String channelId;
|
||||
public Integer offset;
|
||||
public Integer refresh;
|
||||
public String channelId = "";
|
||||
public int offset = 0;
|
||||
public int refresh = 60;
|
||||
}
|
||||
|
@ -12,14 +12,17 @@
|
||||
*/
|
||||
package org.openhab.binding.xmltv.internal.configuration;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link XmlTVConfiguration} class contains fields mapping TV bridge
|
||||
* configuration parameters.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class XmlTVConfiguration {
|
||||
public String filePath;
|
||||
public Integer refresh;
|
||||
public String encoding;
|
||||
public String filePath = "";
|
||||
public int refresh = 24;
|
||||
public String encoding = "UTF8";
|
||||
}
|
||||
|
@ -12,18 +12,21 @@
|
||||
*/
|
||||
package org.openhab.binding.xmltv.internal.discovery;
|
||||
|
||||
import static org.openhab.binding.xmltv.internal.XmlTVBindingConstants.XMLTV_CHANNEL_THING_TYPE;
|
||||
import static org.openhab.binding.xmltv.internal.XmlTVBindingConstants.*;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.binding.xmltv.internal.XmlTVBindingConstants;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.xmltv.internal.configuration.XmlChannelConfiguration;
|
||||
import org.openhab.binding.xmltv.internal.handler.XmlTVHandler;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Tv;
|
||||
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.ThingStatus;
|
||||
import org.openhab.core.thing.ThingUID;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerService;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@ -33,28 +36,33 @@ import org.slf4j.LoggerFactory;
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@Component(service = ThingHandlerService.class)
|
||||
@NonNullByDefault
|
||||
public class XmlTVDiscoveryService extends AbstractDiscoveryService {
|
||||
public class XmlTVDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
|
||||
private static final int SEARCH_TIME = 5;
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(XmlTVDiscoveryService.class);
|
||||
|
||||
private static final int SEARCH_TIME = 10;
|
||||
|
||||
private XmlTVHandler bridgeHandler;
|
||||
private @Nullable XmlTVHandler handler;
|
||||
|
||||
/**
|
||||
* Creates a XmlTVDiscoveryService with background discovery disabled.
|
||||
*/
|
||||
public XmlTVDiscoveryService(XmlTVHandler bridgeHandler) {
|
||||
super(XmlTVBindingConstants.SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME);
|
||||
this.bridgeHandler = bridgeHandler;
|
||||
@Activate
|
||||
public XmlTVDiscoveryService() {
|
||||
super(SUPPORTED_THING_TYPES_UIDS, SEARCH_TIME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void startScan() {
|
||||
logger.debug("Starting XmlTV discovery scan");
|
||||
if (bridgeHandler.getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
Tv tv = bridgeHandler.getXmlFile();
|
||||
if (tv != null) {
|
||||
XmlTVHandler bridgeHandler = handler;
|
||||
if (bridgeHandler != null && bridgeHandler.getThing().getStatus() == ThingStatus.ONLINE) {
|
||||
bridgeHandler.getXmlFile().ifPresent(tv -> {
|
||||
tv.getMediaChannels().stream().forEach(channel -> {
|
||||
String channelId = channel.getId();
|
||||
String uid = channelId.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
@ -67,7 +75,19 @@ public class XmlTVDiscoveryService extends AbstractDiscoveryService {
|
||||
|
||||
thingDiscovered(discoveryResult);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setThingHandler(ThingHandler handler) {
|
||||
if (handler instanceof XmlTVHandler) {
|
||||
this.handler = (XmlTVHandler) handler;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ThingHandler getThingHandler() {
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import org.openhab.binding.xmltv.internal.configuration.XmlChannelConfiguration;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Icon;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.MediaChannel;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Programme;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Tv;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.WithLangType;
|
||||
import org.openhab.core.io.net.http.HttpUtil;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
@ -61,14 +60,16 @@ import org.slf4j.LoggerFactory;
|
||||
public class ChannelHandler extends BaseThingHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(ChannelHandler.class);
|
||||
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> globalJob;
|
||||
private @Nullable ScheduledFuture<?> globalJob;
|
||||
private @Nullable MediaChannel mediaChannel;
|
||||
private @Nullable RawType mediaIcon = new RawType(new byte[0], RawType.DEFAULT_MIME_TYPE);
|
||||
private State mediaIcon = UnDefType.UNDEF;
|
||||
|
||||
public final List<Programme> programmes = new ArrayList<>();
|
||||
private final ZoneId zoneId;
|
||||
|
||||
public ChannelHandler(Thing thing) {
|
||||
public ChannelHandler(Thing thing, ZoneId zoneId) {
|
||||
super(thing);
|
||||
this.zoneId = zoneId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -77,14 +78,14 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
|
||||
logger.debug("Initializing Broadcast Channel handler for uid '{}'", getThing().getUID());
|
||||
|
||||
if (globalJob == null || globalJob.isCancelled()) {
|
||||
ScheduledFuture<?> job = globalJob;
|
||||
if (job == null || job.isCancelled()) {
|
||||
globalJob = scheduler.scheduleWithFixedDelay(() -> {
|
||||
if (programmes.size() < 2) {
|
||||
refreshProgramList();
|
||||
}
|
||||
if (programmes.isEmpty()) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||
"No programmes to come in the current XML file for this channel");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "@text/no-more-programs");
|
||||
} else if (Instant.now().isAfter(programmes.get(0).getProgrammeStop())) {
|
||||
programmes.remove(0);
|
||||
}
|
||||
@ -100,8 +101,7 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
if (bridge != null && bridge.getStatus() == ThingStatus.ONLINE) {
|
||||
XmlTVHandler handler = (XmlTVHandler) bridge.getHandler();
|
||||
if (handler != null) {
|
||||
Tv tv = handler.getXmlFile();
|
||||
if (tv != null) {
|
||||
handler.getXmlFile().ifPresentOrElse(tv -> {
|
||||
String channelId = (String) getConfig().get(XmlChannelConfiguration.CHANNEL_ID);
|
||||
|
||||
if (mediaChannel == null) {
|
||||
@ -119,9 +119,7 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
.forEach(p -> programmes.add(p));
|
||||
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "No file available");
|
||||
}
|
||||
}, () -> updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE, "@text/no-file-available"));
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.BRIDGE_OFFLINE);
|
||||
}
|
||||
@ -132,8 +130,9 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (globalJob != null && !globalJob.isCancelled()) {
|
||||
globalJob.cancel(true);
|
||||
ScheduledFuture<?> job = globalJob;
|
||||
if (job != null && !job.isCancelled()) {
|
||||
job.cancel(true);
|
||||
globalJob = null;
|
||||
}
|
||||
}
|
||||
@ -153,6 +152,7 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
*
|
||||
*/
|
||||
private void updateChannel(ChannelUID channelUID) {
|
||||
// TODO : usage extraction of groupname
|
||||
String[] uidElements = channelUID.getId().split("#");
|
||||
if (uidElements.length == 2) {
|
||||
int target = GROUP_NEXT_PROGRAMME.equals(uidElements[0]) ? 1 : 0;
|
||||
@ -161,29 +161,22 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
|
||||
switch (uidElements[1]) {
|
||||
case CHANNEL_ICON:
|
||||
State icon = null;
|
||||
if (GROUP_CHANNEL_PROPERTIES.equals(uidElements[0])) {
|
||||
icon = mediaIcon;
|
||||
} else {
|
||||
icon = downloadIcon(programme.getIcons());
|
||||
}
|
||||
updateState(channelUID, icon != null ? icon : UnDefType.UNDEF);
|
||||
State icon = GROUP_CHANNEL_PROPERTIES.equals(uidElements[0]) ? mediaIcon
|
||||
: downloadIcon(programme.getIcons());
|
||||
updateState(channelUID, icon);
|
||||
break;
|
||||
case CHANNEL_CHANNEL_URL:
|
||||
MediaChannel channel = mediaChannel;
|
||||
updateState(channelUID,
|
||||
mediaChannel != null ? !mediaChannel.getIcons().isEmpty()
|
||||
? new StringType(mediaChannel.getIcons().get(0).getSrc())
|
||||
channel != null ? !channel.getIcons().isEmpty()
|
||||
? new StringType(channel.getIcons().get(0).getSrc())
|
||||
: UnDefType.UNDEF : UnDefType.UNDEF);
|
||||
break;
|
||||
case CHANNEL_PROGRAMME_START:
|
||||
Instant is = programme.getProgrammeStart();
|
||||
ZonedDateTime zds = ZonedDateTime.ofInstant(is, ZoneId.systemDefault());
|
||||
updateState(channelUID, new DateTimeType(zds));
|
||||
updateDateTimeChannel(channelUID, programme.getProgrammeStart());
|
||||
break;
|
||||
case CHANNEL_PROGRAMME_END:
|
||||
ZonedDateTime zde = ZonedDateTime.ofInstant(programme.getProgrammeStop(),
|
||||
ZoneId.systemDefault());
|
||||
updateState(channelUID, new DateTimeType(zde));
|
||||
updateDateTimeChannel(channelUID, programme.getProgrammeStop());
|
||||
break;
|
||||
case CHANNEL_PROGRAMME_TITLE:
|
||||
List<WithLangType> titles = programme.getTitles();
|
||||
@ -212,18 +205,15 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
updateState(channelUID, getDurationInSeconds(Instant.now(), programme.getProgrammeStart()));
|
||||
break;
|
||||
case CHANNEL_PROGRAMME_PROGRESS:
|
||||
Duration totalLength = Duration.between(programme.getProgrammeStart(),
|
||||
programme.getProgrammeStop());
|
||||
Duration elapsed1 = Duration.between(programme.getProgrammeStart(), Instant.now());
|
||||
long totalLength = Duration.between(programme.getProgrammeStart(), programme.getProgrammeStop())
|
||||
.toSeconds();
|
||||
long elapsed1 = Duration.between(programme.getProgrammeStart(), Instant.now()).toSeconds();
|
||||
|
||||
long secondsElapsed1 = elapsed1.toMillis() / 1000;
|
||||
long secondsLength = totalLength.toMillis() / 1000;
|
||||
|
||||
double progress = 100.0 * secondsElapsed1 / secondsLength;
|
||||
double progress = 100.0 * elapsed1 / totalLength;
|
||||
if (progress > 100 || progress < 0) {
|
||||
logger.debug("Outstanding process");
|
||||
}
|
||||
updateState(channelUID, new QuantityType<>(progress, Units.PERCENT));
|
||||
updateState(channelUID, new QuantityType<>((int) progress, Units.PERCENT));
|
||||
|
||||
break;
|
||||
}
|
||||
@ -233,17 +223,24 @@ public class ChannelHandler extends BaseThingHandler {
|
||||
}
|
||||
}
|
||||
|
||||
private QuantityType<?> getDurationInSeconds(Instant from, Instant to) {
|
||||
Duration elapsed = Duration.between(from, to);
|
||||
long secondsElapsed = TimeUnit.MILLISECONDS.toSeconds(elapsed.toMillis());
|
||||
return new QuantityType<>(secondsElapsed, Units.SECOND);
|
||||
private void updateDateTimeChannel(ChannelUID channelUID, Instant instant) {
|
||||
ZonedDateTime zds = ZonedDateTime.ofInstant(instant, zoneId);
|
||||
updateState(channelUID, new DateTimeType(zds));
|
||||
}
|
||||
|
||||
private @Nullable RawType downloadIcon(List<Icon> icons) {
|
||||
private QuantityType<?> getDurationInSeconds(Instant from, Instant to) {
|
||||
long elapsed = Duration.between(from, to).toSeconds();
|
||||
return new QuantityType<>(elapsed, Units.SECOND);
|
||||
}
|
||||
|
||||
private State downloadIcon(List<Icon> icons) {
|
||||
if (!icons.isEmpty()) {
|
||||
String url = icons.get(0).getSrc();
|
||||
return HttpUtil.downloadImage(url);
|
||||
}
|
||||
return null;
|
||||
RawType result = HttpUtil.downloadImage(url);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return UnDefType.NULL;
|
||||
}
|
||||
}
|
||||
|
@ -16,12 +16,14 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
@ -31,6 +33,7 @@ import javax.xml.stream.XMLStreamReader;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.binding.xmltv.internal.configuration.XmlTVConfiguration;
|
||||
import org.openhab.binding.xmltv.internal.discovery.XmlTVDiscoveryService;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Programme;
|
||||
import org.openhab.binding.xmltv.internal.jaxb.Tv;
|
||||
import org.openhab.core.thing.Bridge;
|
||||
@ -38,6 +41,7 @@ import org.openhab.core.thing.ChannelUID;
|
||||
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.ThingHandlerService;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -51,16 +55,16 @@ import org.slf4j.LoggerFactory;
|
||||
@NonNullByDefault
|
||||
public class XmlTVHandler extends BaseBridgeHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(XmlTVHandler.class);
|
||||
private final XMLInputFactory xif = XMLInputFactory.newFactory();
|
||||
private final JAXBContext jc;
|
||||
private final XMLInputFactory xif;
|
||||
private final Unmarshaller unmarshaller;
|
||||
|
||||
private @Nullable Tv currentXmlFile;
|
||||
private @NonNullByDefault({}) ScheduledFuture<?> reloadJob;
|
||||
|
||||
public XmlTVHandler(Bridge thing) throws JAXBException {
|
||||
public XmlTVHandler(Bridge thing, XMLInputFactory xif, Unmarshaller unmarshaller) {
|
||||
super(thing);
|
||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
jc = JAXBContext.newInstance(Tv.class);
|
||||
this.xif = xif;
|
||||
this.unmarshaller = unmarshaller;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -74,9 +78,7 @@ public class XmlTVHandler extends BaseBridgeHandler {
|
||||
try {
|
||||
// This can take some seconds depending upon weight of the XmlTV source file
|
||||
xsr = xif.createXMLStreamReader(new FileInputStream(new File(config.filePath)), config.encoding);
|
||||
|
||||
try {
|
||||
Unmarshaller unmarshaller = jc.createUnmarshaller();
|
||||
Tv xmlFile = (Tv) unmarshaller.unmarshal(xsr);
|
||||
// Remove all finished programmes
|
||||
xmlFile.getProgrammes().removeIf(programme -> Instant.now().isAfter(programme.getProgrammeStop()));
|
||||
@ -88,7 +90,7 @@ public class XmlTVHandler extends BaseBridgeHandler {
|
||||
currentXmlFile = xmlFile;
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
} else {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED, "XMLTV file seems outdated");
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.DISABLED, "@text/file-outdated");
|
||||
}
|
||||
xsr.close();
|
||||
} catch (JAXBException e) {
|
||||
@ -122,8 +124,12 @@ public class XmlTVHandler extends BaseBridgeHandler {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Tv getXmlFile() {
|
||||
return currentXmlFile;
|
||||
public Optional<Tv> getXmlFile() {
|
||||
return Optional.ofNullable(currentXmlFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends ThingHandlerService>> getServices() {
|
||||
return Set.of(XmlTVDiscoveryService.class);
|
||||
}
|
||||
}
|
||||
|
@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2010-2021 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.xmltv.internal.jaxb;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRegistry;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* This object contains factory methods for each Java content
|
||||
* interface and Java element interface generated in the
|
||||
* org.openhab.binding.xmltv.internal.jaxb package.
|
||||
*
|
||||
* @author Gaël L'hopital - Initial contribution
|
||||
*/
|
||||
@XmlRegistry
|
||||
@NonNullByDefault
|
||||
public class ObjectFactory {
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Tv }
|
||||
*
|
||||
*/
|
||||
public Tv createTv() {
|
||||
return new Tv();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Programme }
|
||||
*
|
||||
*/
|
||||
public Programme createProgramme() {
|
||||
return new Programme();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link MediaChannel }
|
||||
*
|
||||
*/
|
||||
public MediaChannel createChannel() {
|
||||
return new MediaChannel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link Icon }
|
||||
*
|
||||
*/
|
||||
public Icon createIcon() {
|
||||
return new Icon();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link WithLangType }
|
||||
*
|
||||
*/
|
||||
public WithLangType createWithLangType() {
|
||||
return new WithLangType();
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
# binding
|
||||
|
||||
binding.xmltv.name = XmlTV Binding
|
||||
binding.xmltv.description = This is the binding for reading and parsing XmlTV files
|
||||
|
||||
# bridge types
|
||||
|
||||
thing-type.xmltv.xmltvfile.label = XmlTVFile
|
||||
thing-type.xmltv.xmltvfile.description = This is the interface to a XmlTV file
|
||||
|
||||
thing-type.config.xmltv.xmltvfile.filePath.label = XmlTV File Path
|
||||
thing-type.config.xmltv.xmltvfile.filePath.description = Path to an XmlTV file.
|
||||
thing-type.config.xmltv.xmltvfile.refresh.label = Refresh Interval
|
||||
thing-type.config.xmltv.xmltvfile.refresh.description = Specifies the XMLTV file reload interval in hours.
|
||||
thing-type.config.xmltv.xmltvfile.encoding.label = File encoding
|
||||
thing-type.config.xmltv.xmltvfile.encoding.description = Specifies the XMLTV file encoding.
|
||||
|
||||
# thing types
|
||||
|
||||
thing-type.xmltv.channel.label = Channel
|
||||
thing-type.xmltv.channel.description = This represent a channel on a given TV file
|
||||
|
||||
thing-type.config.xmltv.channel.channelId.label = Channel Id
|
||||
thing-type.config.xmltv.channel.channelId.description = Id of the channel as presented in the XmlTV file.
|
||||
thing-type.config.xmltv.channel.offset.label = Offset
|
||||
thing-type.config.xmltv.channel.offset.description = Moves an event or datetime value forward or backward (in minutes)
|
||||
thing-type.config.xmltv.channel.refresh.label = Refresh Interval
|
||||
thing-type.config.xmltv.channel.refresh.description = Specifies the refresh interval in seconds.
|
||||
|
||||
# channel group types
|
||||
|
||||
channel-group-type.xmltv.channelprops.label = Channel Properties
|
||||
channel-group-type.xmltv.currentprog.label = Current Program
|
||||
channel-group-type.xmltv.nextprog.label = Next Program
|
||||
|
||||
# channel type
|
||||
|
||||
channel-type.xmltv.iconUrl.label = Channel Icon URL
|
||||
channel-type.xmltv.iconUrl.description = Icon URL of the TV channel.
|
||||
channel-type.xmltv.progIconUrl.label = Program URL
|
||||
channel-type.xmltv.progIconUrl.description = URL to an image of the program.
|
||||
channel-type.xmltv.progTitle.label = Title
|
||||
channel-type.xmltv.progTitle.description = Program Title.
|
||||
channel-type.xmltv.progCategory.label = Category
|
||||
channel-type.xmltv.progCategory.description = Program Category.
|
||||
channel-type.xmltv.progStart.label = Start Time
|
||||
channel-type.xmltv.progStart.description = Program Start Time
|
||||
channel-type.xmltv.progEnd.label = End Time
|
||||
channel-type.xmltv.progEnd.description = Program End Time
|
||||
channel-type.xmltv.elapsedTime.label = Current Time
|
||||
channel-type.xmltv.elapsedTime.description = Current time of currently playing program.
|
||||
channel-type.xmltv.remainingTime.label = Remaining Time
|
||||
channel-type.xmltv.remainingTime.description = Time remaining until end of the program.
|
||||
channel-type.xmltv.timeLeft.label = Time Left
|
||||
channel-type.xmltv.timeLeft.description = Time left before program start
|
||||
channel-type.xmltv.progress.label = Progress
|
||||
channel-type.xmltv.progress.description = Relative progression of the current program.
|
||||
channel-type.xmltv.icon.label = Icon
|
||||
channel-type.xmltv.icon.description = Icon of the channel / program.
|
||||
|
||||
# messages
|
||||
no-more-programs = No programmes to come in the current XML file for this channel
|
||||
no-file-available = No file available
|
||||
file-outdated = XMLTV file seems outdated
|
Loading…
Reference in New Issue
Block a user