Skip to content

Commit

Permalink
Code review correctiong
Browse files Browse the repository at this point in the history
Added i18n data to get prepared for crowdin

Signed-off-by: clinique <gael@lhopital.org>
  • Loading branch information
clinique committed Nov 20, 2021
1 parent 4395608 commit 1a0e335
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 39 deletions.
15 changes: 9 additions & 6 deletions bundles/org.openhab.binding.sncf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,27 @@
The SNCF binding provides real-time data for each train, bus, tramway... station in France.
This is based on live API provided by DIGITALSNCF.

Get you API key at https://www.digital.sncf.com/startup/api/token-developpeur
Get your API key on [DIGITALSNCF web site](https://www.digital.sncf.com/startup/api/token-developpeur)

Note : SNCF Api is based on the open [API Navitia](https://doc.navitia.io/#getting-started). This binding uses a very small subset of it, restricted to its primary purpose.
Note : SNCF Api is based on the open [API Navitia](https://doc.navitia.io/#getting-started).
This binding uses a very small subset of it, restricted to its primary purpose.

## Supported Things

Bridge: The binding supports a bridge to connect to the [DIGITALSNCF service](https://www.digital.sncf.com/startup/api/token-developpeur). A bridge uses the thing ID "api".
Bridge: The binding supports a bridge to connect to the [DIGITALSNCF service](https://www.digital.sncf.com/startup/api/token developpeur).
A bridge uses the thing ID "api".

Station: Represents a given bus, train station.

Of course, you can add multiple as many stations as needed.
Of course, you can add as many stations as needed.


## Discovery

This binding takes care of auto discovery. This method is strongly recommended as its the only way to get proper station ID depending upon transportation type.
This binding takes care of auto discovery. This method is strongly recommended as it is the only way to get proper station ID depending upon transportation type.

To enable auto-discovery, your location system setting must be defined. Once done, at first launch discovery will search every station in a radius of 2500 m around the system, extending it by step of 500 m until it finds a first set of results.
To enable auto-discovery, your location system setting must be defined.
Once done, at first launch, discovery will search every station in a radius of 2000 m around the system, extending it by step of 500 m until it finds a first set of results.
Every following manual successive launch will extend this radius by 500 m, increasing the number of stations discovered.


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ public class SncfBindingConstants {
public static final ThingTypeUID APIBRIDGE_THING_TYPE = new ThingTypeUID(BINDING_ID, "api");
public static final ThingTypeUID STATION_THING_TYPE = new ThingTypeUID(BINDING_ID, "station");

// List of all adressable things in OH = SUPPORTED_DEVICE_THING_TYPES_UIDS + the virtual bridge
// List of all adressable things
public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Set.of(APIBRIDGE_THING_TYPE, STATION_THING_TYPE);
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@
@Component(service = ThingHandlerService.class)
@NonNullByDefault
public class SncfDiscoveryService extends AbstractDiscoveryService implements ThingHandlerService {
private final Logger logger = LoggerFactory.getLogger(SncfDiscoveryService.class);

private static final int SEARCH_TIME = 2;

private final Logger logger = LoggerFactory.getLogger(SncfDiscoveryService.class);

private @Nullable LocationProvider locationProvider;
private @Nullable SncfBridgeHandler bridgeHandler;

Expand All @@ -68,7 +68,7 @@ public void startScan() {
if (provider != null && handler != null) {
PointType location = provider.getLocation();
if (location != null) {
ThingUID bridgeId = handler.getThing().getUID();
ThingUID bridgeUID = handler.getThing().getUID();
searchRange += 500;
try {
List<PlaceNearby> places = handler.discoverNearby(location, searchRange);
Expand All @@ -77,8 +77,8 @@ public void startScan() {
String placeId = place.id;
String thingId = placeId.replace(":", "_").replace("-", "_").replace("stop_point_", "");
thingDiscovered(
DiscoveryResultBuilder.create(new ThingUID(STATION_THING_TYPE, bridgeId, thingId))
.withLabel(place.stopPoint.name).withBridge(bridgeId)
DiscoveryResultBuilder.create(new ThingUID(STATION_THING_TYPE, bridgeUID, thingId))
.withLabel(place.stopPoint.name).withBridge(bridgeUID)
.withRepresentationProperty(STOP_POINT_ID)
.withProperty(STOP_POINT_ID, placeId).build());
});
Expand All @@ -93,7 +93,6 @@ public void startScan() {
logger.info("Please set a system location to enable station discovery");
}
}
stopScan();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link Coord} class holds latitude and longitude of a point
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link Route} class holds Route details
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link StopArea} class holds informations for a Stop Area
* (usually a train station)
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link StopDateTime} class holds informations for a transportation stop
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link StopPoint} class holds informations for a train station
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
package org.openhab.binding.sncf.internal.dto;

/**
* The {@link VJDisplayInformation} class holds informations displayed
* to traveller regarding a stop in the station
*
* @author Gaël L'hopital - Initial contribution
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpResponseException;
import org.eclipse.jetty.client.api.ContentResponse;
import org.openhab.binding.sncf.internal.SncfException;
import org.openhab.binding.sncf.internal.discovery.SncfDiscoveryService;
Expand All @@ -45,6 +44,7 @@
import org.openhab.core.thing.Bridge;
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;
Expand Down Expand Up @@ -84,7 +84,11 @@ public SncfBridgeHandler(Bridge bridge, Gson gson, LocationProvider locationProv
public void initialize() {
logger.debug("Initializing SNCF API bridge handler.");
apiId = (String) getConfig().get("apiID");
updateStatus(ThingStatus.ONLINE);
if (apiId != null && apiId.length() != 0) {
updateStatus(ThingStatus.ONLINE);
} else {
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "@text/null-or-empty-api-key");
}
}

@Override
Expand Down Expand Up @@ -130,16 +134,7 @@ private String getResponse(String url) throws SncfException {
logger.debug("SNCF Api server responded with status code {}: {}", httpStatus, content);
throw new SncfException(content);
}
} catch (ExecutionException e) {
String errorMessage = e.getLocalizedMessage();
logger.trace("Exception occurred during execution: {}", errorMessage, e);
if (e.getCause() instanceof HttpResponseException) {
logger.debug("SNCF Api server responded with status code {}: Invalid API key.", UNAUTHORIZED_401);
throw new SncfException("@text/offline.conf-error-invalid-apikey", e.getCause());
} else {
throw new SncfException(errorMessage, e.getCause());
}
} catch (TimeoutException e) {
} catch (TimeoutException | ExecutionException e) {
logger.debug("Exception occurred during execution: {}", e.getLocalizedMessage(), e);
throw new SncfException(e.getLocalizedMessage(), e.getCause());
} catch (InterruptedException e) {
Expand Down Expand Up @@ -167,7 +162,8 @@ public Optional<Passage> getNextPassage(String stopPointId, String expected) thr
String URL = String.format(Locale.US, "%s/stop_points/%s/%s?disable_geojson=true&count=1", SERVICE_URL,
stopPointId, expected);
List<Passage> passages = getResponseFromCache(URL, Passages.class).passages;
return passages != null ? Optional.ofNullable(passages.get(0)) : Optional.empty();
return passages != null ? passages.size() > 0 ? Optional.ofNullable(passages.get(0)) : Optional.empty()
: Optional.empty();
}

public LocationProvider getLocationProvider() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,23 +130,29 @@ private void queryApiAndUpdateChannels() {
SncfBridgeHandler bridgeHandler = getBridgeHandler();
if (bridgeHandler != null) {
try {
bridgeHandler.getNextPassage(stationId, GROUP_DEPARTURE).ifPresent(departure -> {
bridgeHandler.getNextPassage(stationId, GROUP_DEPARTURE).ifPresentOrElse(departure -> {
getThing().getChannels().stream().map(Channel::getUID).filter(
channelUID -> isLinked(channelUID) && GROUP_DEPARTURE.equals(channelUID.getGroupId()))
.forEach(channelUID -> {
State state = getValue(channelUID.getIdWithoutGroup(), departure, GROUP_DEPARTURE);
updateState(channelUID, state);
});
scheduleRefresh(fromDTO(departure.stopDateTime.departureDateTime));
}, () -> {
logger.debug("No {} available", GROUP_DEPARTURE);
scheduleRefresh(ZonedDateTime.now().plusMinutes(5));
});
bridgeHandler.getNextPassage(stationId, GROUP_ARRIVAL).ifPresent(arrival -> {
bridgeHandler.getNextPassage(stationId, GROUP_ARRIVAL).ifPresentOrElse(arrival -> {
getThing().getChannels().stream().map(Channel::getUID)
.filter(channelUID -> isLinked(channelUID) && GROUP_ARRIVAL.equals(channelUID.getGroupId()))
.forEach(channelUID -> {
State state = getValue(channelUID.getIdWithoutGroup(), arrival, GROUP_ARRIVAL);
updateState(channelUID, state);
});
scheduleRefresh(fromDTO(arrival.stopDateTime.arrivalDateTime));
}, () -> {
logger.debug("No {} available", GROUP_ARRIVAL);
scheduleRefresh(ZonedDateTime.now().plusMinutes(5));
});
updateStatus(ThingStatus.ONLINE);
} catch (SncfException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<config-description uri="thing-type:sncf:api">
<parameter name="apiID" type="text">
<label>API ID</label>
<description>Your Sncf API ID</description>
<required>true</required>
<context>password</context>
</parameter>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

binding.sncf.name = SNCF Binding
binding.sncf.description = Retrieves French railway informations

config.thing-type.sncf.api.apiID.label = API ID
config.thing-type.sncf.api.apiID.description = Your Sncf API ID

thing-type.sncf.api.label = SNCF API
thing-type.sncf.api.description = This bridge represents the gateway to Sncf API.

thing-type.sncf.station.label = Station
thing-type.sncf.station.description = This represents a station hosting some transportation mode.

channel-type.sncf.direction.label = Direction
channel-type.sncf.direction.description = The direction of this route.
channel-type.sncf.code.label = Code
channel-type.sncf.code.description = Code of the line.
channel-type.sncf.name.label = Name
channel-type.sncf.name.description = Name of the line.
channel-type.sncf.network.label = Network
channel-type.sncf.network.description = Name of the transportation network.
channel-type.sncf.commercialMode.label = Commercial Mode
channel-type.sncf.commercialMode.description = Commercial modes are close from physical modes, but not normalized and can refer to a brand, something that can be specific to a network, and known to the traveler.
channel-type.sncf.timestamp.label = Timestamp
channel-type.sncf.timestamp.description = Timestamp of the future event.

# Error messages
null-or-empty-api-key = Null or empty API ID
error-invalid-apikey = Invalid API ID
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

<bridge-type id="api">
<label>SNCF API</label>
<description>This bridge represents the gateway to Sncf API.</description>
<config-description-ref uri="thing-type:sncf:api"/>
</bridge-type>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
<config-description>
<parameter name="stopPointId" type="text" required="true">
<label>Station ID</label>
<description>Identifier of the station</description>
</parameter>
</config-description>
</thing-type>
Expand All @@ -40,51 +39,43 @@
<channel id="network" typeId="network"/>
<channel id="timestamp" typeId="timestamp">
<label>Horodatage</label>
<description>Date et heure de l'évènement</description>
</channel>
</channels>
</channel-group-type>

<channel-type id="direction">
<item-type>String</item-type>
<label>Direction</label>
<description>The direction of this route</description>
<state readOnly="true"></state>
</channel-type>

<channel-type id="code">
<item-type>String</item-type>
<label>Code</label>
<description>Code name of the line</description>
<state readOnly="true"></state>
</channel-type>

<channel-type id="name">
<item-type>String</item-type>
<label>Name</label>
<description>Name of the line</description>
<state readOnly="true"></state>
</channel-type>

<channel-type id="network">
<item-type>String</item-type>
<label>Network</label>
<description>Name of the network</description>
<state readOnly="true"></state>
</channel-type>

<channel-type id="commercialMode">
<item-type>String</item-type>
<label>Commercial Mode</label>
<description>Commercial modes are close from physical modes, but not normalized and can refer to a brand, something
that can be specific to a network, and known to the traveler.</description>
<state readOnly="true"></state>
</channel-type>

<channel-type id="timestamp">
<item-type>DateTime</item-type>
<label>Timestamp</label>
<description>Data timestamp</description>
<state readOnly="true"/>
</channel-type>

Expand Down
38 changes: 38 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,44 @@ Import-Package: \\
</configuration>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>transform</goal>
</goals>
</execution>
</executions>
<configuration>
<transformationSets>
<transformationSet>
<dir>${project.basedir}/src/main/resources/OH-INF/</dir>
<!-- *.xml -->
<includes>
<include>**/*.xml</include>
</includes>
<outputDir>${project.basedir}/src/main/resources/OH-INF/i18n</outputDir>
<stylesheet>${project.basedir}/../../tools/i18n/i18n.xsl</stylesheet>
<outputProperties>
<outputProperty>
<name>omit-xml-declaration</name>
<value>yes</value>
</outputProperty>
</outputProperties>
<fileMappers>
<fileMapper
implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
<targetExtension>properties</targetExtension>
</fileMapper>
</fileMappers>
</transformationSet>
</transformationSets>
</configuration>
</plugin>

<plugin>
<groupId>org.openhab.tools.sat</groupId>
<artifactId>sat-plugin</artifactId>
Expand Down

0 comments on commit 1a0e335

Please sign in to comment.