6 个版本 (1 个稳定版)
1.0.0 | 2023 年 12 月 14 日 |
---|---|
0.3.1 | 2022 年 12 月 25 日 |
0.3.0 | 2021 年 7 月 19 日 |
0.2.0 | 2021 年 7 月 17 日 |
0.1.1 | 2021 年 5 月 4 日 |
#1 in #spacex
19KB
starlink-rs
Rust 客户端实现,用于 SpaceX Starlink 用户终端暴露的 gRPC 端点。
免责声明:如果您是 Elon 或其他 SpaceX 相关权威人士,并且不想存在此内容,请直接联系我。
背景
Starlink 天线在其本地网络下 192.168.100.1:9200
暴露了一个未经身份验证的 gRPC HTTP/2 服务器,允许进行 服务器反射。这包含从其中反转出来的(可能仍然有缺陷的)Protobuf 定义以及一个能够与天线通信的 Rust 客户端实现,用于科学研究。
天线暴露了两种方法(据我所知);一种用于请求/响应,另一种用于流式传输
service Device {
rpc Handle (.SpaceX.API.Device.Request) returns (.SpaceX.API.Device.Response) {}
rpc Stream (stream .SpaceX.API.Device.ToDevice) returns (stream .SpaceX.API.Device.FromDevice) {}
}
示例用法
请求/响应和流式通信的工作示例在 示例目录 中。
请求 / 响应
use starlink::proto::space_x::api::device::{device_client::DeviceClient, request, GetStatusRequest, Request};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = DeviceClient::connect("http://192.168.100.1:9200").await?;
let request = tonic::Request::new(Request {
id: None,
epoch_id: None,
target_id: None,
request: Some(request::Request::GetStatus(GetStatusRequest {})),
});
let response = client.handle(request).await?;
dbg!(response);
Ok(())
}
cargo run --example request_response
打印类似以下内容
Response {
metadata: MetadataMap {
headers: {
"content-type": "application/grpc",
"grpc-status": "0",
"grpc-message": "",
},
},
message: Response {
id: None,
status: None,
response: Some(
DishGetStatus(
DishGetStatusResponse {
device_info: Some(
DeviceInfo {
id: Some(
"<my-ID>",
),
hardware_version: Some(
"rev1_pre_production",
),
software_version: Some(
"1f86ec34-34ea-4e7a-9758-3842e72422fb.release",
),
country_code: Some(
"DE",
),
utc_offset_s: Some(
1,
),
},
),
device_state: Some(
DeviceState {
uptime_s: Some(
26115,
),
},
),
state: Some(
Connected,
),
alerts: Some(
DishAlerts {
motors_stuck: None,
thermal_throttle: None,
thermal_shutdown: None,
mast_not_near_vertical: None,
unexpected_location: None,
slow_ethernet_speeds: None,
},
),
snr: Some(
6.0,
),
seconds_to_first_nonempty_slot: None,
pop_ping_drop_rate: None,
downlink_throughput_bps: Some(
8584784.0,
),
uplink_throughput_bps: Some(
311510.97,
),
pop_ping_latency_ms: Some(
38.857143,
),
obstruction_stats: Some(
DishObstructionStats {
currently_obstructed: None,
fraction_obstructed: Some(
0.0010516815,
),
last_24h_obstructed_s: Some(
72.0,
),
valid_s: Some(
21260.67,
),
wedge_fraction_obstructed: [
1.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
],
wedge_abs_fraction_obstructed: [
0.0010516815,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
],
},
),
},
),
),
},
}
流式传输
use async_stream::stream;
use std::time::Duration;
use tokio::time::sleep;
use starlink::proto::space_x::api::device::{
device_client::DeviceClient,
request,
to_device,
GetStatusRequest,
Request,
ToDevice,
};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = DeviceClient::connect("http://192.168.100.1:9200").await?;
let request_stream = stream! {
loop {
yield ToDevice {
message: Some(to_device::Message::Request(Request {
id: None,
epoch_id: None,
target_id: None,
request: Some(request::Request::GetStatus(GetStatusRequest {})),
})),
};
sleep(Duration::from_secs(1)).await;
}
};
let request = tonic::Request::new(request_stream);
let mut response_stream = client.stream(request).await?.into_inner();
while let Some(message) = response_stream.message().await? {
dbg!(message);
}
Ok(())
}
cargo run --example streaming
开发
Protobuf 代码生成由工作空间中的 codegen
crate 处理。生成的 Protobuf 文件已提交。要运行代码生成,请执行
cargo run --package starlink-codegen
许可证
starlink-rs
根据 Apache 许可证 2.0 版或 MIT 许可证进行许可。
- Apache 许可证,版本 2.0,(LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
您可选择。
依赖项
~4–6MB
~98K SLoC