6个版本 (重大更新)

0.4.0 2022年5月26日
0.3.0 2022年5月26日
0.2.1 2022年5月20日
0.1.0 2022年5月12日
0.0.1 2022年5月10日

HTTP客户端中排名262

MIT许可证

1.5MB
2K SLoC

MBTA Logo

MBTA-RS


一个简单的Rust客户端,用于与马萨诸塞州湾交通管理局的V3 API交互*

*此项目与MBTA的任何官方开发工作无关

关于

MBTA V3 API描述为

一个快速、灵活、基于标准的API,用于时刻表、到达预测、车辆位置和服务警报。

此项目提供了一个简单的同步客户端和数据模型,以便在Rust代码中轻松使用API中的数据。

构建工具

  • ureq 作为底层HTTP客户端
  • SerdeSerde JSON 用于数据反序列化/序列化
  • Chrono 用于处理日期和时间数据

为什么提供一个同步客户端而不是异步客户端呢?

  1. 我不想将此crate绑定到特定的async运行时
  2. 我想使用ureq crate,因为它具有简单的API和小巧的体积,并且它只提供同步客户端

鉴于存在OpenAPI/Swagger客户端代码生成器,为什么不自动生成客户端呢?

  1. 我对任何可用的代码生成工具都不太熟悉
  2. 我更喜欢拥有一些更精确的数据定义的手工制作客户端,而不是自动生成的客户端
  3. 目前API端点并不多,所以一旦启动,手动维护应该不会太多问题
  4. 我喜欢让自己承受不必要的和西西弗斯般的任务

使用方法

强烈建议在API Swagger文档(https://api-v3.mbta.com/docs/swagger/index.html)中查找更多详细和全面的文档,因为这里通常包含比这里更详细的模型字段文档。

在您的Cargo.toml文件中

[dependencies]
mbta-rs = "*"

# if you need to manipulate/further inspect certain fields
chrono = "*"
serde_json = "*"

简单示例使用

use std::env;
use mbta_rs::Client;

let client = match env::var("MBTA_TOKEN") {
    Ok(token) => Client::with_key(token),
    Err(_) => Client::without_key()
};

let query_params = [
    ("page[limit]", "3")
];

let alerts_response = client.alerts(&query_params);
if let Ok(response) = alerts_response {
    for alert in response.data {
        println!("MBTA alert: {}", alert.attributes.header);
    }
}

映射功能

本库附带一个可选模块,用于将位置相关的数据模型(停靠点、车辆、形状等)绘制到简单的瓦片地图上。

在您的Cargo.toml文件中

[dependencies]
mbta-rs = { version = "*", features = ["map"] }

# necessary to create the map itself
staticmap = "*"

简单示例使用

use std::{collections::HashMap, env};
use staticmap::StaticMapBuilder;
use mbta_rs::{Client, map::{Plottable, PlotStyle}};

let client = match env::var("MBTA_TOKEN") {
    Ok(token) => Client::with_key(token),
    Err(_) => Client::without_key()
};

let routes = client.routes(&[("filter[type]", "0,1")]).expect("failed to get routes");
let mut map = StaticMapBuilder::new()
    .width(1000)
    .height(1000)
    .zoom(12)
    .lat_center(42.326768)
    .lon_center(-71.100099)
    .build()
    .expect("failed to build map");

for route in routes.data {
    let query_params = [("filter[route]", &route.id)];
    let shapes = client
        .shapes(&query_params)
        .expect("failed to get shapes");
    for shape in shapes.data {
        shape
            .plot(&mut map, true, PlotStyle::new((route.attributes.color.clone(), 3.0), Some(("#FFFFFF".into(), 1.0))))
            .expect("failed to plot shape");
    }
    let stops = client
        .stops(&query_params)
        .expect("failed to get stops");
    for stop in stops.data {
        stop.plot(
            &mut map,
            true,
            PlotStyle::new((route.attributes.color.clone(), 3.0), Some(("#FFFFFF".into(), 1.0))),
        )
        .expect("failed to plot stop");
    }
}

// save to file...

贡献

请参阅CONTRIBUTE.md以开始贡献!

其他致谢

依赖项

~3.5–5.5MB
~129K SLoC