https://github.com/matnich89/network-rail-client
A Go Client for consuming real time data from Network Rails STOMP Data feeds
https://github.com/matnich89/network-rail-client
asynchronous-programming go high-performance train-information trains
Last synced: 3 months ago
JSON representation
A Go Client for consuming real time data from Network Rails STOMP Data feeds
- Host: GitHub
- URL: https://github.com/matnich89/network-rail-client
- Owner: matnich89
- Created: 2024-07-17T17:14:51.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-08-22T17:02:57.000Z (almost 2 years ago)
- Last Synced: 2024-09-01T09:21:51.495Z (almost 2 years ago)
- Topics: asynchronous-programming, go, high-performance, train-information, trains
- Language: Go
- Homepage:
- Size: 34.2 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Network Rail Client
This Go package provides a client for connecting to and consuming data from the Network Rail data feeds. It handles
Real-Time Public Performance Measure (RTPPM) and Train Movement data feeds.
## Installation
To use this package in your Go project, run:
```bash
go get github.com/matnich89/network-rail-client
```
## Features
* Easy connection to Network Rail's STOMP server
* Automatic handling of subscription and message parsing for multiple data feeds
* Support for subscribing to all train movements or specific train operating companies
* Graceful shutdown and resource cleanup
* Error handling through a dedicated error channel
## API
### `NewNetworkRailClient(ctx context.Context, username, password string) (*NetworkRailClient, error)`
Creates a new Network Rail client and establishes a connection to the STOMP server.
### `(nr *NetworkRailClient) SubRTPPM() (chan *realtime.RTPPMDataMsg, error)`
Subscribes to the RTPPM feed and returns a channel of RTPPM messages.
### `(nr *NetworkRailClient) SubAllTrainMovement() (<-chan movement.Body, error)`
Subscribes to all train movement messages and returns a channel of movement data.
### `(nr *NetworkRailClient) SubMultiTrainCompanyMovements(operators []model.TrainOperator) ([]*TrainCompanySub, error)`
Subscribes to train movement messages for specific train operating companies and returns a slice of TrainCompanySub
structures, each containing a channel for that company's movement data.
## Data Models
The package includes several data models:
* `realtime.RTPPMDataMsg`: Represents the RTPPM data structure.
* `movement.Body`: Interface for different types of train movement messages.
* `model.TrainOperator`: Represents a train operating company.
## Usage
Here's a basic example of how to use the client:
```go
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"sync"
"syscall"
"github.com/matnich89/network-rail-client/client"
"github.com/matnich89/network-rail-client/model"
"github.com/matnich89/network-rail-client/model/movement"
"github.com/matnich89/network-rail-client/model/realtime"
)
func main() {
// Replace with your actual Network Rail API credentials (MAKE SURE TO USE EMV VARS!!!)
username := "your-username"
password := "your-password"
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// Create a new NetworkRailClient
nrClient, err := client.NewNetworkRailClient(ctx, username, password)
if err != nil {
log.Fatalf("Failed to create NetworkRailClient: %v", err)
}
// Create a WaitGroup to manage our goroutines
var wg sync.WaitGroup
// Subscribe to RTPPM data
rtppmChan, err := nrClient.SubRTPPM()
if err != nil {
log.Fatalf("Failed to subscribe to RTPPM: %v", err)
}
// Subscribe to all train movements
allMovementsChan, err := nrClient.SubAllTrainMovement()
if err != nil {
log.Fatalf("Failed to subscribe to all train movements: %v", err)
}
// Subscribe to specific train company movements
operators := []model.TrainOperator{
model.ElizabethLine,
model.CrossCountry,
}
companySubChannels, err := nrClient.SubMultiTrainCompanyMovements(operators)
if err != nil {
log.Fatalf("Failed to subscribe to company-specific movements: %v", err)
}
// Set up a channel to handle shutdown gracefully
shutdown := make(chan os.Signal, 1)
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM)
// Start goroutines to handle incoming data
wg.Add(1)
go handleRTPPM(ctx, &wg, rtppmChan)
wg.Add(1)
go handleAllMovements(ctx, &wg, allMovementsChan)
for _, companySub := range companySubChannels {
wg.Add(1)
go handleCompanyMovements(ctx, &wg, companySub)
}
// Handle errors
wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case err := <-nrClient.ErrCh:
log.Printf("Error: %v", err)
case <-ctx.Done():
return
}
}
}()
// Wait for shutdown signal
<-shutdown
fmt.Println("Shutting down...")
cancel()
// Wait for all goroutines to finish
wg.Wait()
fmt.Println("Shutdown complete")
}
func handleRTPPM(ctx context.Context, wg *sync.WaitGroup, rtppmChan <-chan *realtime.RTPPMDataMsg) {
defer wg.Done()
for {
select {
case msg := <-rtppmChan:
fmt.Printf("Received RTPPM data: %+v\n", msg)
case <-ctx.Done():
return
}
}
}
func handleAllMovements(ctx context.Context, wg *sync.WaitGroup, movementsChan <-chan movement.Body) {
defer wg.Done()
for {
select {
case movement := <-movementsChan:
fmt.Printf("Received movement: %+v\n", movement)
case <-ctx.Done():
return
}
}
}
func handleCompanyMovements(ctx context.Context, wg *sync.WaitGroup, companySub *client.TrainCompanySub) {
defer wg.Done()
for {
select {
case movement := <-companySub.SubChan:
fmt.Printf("Received %s movement: %+v\n", companySub.Name, movement)
case <-ctx.Done():
return
}
}
}
```
## Dependencies
* github.com/go-stomp/stomp/v3
## License
MIT License
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## Disclaimer
This client is unofficial and is not affiliated with Network Rail. Users must comply with Network Rail's terms of
service when using this client.
## Resources
For Network Rail data-feed info, check out
the [Network Rail Open Data Feeds](https://www.networkrail.co.uk/who-we-are/transparency-and-ethics/transparency/open-data-feeds/)
page.
For documents on how to interact with the feeds, visit
the [Open Rail Wiki](https://wiki.openraildata.com/index.php?title=Main_Page).