added migrated 2.x add-ons
Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<features name="org.openhab.binding.enturno-${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-enturno" description="Enturno Binding" version="${project.version}">
|
||||
<feature>openhab-runtime-base</feature>
|
||||
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.enturno/${project.version}</bundle>
|
||||
</feature>
|
||||
</features>
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.enturno.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
|
||||
/**
|
||||
* The {@link EnturNoBindingConstants} class defines common constants, which are
|
||||
* used across the whole binding.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturNoBindingConstants {
|
||||
|
||||
private static final String BINDING_ID = "enturno";
|
||||
|
||||
public static final String TIME_ZONE = "Europe/Oslo";
|
||||
|
||||
// List of all Thing Type UIDs
|
||||
public static final ThingTypeUID LINESTOP = new ThingTypeUID(BINDING_ID, "linestop");
|
||||
|
||||
// List of all channel groups
|
||||
public static final String CHANNEL_GROUP_STOP_PLACE = "stopPlace";
|
||||
public static final String CHANNEL_GROUP_DIRECTION_1 = "Direction01";
|
||||
public static final String CHANNEL_GROUP_DIRECTION_2 = "Direction02";
|
||||
|
||||
// List of all channels
|
||||
public static final String CHANNEL_STOP_ID = "id";
|
||||
public static final String CHANNEL_STOP_NAME = "name";
|
||||
public static final String CHANNEL_STOP_TRANSPORT_MODE = "transportMode";
|
||||
public static final String CHANNEL_LINE_CODE = "lineCode";
|
||||
public static final String CHANNEL_DEPARTURE_01 = "departure01";
|
||||
public static final String CHANNEL_DEPARTURE_02 = "departure02";
|
||||
public static final String CHANNEL_DEPARTURE_03 = "departure03";
|
||||
public static final String CHANNEL_DEPARTURE_04 = "departure04";
|
||||
public static final String CHANNEL_DEPARTURE_05 = "departure05";
|
||||
public static final String ESTIMATED_FLAG_01 = "estimatedFlag01";
|
||||
public static final String ESTIMATED_FLAG_02 = "estimatedFlag02";
|
||||
public static final String ESTIMATED_FLAG_03 = "estimatedFlag03";
|
||||
public static final String ESTIMATED_FLAG_04 = "estimatedFlag04";
|
||||
public static final String ESTIMATED_FLAG_05 = "estimatedFlag05";
|
||||
public static final String CHANNEL_FRONT_DISPLAY = "frontDisplayText";
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.enturno.internal;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The {@link EnturNoConfiguration} class contains fields mapping thing configuration parameters.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturNoConfiguration {
|
||||
|
||||
public @Nullable String stopPlaceId;
|
||||
|
||||
public @Nullable String getStopPlaceId() {
|
||||
return stopPlaceId;
|
||||
}
|
||||
|
||||
public void setStopPlaceId(String stopPlaceId) {
|
||||
this.stopPlaceId = stopPlaceId;
|
||||
}
|
||||
|
||||
public @Nullable String lineCode;
|
||||
|
||||
public @Nullable String getLineCode() {
|
||||
return lineCode;
|
||||
}
|
||||
|
||||
public void setLineCode(String lineCode) {
|
||||
this.lineCode = lineCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* 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.enturno.internal;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.binding.enturno.internal.connection.EnturCommunicationException;
|
||||
import org.openhab.binding.enturno.internal.connection.EnturConfigurationException;
|
||||
import org.openhab.binding.enturno.internal.connection.EnturNoConnection;
|
||||
import org.openhab.binding.enturno.internal.model.simplified.DisplayData;
|
||||
import org.openhab.core.library.types.DateTimeType;
|
||||
import org.openhab.core.library.types.StringType;
|
||||
import org.openhab.core.thing.Channel;
|
||||
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.BaseThingHandler;
|
||||
import org.openhab.core.thing.type.ChannelKind;
|
||||
import org.openhab.core.types.Command;
|
||||
import org.openhab.core.types.RefreshType;
|
||||
import org.openhab.core.types.State;
|
||||
import org.openhab.core.types.UnDefType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link EnturNoHandler} is responsible for handling commands, which are
|
||||
* sent to one of the channels.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturNoHandler extends BaseThingHandler {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnturNoHandler.class);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private @NonNullByDefault({}) EnturNoConfiguration config;
|
||||
|
||||
private @NonNullByDefault({}) EnturNoConnection connection;
|
||||
|
||||
private static final long INITIAL_DELAY_IN_SECONDS = 15;
|
||||
|
||||
private static final long REFRESH_INTERVAL_IN_SECONDS = 30;
|
||||
|
||||
private @Nullable ScheduledFuture<?> refreshJob;
|
||||
|
||||
private @Nullable String stopId;
|
||||
|
||||
private List<DisplayData> processedData = new ArrayList<>();
|
||||
|
||||
public EnturNoHandler(Thing thing, HttpClient httpClient) {
|
||||
super(thing);
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCommand(ChannelUID channelUID, Command command) {
|
||||
if (command instanceof RefreshType) {
|
||||
updateChannel(channelUID);
|
||||
} else {
|
||||
logger.debug("Entur binding is a read-only binding and cannot handle command '{}'.", command);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
logger.debug("Initialize Entur EnturTimeTable API handler '{}'.", getThing().getUID());
|
||||
config = getConfigAs(EnturNoConfiguration.class);
|
||||
stopId = config.getStopPlaceId();
|
||||
|
||||
logger.debug("Stop place id: {}", stopId);
|
||||
boolean configValid = true;
|
||||
if (StringUtils.trimToNull(stopId) == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error-missing-stopId");
|
||||
configValid = false;
|
||||
}
|
||||
|
||||
logger.debug("Line code: {}", config.getLineCode());
|
||||
if (StringUtils.trimToNull(config.getLineCode()) == null) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR,
|
||||
"@text/offline.conf-error-missing-lineCode");
|
||||
configValid = false;
|
||||
}
|
||||
|
||||
if (configValid) {
|
||||
connection = new EnturNoConnection(this, httpClient);
|
||||
|
||||
updateStatus(ThingStatus.UNKNOWN);
|
||||
|
||||
if (refreshJob == null || refreshJob.isCancelled()) {
|
||||
logger.debug("Start refresh job at interval {} sec.", REFRESH_INTERVAL_IN_SECONDS);
|
||||
refreshJob = scheduler.scheduleWithFixedDelay(this::updateThing, INITIAL_DELAY_IN_SECONDS,
|
||||
REFRESH_INTERVAL_IN_SECONDS, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
logger.debug("Dispose Entur real-time timetable API handler '{}'.", getThing().getUID());
|
||||
if (refreshJob != null && !refreshJob.isCancelled()) {
|
||||
logger.debug("Stop refresh job.");
|
||||
if (refreshJob.cancel(true)) {
|
||||
refreshJob = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public EnturNoConfiguration getEnturNoConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
private void updateThing() {
|
||||
ThingStatus status = ThingStatus.OFFLINE;
|
||||
if (connection != null) {
|
||||
logger.trace("Updating data");
|
||||
updateData(connection);
|
||||
status = thing.getStatus();
|
||||
} else {
|
||||
logger.debug("Cannot update real-time data of thing '{}' as connection is null.", thing.getUID());
|
||||
status = ThingStatus.OFFLINE;
|
||||
}
|
||||
|
||||
updateStatus(status);
|
||||
}
|
||||
|
||||
public void updateData(EnturNoConnection connection) {
|
||||
try {
|
||||
if (requestData(connection)) {
|
||||
updateChannels();
|
||||
updateStatus(ThingStatus.ONLINE);
|
||||
}
|
||||
} catch (EnturCommunicationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, e.getLocalizedMessage());
|
||||
} catch (EnturConfigurationException e) {
|
||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean requestData(EnturNoConnection connection)
|
||||
throws EnturConfigurationException, EnturCommunicationException {
|
||||
logger.debug("Update real-time data of thing '{}'.", getThing().getUID());
|
||||
try {
|
||||
processedData = connection.getEnturTimeTable(stopId, config.getLineCode());
|
||||
|
||||
return true;
|
||||
} catch (JsonSyntaxException e) {
|
||||
logger.debug("JsonSyntaxException occurred during execution: {}", e.getLocalizedMessage(), e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChannels() {
|
||||
for (Channel channel : getThing().getChannels()) {
|
||||
ChannelUID channelUID = channel.getUID();
|
||||
if (ChannelKind.STATE.equals(channel.getKind()) && channelUID.isInGroup() && channelUID.getGroupId() != null
|
||||
&& isLinked(channelUID)) {
|
||||
updateChannel(channelUID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChannel(ChannelUID channelUID) {
|
||||
String channelGroupId = channelUID.getGroupId();
|
||||
logger.trace("Channel group id: {}", channelGroupId);
|
||||
if (channelGroupId != null) {
|
||||
switch (channelGroupId) {
|
||||
case EnturNoBindingConstants.CHANNEL_GROUP_STOP_PLACE:
|
||||
updateStopPlaceChannel(channelUID);
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_GROUP_DIRECTION_1:
|
||||
updateDirectionChannel(channelUID, 0);
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_GROUP_DIRECTION_2:
|
||||
updateDirectionChannel(channelUID, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateDirectionChannel(ChannelUID channelUID, int i) {
|
||||
String channelId = channelUID.getIdWithoutGroup();
|
||||
String channelGroupId = channelUID.getGroupId();
|
||||
logger.trace("Channel id: {}, Channel group id: {}", channelId, channelGroupId);
|
||||
if (processedData.size() > i) {
|
||||
State state = UnDefType.UNDEF;
|
||||
List<String> departures = processedData.get(i).departures;
|
||||
List<String> estimatedFlags = processedData.get(i).estimatedFlags;
|
||||
switch (channelId) {
|
||||
case EnturNoBindingConstants.CHANNEL_DEPARTURE_01:
|
||||
state = departures.size() > 0 ? getDateTimeTypeState(departures.get(0)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_DEPARTURE_02:
|
||||
state = departures.size() > 1 ? getDateTimeTypeState(departures.get(1)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_DEPARTURE_03:
|
||||
state = departures.size() > 2 ? getDateTimeTypeState(departures.get(2)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_DEPARTURE_04:
|
||||
state = departures.size() > 3 ? getDateTimeTypeState(departures.get(3)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_DEPARTURE_05:
|
||||
state = departures.size() > 4 ? getDateTimeTypeState(departures.get(4)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.ESTIMATED_FLAG_01:
|
||||
state = estimatedFlags.size() > 0 ? getStringTypeState(estimatedFlags.get(0)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.ESTIMATED_FLAG_02:
|
||||
state = estimatedFlags.size() > 1 ? getStringTypeState(estimatedFlags.get(1)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.ESTIMATED_FLAG_03:
|
||||
state = estimatedFlags.size() > 2 ? getStringTypeState(estimatedFlags.get(2)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.ESTIMATED_FLAG_04:
|
||||
state = estimatedFlags.size() > 3 ? getStringTypeState(estimatedFlags.get(3)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.ESTIMATED_FLAG_05:
|
||||
state = estimatedFlags.size() > 4 ? getStringTypeState(estimatedFlags.get(4)) : state;
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_LINE_CODE:
|
||||
state = getStringTypeState(processedData.get(i).lineCode);
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_FRONT_DISPLAY:
|
||||
state = getStringTypeState(processedData.get(i).frontText);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||
updateState(channelUID, state);
|
||||
} else {
|
||||
logger.debug("No real-time data available to update channel '{}' of group '{}'.", channelId,
|
||||
channelGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the channel from the last Entur data retrieved.
|
||||
*
|
||||
* @param channelUID the id identifying the channel to be updated
|
||||
*/
|
||||
private void updateStopPlaceChannel(ChannelUID channelUID) {
|
||||
String channelId = channelUID.getIdWithoutGroup();
|
||||
String channelGroupId = channelUID.getGroupId();
|
||||
if (!processedData.isEmpty()) {
|
||||
State state = UnDefType.UNDEF;
|
||||
switch (channelId) {
|
||||
case EnturNoBindingConstants.CHANNEL_STOP_ID:
|
||||
state = getStringTypeState(processedData.get(0).stopPlaceId);
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_STOP_NAME:
|
||||
state = getStringTypeState(processedData.get(0).stopName);
|
||||
break;
|
||||
case EnturNoBindingConstants.CHANNEL_STOP_TRANSPORT_MODE:
|
||||
state = getStringTypeState(processedData.get(0).transportMode);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
logger.debug("Update channel '{}' of group '{}' with new state '{}'.", channelId, channelGroupId, state);
|
||||
updateState(channelUID, state);
|
||||
} else {
|
||||
logger.debug("No real-time data available to update channel '{}' of group '{}'.", channelId,
|
||||
channelGroupId);
|
||||
}
|
||||
}
|
||||
|
||||
private State getDateTimeTypeState(@Nullable String value) {
|
||||
return (value == null) ? UnDefType.UNDEF
|
||||
: new DateTimeType(ZonedDateTime.parse(value, DateTimeFormatter.ISO_DATE_TIME)
|
||||
.withZoneSameInstant(ZoneId.of(EnturNoBindingConstants.TIME_ZONE)));
|
||||
}
|
||||
|
||||
private State getStringTypeState(@Nullable String value) {
|
||||
return (value == null) ? UnDefType.UNDEF : new StringType(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.enturno.internal;
|
||||
|
||||
import static org.openhab.binding.enturno.internal.EnturNoBindingConstants.LINESTOP;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.openhab.core.io.net.http.HttpClientFactory;
|
||||
import org.openhab.core.thing.Thing;
|
||||
import org.openhab.core.thing.ThingTypeUID;
|
||||
import org.openhab.core.thing.binding.BaseThingHandlerFactory;
|
||||
import org.openhab.core.thing.binding.ThingHandler;
|
||||
import org.openhab.core.thing.binding.ThingHandlerFactory;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
|
||||
/**
|
||||
* The {@link EnturNoHandlerFactory} is responsible for creating things and thing
|
||||
* handlers.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
@Component(configurationPid = "binding.enturno", service = ThingHandlerFactory.class)
|
||||
public class EnturNoHandlerFactory extends BaseThingHandlerFactory {
|
||||
|
||||
private static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections.singleton(LINESTOP);
|
||||
|
||||
private final HttpClient httpClient;
|
||||
|
||||
@Activate
|
||||
public EnturNoHandlerFactory(@Reference final HttpClientFactory httpClientFactory) {
|
||||
this.httpClient = httpClientFactory.getCommonHttpClient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsThingType(ThingTypeUID thingTypeUID) {
|
||||
return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable ThingHandler createHandler(Thing thing) {
|
||||
ThingTypeUID thingTypeUID = thing.getThingTypeUID();
|
||||
|
||||
if (LINESTOP.equals(thingTypeUID)) {
|
||||
return new EnturNoHandler(thing, httpClient);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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.enturno.internal.connection;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EnturCommunicationException} is a communication exception for the connections to Entur API.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturCommunicationException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EnturCommunicationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EnturCommunicationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -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.enturno.internal.connection;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
|
||||
/**
|
||||
* The {@link EnturConfigurationException} is a configuration exception for the connections to Entur API.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturConfigurationException extends IllegalArgumentException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public EnturConfigurationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public EnturConfigurationException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public EnturConfigurationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/**
|
||||
* 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.enturno.internal.connection;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
import static org.eclipse.jetty.http.HttpMethod.POST;
|
||||
import static org.eclipse.jetty.http.HttpStatus.*;
|
||||
import static org.openhab.binding.enturno.internal.EnturNoBindingConstants.TIME_ZONE;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.client.api.Request;
|
||||
import org.eclipse.jetty.client.util.StringContentProvider;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.openhab.binding.enturno.internal.EnturNoConfiguration;
|
||||
import org.openhab.binding.enturno.internal.EnturNoHandler;
|
||||
import org.openhab.binding.enturno.internal.model.EnturJsonData;
|
||||
import org.openhab.binding.enturno.internal.model.estimated.EstimatedCalls;
|
||||
import org.openhab.binding.enturno.internal.model.simplified.DisplayData;
|
||||
import org.openhab.binding.enturno.internal.model.stopplace.StopPlace;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* The {@link EnturNoConnection} is responsible for handling connection to Entur.no API
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
@NonNullByDefault
|
||||
public class EnturNoConnection {
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(EnturNoConnection.class);
|
||||
private static final String REQUEST_BODY = "realtime_request.graphql";
|
||||
private static final String PROPERTY_MESSAGE = "message";
|
||||
private static final String CONTENT_TYPE = "application/graphql";
|
||||
private static final String REQUIRED_CLIENT_NAME_HEADER = "ET-Client-Name";
|
||||
private static final String REQUIRED_CLIENT_NAME = "openHAB-enturnobinding";
|
||||
|
||||
private static final String PARAM_STOPID = "stopid";
|
||||
private static final String PARAM_START_DATE_TIME = "startDateTime";
|
||||
|
||||
private static final String REALTIME_URL = "https://api.entur.io/journey-planner/v2/graphql";
|
||||
|
||||
private final EnturNoHandler handler;
|
||||
private final HttpClient httpClient;
|
||||
|
||||
private final JsonParser parser = new JsonParser();
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
public EnturNoConnection(EnturNoHandler handler, HttpClient httpClient) {
|
||||
this.handler = handler;
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the real-time timetable for specified line and stop place
|
||||
*
|
||||
* @param stopPlaceId stop place id see https://en-tur.no
|
||||
* @return the real-time timetable
|
||||
* @throws JsonSyntaxException
|
||||
* @throws EnturCommunicationException
|
||||
* @throws EnturConfigurationException
|
||||
*/
|
||||
public synchronized List<DisplayData> getEnturTimeTable(@Nullable String stopPlaceId, @Nullable String lineCode)
|
||||
throws JsonSyntaxException, EnturConfigurationException, EnturCommunicationException {
|
||||
if (StringUtils.isBlank(stopPlaceId)) {
|
||||
throw new EnturConfigurationException("Stop place id cannot be empty or null");
|
||||
} else if (lineCode == null || StringUtils.isBlank(lineCode)) {
|
||||
throw new EnturConfigurationException("Line code cannot be empty or null");
|
||||
}
|
||||
|
||||
Map<String, String> params = getRequestParams(handler.getEnturNoConfiguration());
|
||||
|
||||
EnturJsonData enturJsonData = gson.fromJson(getResponse(REALTIME_URL, params), EnturJsonData.class);
|
||||
|
||||
if (enturJsonData == null) {
|
||||
throw new EnturCommunicationException("Error when deserializing response to EnturJsonData.class");
|
||||
}
|
||||
|
||||
return processData(enturJsonData.data.stopPlace, lineCode);
|
||||
}
|
||||
|
||||
private Map<String, String> getRequestParams(EnturNoConfiguration config) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
params.put(PARAM_STOPID, StringUtils.trimToEmpty(config.getStopPlaceId()));
|
||||
params.put(PARAM_START_DATE_TIME, StringUtils.trimToEmpty(LocalDateTime.now(ZoneId.of(TIME_ZONE)).toString()));
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
private String getResponse(String url, Map<String, String> params) {
|
||||
try {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Entur request: URL = '{}', graphQL parameters -> startTime = '{}', stopId = '{}'",
|
||||
REALTIME_URL, params.get(PARAM_START_DATE_TIME), params.get(PARAM_STOPID));
|
||||
}
|
||||
|
||||
Request request = httpClient.newRequest(url);
|
||||
request.method(POST);
|
||||
request.timeout(10, TimeUnit.SECONDS);
|
||||
request.header(HttpHeader.CONTENT_TYPE, CONTENT_TYPE);
|
||||
request.header(REQUIRED_CLIENT_NAME_HEADER, REQUIRED_CLIENT_NAME);
|
||||
request.content(new StringContentProvider(getRequestBody(params)));
|
||||
|
||||
logger.trace("Request body: {}", getRequestBody(params));
|
||||
|
||||
ContentResponse contentResponse = request.send();
|
||||
|
||||
int httpStatus = contentResponse.getStatus();
|
||||
String content = contentResponse.getContentAsString();
|
||||
String errorMessage = StringUtils.EMPTY;
|
||||
logger.trace("Entur response: status = {}, content = '{}'", httpStatus, content);
|
||||
switch (httpStatus) {
|
||||
case OK_200:
|
||||
return content;
|
||||
case BAD_REQUEST_400:
|
||||
case NOT_FOUND_404:
|
||||
errorMessage = getErrorMessage(content);
|
||||
logger.debug("Entur server responded with status code {}: {}", httpStatus, errorMessage);
|
||||
throw new EnturConfigurationException(errorMessage);
|
||||
default:
|
||||
errorMessage = getErrorMessage(content);
|
||||
logger.debug("Entur server responded with status code {}: {}", httpStatus, errorMessage);
|
||||
throw new EnturCommunicationException(errorMessage);
|
||||
}
|
||||
} catch (ExecutionException e) {
|
||||
String errorMessage = e.getLocalizedMessage();
|
||||
logger.debug("Exception occurred during execution: {}", errorMessage, e);
|
||||
throw new EnturCommunicationException(errorMessage, e);
|
||||
} catch (InterruptedException | TimeoutException | IOException e) {
|
||||
logger.debug("Exception occurred during execution: {}", e.getLocalizedMessage(), e);
|
||||
throw new EnturCommunicationException(e.getLocalizedMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getErrorMessage(String response) {
|
||||
JsonObject jsonResponse = parser.parse(response).getAsJsonObject();
|
||||
if (jsonResponse.has(PROPERTY_MESSAGE)) {
|
||||
return jsonResponse.get(PROPERTY_MESSAGE).getAsString();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
private String getRequestBody(Map<String, String> params) throws IOException {
|
||||
try (InputStream inputStream = EnturNoConnection.class.getClassLoader().getResourceAsStream(REQUEST_BODY);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
|
||||
String json = bufferedReader.lines().collect(Collectors.joining("\n"));
|
||||
|
||||
return json.replaceAll("\\{stopPlaceId}", "" + params.get(PARAM_STOPID)).replaceAll("\\{startDateTime}",
|
||||
"" + params.get(PARAM_START_DATE_TIME));
|
||||
}
|
||||
}
|
||||
|
||||
private List<DisplayData> processData(StopPlace stopPlace, String lineCode) {
|
||||
Map<String, List<EstimatedCalls>> departures = stopPlace.estimatedCalls.stream()
|
||||
.filter(call -> StringUtils.equalsIgnoreCase(
|
||||
StringUtils.trimToEmpty(call.serviceJourney.journeyPattern.line.publicCode),
|
||||
StringUtils.trimToEmpty(lineCode)))
|
||||
.collect(groupingBy(call -> call.quay.id));
|
||||
|
||||
List<DisplayData> processedData = new ArrayList<>();
|
||||
if (departures.keySet().size() > 0) {
|
||||
DisplayData processedData01 = getDisplayData(stopPlace, departures, 0);
|
||||
processedData.add(processedData01);
|
||||
}
|
||||
|
||||
if (departures.keySet().size() > 1) {
|
||||
DisplayData processedData02 = getDisplayData(stopPlace, departures, 1);
|
||||
processedData.add(processedData02);
|
||||
}
|
||||
|
||||
return processedData;
|
||||
}
|
||||
|
||||
private DisplayData getDisplayData(StopPlace stopPlace, Map<String, List<EstimatedCalls>> departures,
|
||||
int quayIndex) {
|
||||
List<String> keys = new ArrayList<>(departures.keySet());
|
||||
DisplayData processedData = new DisplayData();
|
||||
List<EstimatedCalls> quayCalls = departures.get(keys.get(quayIndex));
|
||||
List<String> departureTimes = quayCalls.stream().map(eq -> eq.expectedDepartureTime).map(this::getIsoDateTime)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<String> estimatedFlags = quayCalls.stream().map(es -> es.realtime).collect(Collectors.toList());
|
||||
|
||||
if (quayCalls.size() > quayIndex) {
|
||||
String lineCode = quayCalls.get(0).serviceJourney.journeyPattern.line.publicCode;
|
||||
String frontText = quayCalls.get(0).destinationDisplay.frontText;
|
||||
processedData.lineCode = lineCode;
|
||||
processedData.frontText = frontText;
|
||||
processedData.departures = departureTimes;
|
||||
processedData.estimatedFlags = estimatedFlags;
|
||||
}
|
||||
|
||||
processedData.stopPlaceId = stopPlace.id;
|
||||
processedData.stopName = stopPlace.name;
|
||||
processedData.transportMode = stopPlace.transportMode;
|
||||
return processedData;
|
||||
}
|
||||
|
||||
private String getIsoDateTime(String dateTimeWithoutColonInZone) {
|
||||
String dateTime = StringUtils.substringBeforeLast(dateTimeWithoutColonInZone, "+");
|
||||
String offset = StringUtils.substringAfterLast(dateTimeWithoutColonInZone, "+");
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
return builder.append(dateTime).append("+").append(StringUtils.substring(offset, 0, 2)).append(":00")
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.enturno.internal.model;
|
||||
|
||||
import org.openhab.binding.enturno.internal.model.stopplace.StopPlace;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Data} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class Data {
|
||||
public StopPlace stopPlace;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.enturno.internal.model;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Data} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class EnturData {
|
||||
public Data data;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.enturno.internal.model;
|
||||
|
||||
/**
|
||||
* {@link EnturJsonData} is a root level class to holding reference of data generated from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class EnturJsonData {
|
||||
public Data data;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link DestinationDisplay} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class DestinationDisplay {
|
||||
public String frontText;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link EstimatedCalls} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class EstimatedCalls {
|
||||
public String aimedArrivalTime;
|
||||
|
||||
public String date;
|
||||
|
||||
public String realtime;
|
||||
|
||||
public String expectedDepartureTime;
|
||||
|
||||
public String forAlighting;
|
||||
|
||||
public DestinationDisplay destinationDisplay;
|
||||
|
||||
public String forBoarding;
|
||||
|
||||
public ServiceJourney serviceJourney;
|
||||
|
||||
public Quay quay;
|
||||
|
||||
public String aimedDepartureTime;
|
||||
|
||||
public String expectedArrivalTime;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link JourneyPattern} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class JourneyPattern {
|
||||
public Line line;
|
||||
}
|
||||
@@ -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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Line} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class Line {
|
||||
public String name;
|
||||
|
||||
public String transportMode;
|
||||
|
||||
public String publicCode;
|
||||
|
||||
public String id;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link Quay} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class Quay {
|
||||
public String publicCode;
|
||||
|
||||
public String id;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.estimated;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link ServiceJourney} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class ServiceJourney {
|
||||
public JourneyPattern journeyPattern;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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.enturno.internal.model.simplified;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link DisplayData} is a Plain Old Java Objects class to wrap only needed data after processing API call results.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class DisplayData {
|
||||
public String stopPlaceId;
|
||||
|
||||
public String stopName;
|
||||
|
||||
public String transportMode;
|
||||
|
||||
public String lineCode;
|
||||
|
||||
public String frontText;
|
||||
|
||||
public List<String> departures;
|
||||
|
||||
public List<String> estimatedFlags;
|
||||
}
|
||||
@@ -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.enturno.internal.model.stopplace;
|
||||
|
||||
import org.openhab.binding.enturno.internal.model.estimated.EstimatedCalls;
|
||||
|
||||
/**
|
||||
* Generated Plain Old Java Objects class for {@link StopPlace} from JSON.
|
||||
*
|
||||
* @author Michal Kloc - Initial contribution
|
||||
*/
|
||||
public class StopPlace {
|
||||
public java.util.List<EstimatedCalls> estimatedCalls;
|
||||
|
||||
public String name;
|
||||
|
||||
public String id;
|
||||
|
||||
public String transportMode;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<binding:binding id="enturno" 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>Entur Binding</name>
|
||||
<description>Real-time timetable binding for Norwegian public transport operators.</description>
|
||||
<author>Michal Kloc</author>
|
||||
|
||||
</binding:binding>
|
||||
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<config-description:config-descriptions
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:config-description="https://openhab.org/schemas/config-description/v1.0.0"
|
||||
xsi:schemaLocation="https://openhab.org/schemas/config-description/v1.0.0 https://openhab.org/schemas/config-description-1.0.0.xsd">
|
||||
|
||||
<!-- Config for EnturTimeTable Binding -->
|
||||
<config-description uri="thing-type:enturno:linestop">
|
||||
<parameter name="stopPlaceId" type="text" required="true">
|
||||
<label>Stop Code</label>
|
||||
<description>Stop code that can be find here https://en-tur.no (id in link when stop is chosen).</description>
|
||||
</parameter>
|
||||
<parameter name="lineCode" type="text" required="true">
|
||||
<label>Line Code</label>
|
||||
<description>Line code that can be find here https://en-tur.no (displayed when departures for stop are chosen).</description>
|
||||
</parameter>
|
||||
</config-description>
|
||||
|
||||
</config-description:config-descriptions>
|
||||
@@ -0,0 +1,3 @@
|
||||
# thing status
|
||||
offline.conf-error-missing-stopId = The 'stopId' parameter must be configured.
|
||||
offline.conf-error-missing-lineCode = The 'lineCode' parameter must be configured.
|
||||
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="enturno"
|
||||
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">
|
||||
|
||||
<!-- Channel groups for EnturTimeTable Binding -->
|
||||
<channel-group-type id="stopPlace">
|
||||
<label>Stop Place</label>
|
||||
<description>This is a stop place.</description>
|
||||
<channels>
|
||||
<channel id="id" typeId="stop-id"/>
|
||||
<channel id="name" typeId="stop-name"/>
|
||||
<channel id="transportMode" typeId="stop-transport-mode"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<channel-group-type id="direction">
|
||||
<label>Line Direction</label>
|
||||
<description>This is the data for public transport line direction.</description>
|
||||
<channels>
|
||||
<channel id="lineCode" typeId="line-code"/>
|
||||
<channel id="frontDisplayText" typeId="front-display"/>
|
||||
<channel id="departure01" typeId="departure"/>
|
||||
<channel id="departure02" typeId="departure"/>
|
||||
<channel id="departure03" typeId="departure"/>
|
||||
<channel id="departure04" typeId="departure"/>
|
||||
<channel id="departure05" typeId="departure"/>
|
||||
<channel id="estimatedFlag01" typeId="is-real"/>
|
||||
<channel id="estimatedFlag02" typeId="is-real"/>
|
||||
<channel id="estimatedFlag03" typeId="is-real"/>
|
||||
<channel id="estimatedFlag04" typeId="is-real"/>
|
||||
<channel id="estimatedFlag05" typeId="is-real"/>
|
||||
</channels>
|
||||
</channel-group-type>
|
||||
|
||||
<!-- Channels for EnturTimeTable Binding -->
|
||||
<channel-type id="departure">
|
||||
<item-type>DateTime</item-type>
|
||||
<label>Departure Time</label>
|
||||
<description>Time of departure.</description>
|
||||
<category>Time</category>
|
||||
<state readOnly="true" pattern="%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="line-code">
|
||||
<item-type>String</item-type>
|
||||
<label>Line Code</label>
|
||||
<description>Code (usually number) of the public transport line.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="is-real">
|
||||
<item-type>String</item-type>
|
||||
<label>Estimated Flag</label>
|
||||
<description>Whether departure time is calculated/estimated or as in printed timetable (true/false).</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="front-display">
|
||||
<item-type>String</item-type>
|
||||
<label>Front Display</label>
|
||||
<description>Front display usually shows direction of the line.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="stop-id">
|
||||
<item-type>String</item-type>
|
||||
<label>Stop Id</label>
|
||||
<description>Id of the stop place.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="stop-name">
|
||||
<item-type>String</item-type>
|
||||
<label>Stop Name</label>
|
||||
<description>Name of the stop place.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
<channel-type id="stop-transport-mode">
|
||||
<item-type>String</item-type>
|
||||
<label>Stop Transport Mode</label>
|
||||
<description>Bus/Tramway/Plane etc.</description>
|
||||
<state readOnly="true"/>
|
||||
</channel-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<thing:thing-descriptions bindingId="enturno"
|
||||
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">
|
||||
|
||||
<!-- LineStop Type -->
|
||||
<thing-type id="linestop">
|
||||
<label>Entur Timetable</label>
|
||||
<description>Provides real-time (estimated) departure timetable for chosen public transport line and stop in Norway.
|
||||
Data provided by Entur.no API.</description>
|
||||
|
||||
<channel-groups>
|
||||
<channel-group id="stopPlace" typeId="stopPlace"/>
|
||||
<channel-group id="Direction01" typeId="direction">
|
||||
<label>Direction 1</label>
|
||||
<description>This is the real-time table for direction nr 1.</description>
|
||||
</channel-group>
|
||||
<channel-group id="Direction02" typeId="direction">
|
||||
<label>Direction 2</label>
|
||||
<description>This is the real-time table for direction nr 2.</description>
|
||||
</channel-group>
|
||||
</channel-groups>
|
||||
|
||||
<config-description-ref uri="thing-type:enturno:linestop"/>
|
||||
|
||||
</thing-type>
|
||||
|
||||
</thing:thing-descriptions>
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
stopPlace(id: "{stopPlaceId}") {
|
||||
id
|
||||
name
|
||||
transportMode
|
||||
estimatedCalls(startTime:"{startDateTime}" timeRange: 86400, numberOfDepartures: 400) {
|
||||
realtime
|
||||
aimedArrivalTime
|
||||
aimedDepartureTime
|
||||
expectedArrivalTime
|
||||
expectedDepartureTime
|
||||
date
|
||||
forBoarding
|
||||
forAlighting
|
||||
destinationDisplay {
|
||||
frontText
|
||||
}
|
||||
quay {
|
||||
id
|
||||
publicCode
|
||||
}
|
||||
serviceJourney {
|
||||
journeyPattern {
|
||||
line {
|
||||
id
|
||||
name
|
||||
transportMode
|
||||
publicCode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user