Skip to content

Commit

Permalink
[SNCF] A binding to get French railways arrivals and departures (open…
Browse files Browse the repository at this point in the history
…hab#11607)

* SNCF : new binding

Signed-off-by: clinique <gael@lhopital.org>
Signed-off-by: Andras Uhrin <andras.uhrin@gmail.com>
  • Loading branch information
clinique authored and andrasU committed Nov 12, 2022
1 parent b572a85 commit 1639b7c
Show file tree
Hide file tree
Showing 30 changed files with 1,285 additions and 0 deletions.
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@
/bundles/org.openhab.binding.smartmeter/ @msteigenberger
/bundles/org.openhab.binding.smartthings/ @BobRak
/bundles/org.openhab.binding.smhi/ @pacive
/bundles/org.openhab.binding.sncf/ @clinique
/bundles/org.openhab.binding.snmp/ @openhab/add-ons-maintainers
/bundles/org.openhab.binding.solaredge/ @alexf2015
/bundles/org.openhab.binding.solarlog/ @johannrichard
Expand Down
5 changes: 5 additions & 0 deletions bom/openhab-addons/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,11 @@
<artifactId>org.openhab.binding.smhi</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.sncf</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.binding.snmp</artifactId>
Expand Down
13 changes: 13 additions & 0 deletions bundles/org.openhab.binding.sncf/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
This content is produced and maintained by the openHAB project.

* Project home: https://www.openhab.org

== Declared Project Licenses

This program and the accompanying materials are made available under the terms
of the Eclipse Public License 2.0 which is available at
https://www.eclipse.org/legal/epl-2.0/.

== Source Code

https://github.com/openhab/openhab-addons
87 changes: 87 additions & 0 deletions bundles/org.openhab.binding.sncf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# SNCF Binding

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 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.

(*) According to DIGITALSNCF Transilien may only be available for schedule, maybe not real-time.

## 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".

Station: Represents a given bus, train station.

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


## Discovery

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 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.


## Binding Configuration

The binding has no configuration options, all configuration is done at Thing level.

## Bridge Configuration

The bridge configuration only holds the api key :

| Parameter | Description |
|-----------|----------------------------------------------------------------|
| apiID | API ID provided by the DIGITALSNCF service. Mandatory. |

## Thing Configuration

The 'Station' thing has only one configuration parameter:

| Parameter | Description |
|-------------|--------------------------------------------------------------|
| stopPointId | Identifier of the station in the DIGITALSNCF network. |

The thing will auto-update depending on the timestamp of the earliest event detected to trigger (arrival or departure).

## Channels

The Station thing holds two groups of channels (arrivals and departures) containing these channels:

| Channel ID | Item Type | Description |
|-----------------------|-----------|--------------------------------------------------|
| direction | String | The direction of the route |
| lineName | String | Commercial name of the line |
| name | String | Name of the line |
| network | String | Name of the network ruling the line |
| timestamp | DateTime | Timestamp of the event (departure, arrival) |

## Full Example

sncf.things:

```
Bridge sncf:api:8901d44a68 "Bridge" [apiID="xxx-yyy-zzz"] {
station MyHouse "Krakow"[stopPointId="stop_point:SNCF:87561951:Bus"]
}
```

sncf.items:

```
String Arrival_Direction { channel="sncf:station:8901d44a68:87381475_RapidTransit:arrivals#direction" }
String Arrival_Line { channel="sncf:station:8901d44a68:87381475_RapidTransit:arrivals#lineName" }
DateTime Arrival_Time { channel="sncf:station:8901d44a68:87381475_RapidTransit:arrivals#timestamp" }
String Departure_Direction { channel="sncf:station:8901d44a68:87381475_RapidTransit:departures#direction" }
String Departure_Line { channel="sncf:station:8901d44a68:87381475_RapidTransit:departures#lineName" }
DateTime Departure_Time { channel="sncf:station:8901d44a68:87381475_RapidTransit:departures#timestamp" }
```

17 changes: 17 additions & 0 deletions bundles/org.openhab.binding.sncf/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.openhab.addons.bundles</groupId>
<artifactId>org.openhab.addons.reactor.bundles</artifactId>
<version>3.2.0-SNAPSHOT</version>
</parent>

<artifactId>org.openhab.binding.sncf</artifactId>

<name>openHAB Add-ons :: Bundles :: SNCF Binding</name>

</project>
9 changes: 9 additions & 0 deletions bundles/org.openhab.binding.sncf/src/main/feature/feature.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<features name="org.openhab.binding.sncf-${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-sncf" description="SNCF Binding" version="${project.version}">
<feature>openhab-runtime-base</feature>
<bundle start-level="80">mvn:org.openhab.addons.bundles/org.openhab.binding.sncf/${project.version}</bundle>
</feature>
</features>
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* 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.sncf.internal;

import java.util.Set;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.core.thing.ThingTypeUID;

/**
* The {@link SncfBindingConstants} class defines common constants, which are
* used across the whole binding.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class SncfBindingConstants {

public static final String BINDING_ID = "sncf";

// Station properties
public static final String STOP_POINT_ID = "stopPointId";
public static final String DISTANCE = "Distance";
public static final String LOCATION = "Location";
public static final String TIMEZONE = "Timezone";

// List of Channel groups
public static final String GROUP_ARRIVAL = "arrivals";
public static final String GROUP_DEPARTURE = "departures";

// List of Channel id's
public static final String DIRECTION = "direction";
public static final String LINE_NAME = "lineName";
public static final String NAME = "name";
public static final String NETWORK = "network";
public static final String TIMESTAMP = "timestamp";

// List of Thing Type UIDs
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
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
@@ -0,0 +1,38 @@
/**
* 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.sncf.internal;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;

/**
* Exception for errors when using the SNCF API
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
public class SncfException extends Exception {
private static final long serialVersionUID = -6215621577081394328L;

public SncfException(String label) {
super(label);
}

public SncfException(Throwable e) {
super(e);
}

public SncfException(@Nullable String message, @Nullable Throwable e) {
super(message, e);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/**
* 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.sncf.internal;

import static org.openhab.binding.sncf.internal.SncfBindingConstants.*;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jetty.client.HttpClient;
import org.openhab.binding.sncf.internal.handler.SncfBridgeHandler;
import org.openhab.binding.sncf.internal.handler.StationHandler;
import org.openhab.core.i18n.LocationProvider;
import org.openhab.core.io.net.http.HttpClientFactory;
import org.openhab.core.thing.Bridge;
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;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

/**
* The {@link SncfHandlerFactory} is responsible for creating things and thing
* handlers.
*
* @author Gaël L'hopital - Initial contribution
*/
@NonNullByDefault
@Component(configurationPid = "binding.sncf", service = ThingHandlerFactory.class)
public class SncfHandlerFactory extends BaseThingHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(SncfHandlerFactory.class);
private final LocationProvider locationProvider;
private final HttpClient httpClient;
private final Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.create();

@Activate
public SncfHandlerFactory(@Reference LocationProvider locationProvider,
final @Reference HttpClientFactory httpClientFactory) {
this.locationProvider = locationProvider;
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 (APIBRIDGE_THING_TYPE.equals(thingTypeUID)) {
return new SncfBridgeHandler((Bridge) thing, gson, locationProvider, httpClient);
} else if (STATION_THING_TYPE.equals(thingTypeUID)) {
return new StationHandler(thing, locationProvider);
}
logger.warn("ThingHandler not found for {}", thing.getThingTypeUID());
return null;
}
}
Loading

0 comments on commit 1639b7c

Please sign in to comment.