Skip to content

Commit 2107064

Browse files
author
Cornelius Krupp
committed
Basic droidgpric config requesting
1 parent fd3815e commit 2107064

2 files changed

Lines changed: 203 additions & 0 deletions

File tree

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
use tonic::{Request, Response, Status};
2+
use tonic::transport::Server;
3+
use tokio_stream::wrappers::ReceiverStream;
4+
use futures_util::StreamExt;
5+
6+
pub mod droidgrpc {
7+
tonic::include_proto!("droidgrpc");
8+
}
9+
10+
use droidgrpc::arm_service_server::{ArmService, ArmServiceServer};
11+
use droidgrpc::leg_service_server::{LegService, LegServiceServer};
12+
use droidgrpc::{DroidConfigs, DroidStateResponse, DroidArmResponse, DroidCommandRequest, Empty};
13+
14+
#[derive(Debug, Default)]
15+
pub struct DummyArmService {}
16+
17+
#[tonic::async_trait]
18+
impl ArmService for DummyArmService {
19+
// --- 1. Define the missing associated types ---
20+
type GetArmStateStreamStream = ReceiverStream<Result<DroidArmResponse, Status>>;
21+
type ExchangeArmControlStreamStream = ReceiverStream<Result<DroidArmResponse, Status>>;
22+
23+
// --- 2. Implement the methods ---
24+
25+
async fn get_arm_config(&self, _: Request<Empty>) -> Result<Response<DroidConfigs>, Status> {
26+
Ok(Response::new(DroidConfigs::default()))
27+
}
28+
29+
async fn get_arm_state(&self, _: Request<Empty>) -> Result<Response<DroidArmResponse>, Status> {
30+
Ok(Response::new(DroidArmResponse::default()))
31+
}
32+
33+
async fn get_arm_state_stream(&self, _: Request<Empty>) -> Result<Response<Self::GetArmStateStreamStream>, Status> {
34+
let (tx, rx) = tokio::sync::mpsc::channel(4);
35+
// Minimal result: just one empty response
36+
let _ = tx.try_send(Ok(DroidArmResponse::default()));
37+
Ok(Response::new(ReceiverStream::new(rx)))
38+
}
39+
40+
async fn set_arm_command(&self, _: Request<DroidCommandRequest>) -> Result<Response<Empty>, Status> {
41+
Ok(Response::new(Empty::default()))
42+
}
43+
44+
async fn set_arm_command_stream(&self, mut request: Request<tonic::Streaming<DroidCommandRequest>>) -> Result<Response<Empty>, Status> {
45+
let mut stream = request.into_inner();
46+
while let Some(_cmd) = stream.next().await {
47+
// Echo/Process logic here
48+
}
49+
Ok(Response::new(Empty::default()))
50+
}
51+
52+
async fn exchange_arm_control_stream(
53+
&self,
54+
request: Request<tonic::Streaming<DroidCommandRequest>>,
55+
) -> Result<Response<Self::ExchangeArmControlStreamStream>, Status> {
56+
let mut in_stream = request.into_inner();
57+
let (tx, rx) = tokio::sync::mpsc::channel(128);
58+
59+
tokio::spawn(async move {
60+
while let Some(Ok(cmd)) = in_stream.next().await {
61+
// Echoing the command fields back into a response
62+
let echo = DroidArmResponse {
63+
position: cmd.position,
64+
velocity: cmd.velocity,
65+
torque: cmd.torque,
66+
..Default::default()
67+
};
68+
if tx.send(Ok(echo)).await.is_err() { break; }
69+
}
70+
});
71+
72+
Ok(Response::new(ReceiverStream::new(rx)))
73+
}
74+
}
75+
76+
#[derive(Debug, Default)]
77+
pub struct DummyLegService {}
78+
79+
#[tonic::async_trait]
80+
impl LegService for DummyLegService {
81+
// Associated types required by the generated trait for streaming RPCs
82+
type GetLegStateStreamStream = ReceiverStream<Result<DroidStateResponse, Status>>;
83+
type ExchangeLegControlStreamStream = ReceiverStream<Result<DroidStateResponse, Status>>;
84+
85+
async fn get_leg_config(&self, _: Request<Empty>) -> Result<Response<DroidConfigs>, Status> {
86+
Ok(Response::new(DroidConfigs::default()))
87+
}
88+
89+
async fn get_leg_state(&self, _: Request<Empty>) -> Result<Response<DroidStateResponse>, Status> {
90+
Ok(Response::new(DroidStateResponse::default()))
91+
}
92+
93+
async fn get_leg_state_stream(&self, _: Request<Empty>) -> Result<Response<Self::GetLegStateStreamStream>, Status> {
94+
let (tx, rx) = tokio::sync::mpsc::channel(4);
95+
// Minimal pulse: send one default state
96+
let _ = tx.try_send(Ok(DroidStateResponse::default()));
97+
Ok(Response::new(ReceiverStream::new(rx)))
98+
}
99+
100+
async fn set_leg_command(&self, _: Request<DroidCommandRequest>) -> Result<Response<Empty>, Status> {
101+
Ok(Response::new(Empty::default()))
102+
}
103+
104+
async fn set_leg_command_stream(&self, mut request: Request<tonic::Streaming<DroidCommandRequest>>) -> Result<Response<Empty>, Status> {
105+
let mut stream = request.into_inner();
106+
while let Some(Ok(_cmd)) = stream.next().await {
107+
// Echo logic could be added here for processing
108+
}
109+
Ok(Response::new(Empty::default()))
110+
}
111+
112+
async fn exchange_leg_control_stream(
113+
&self,
114+
request: Request<tonic::Streaming<DroidCommandRequest>>,
115+
) -> Result<Response<Self::ExchangeLegControlStreamStream>, Status> {
116+
let mut in_stream = request.into_inner();
117+
let (tx, rx) = tokio::sync::mpsc::channel(128);
118+
119+
tokio::spawn(async move {
120+
while let Some(Ok(cmd)) = in_stream.next().await {
121+
// Echo common fields from DroidCommandRequest to DroidStateResponse
122+
let echo = DroidStateResponse {
123+
position: cmd.position,
124+
velocity: cmd.velocity,
125+
torque: cmd.torque,
126+
..Default::default()
127+
};
128+
if tx.send(Ok(echo)).await.is_err() {
129+
break;
130+
}
131+
}
132+
});
133+
134+
Ok(Response::new(ReceiverStream::new(rx)))
135+
}
136+
}
137+
138+
#[tokio::main]
139+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
140+
// 1. Define the addresses
141+
let leg_addr = "[::1]:50051".parse()?;
142+
let arm_addr = "[::1]:50052".parse()?;
143+
144+
println!("LegService starting on {}", leg_addr);
145+
println!("ArmService starting on {}", arm_addr);
146+
147+
// 2. Spawn the LegService on port 50051
148+
let leg_handle = tokio::spawn(async move {
149+
let service = DummyLegService::default();
150+
Server::builder()
151+
.add_service(LegServiceServer::new(service))
152+
.serve(leg_addr)
153+
.await
154+
.expect("LegService server failed");
155+
});
156+
157+
// 3. Spawn the ArmService on port 50052
158+
let arm_handle = tokio::spawn(async move {
159+
let service = DummyArmService::default();
160+
Server::builder()
161+
.add_service(ArmServiceServer::new(service))
162+
.serve(arm_addr)
163+
.await
164+
.expect("ArmService server failed");
165+
});
166+
167+
// 4. Wait for both servers (they will run indefinitely)
168+
let _ = tokio::try_join!(leg_handle, arm_handle)?;
169+
170+
Ok(())
171+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::env;
2+
use droidgrpc::Empty;
3+
use droidgrpc::arm_service_client::ArmServiceClient;
4+
use droidgrpc::leg_service_client::LegServiceClient;
5+
6+
pub mod droidgrpc {
7+
tonic::include_proto!("droidgrpc");
8+
}
9+
10+
#[tokio::main]
11+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
12+
// 1. Get IP from CLI argument or default to localhost
13+
let args: Vec<String> = env::args().collect();
14+
let ip_str = args.get(1).map(|s| s.as_str()).unwrap_or("[::1]");
15+
16+
// Parse the string into an IpAddr to ensure it's a valid IPv4/IPv6
17+
let leg_uri = format!("http://{}:50051", ip_str);
18+
let arm_uri = format!("http://{}:50052", ip_str);
19+
let mut leg_client = LegServiceClient::connect(leg_uri).await?;
20+
let mut arm_client = ArmServiceClient::connect(arm_uri).await?;
21+
22+
let request = tonic::Request::new(Empty {});
23+
24+
let leg_config = leg_client.get_leg_config(request).await?;
25+
let request = tonic::Request::new(Empty {});
26+
let arm_config = arm_client.get_arm_config(request).await?;
27+
28+
println!("LEG_CONFIG={leg_config:?}");
29+
println!("ARM_CONFIG={arm_config:?}");
30+
31+
Ok(())
32+
}

0 commit comments

Comments
 (0)