Skip to content

Commit 48d837d

Browse files
author
Dave Horner
committed
feat: update dependencies, logging, and documentation
- Enable "env-filter" feature for tracing-subscriber in Cargo.toml - Update README: adjust run command, add Lua and Rust examples, and refine usage details - Increase delay in Lua example (windows-notepad-helloworld.lua) - Comment out debug logs in jetkvm_rpc_client.rs for cleaner output - Enhance keyboard character mapping in src/keyboard.rs with extended punctuation support - Improve tracing configuration in main.rs to include verbose logging options - Tidy debug messages in src/rpc_client.rs
1 parent d1b3116 commit 48d837d

File tree

8 files changed

+186
-72
lines changed

8 files changed

+186
-72
lines changed

Cargo.lock

Lines changed: 31 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ serde_json = "1.0.138"
2525
tokio = "1.43.0"
2626
toml = "0.8.20"
2727
tracing = "0.1.41"
28-
tracing-subscriber = "0.3.19"
28+
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
2929
#webrtc = "0.12.0"
3030
webrtc = { git = "https://github.com/davehorner/webrtc.git", branch = "jetkvm_16_bit_patch", version = "0.12.0" }
3131
mlua = { version = "0.10.1", features = ["lua54", "vendored", "async", "send", "serialize"], optional = true }

README.md

Lines changed: 59 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -46,62 +46,85 @@ jetkvm_control = "0.1.0" # or use a git dependency / local path during developm
4646
3. **Running the Project**
4747
After setting up your configuration, you can build and run the project with Cargo:
4848
```bash
49-
cargo run
49+
cargo run -- -H 192.168.1.100 lua-examples/windows-notepad-helloworld.lua
5050
```
5151
52-
This will compile the project and start the demo application which:
52+
This will compile the project and execute the window-notepad-helloworld.lua example.
5353
54-
- Connects to the JetKVM service,
55-
- Opens a WebRTC DataChannel,
56-
- Sends RPC calls to perform actions (e.g., keyboard events, mouse clicks).
54+
## About the cmdline client
5755
58-
## What's the cmdline client look like
56+
The client (cargo run/jetkvm_control) is a simple ping if you don't have the `lua` feature enabled.
5957
60-
Right now the client doesn't do anything put ping and display some additional debug.
58+
If you enable the lua feature; jetkvm_control will expect a lua file to execute.
6159
6260
```
6361
A control client for JetKVM over WebRTC.
6462

65-
Usage: jetkvm_control [OPTIONS]
63+
Usage: jetkvm_control [OPTIONS] <LUA_SCRIPT>
64+
65+
Arguments:
66+
<LUA_SCRIPT> Path to the Lua script to execute
6667

6768
Options:
6869
-H, --host <HOST> The host address to connect to
6970
-p, --port <PORT> The port number to use
7071
-a, --api <API> The API endpoint
7172
-P, --password <PASSWORD> The password for authentication
73+
-v, --verbose Enable verbose logging (include logs from webrtc_sctp)
7274
-h, --help Print help
7375
-V, --version Print version
7476
```
7577
7678
## What's the code look like
7779
78-
```rust
79-
let config = JetKvmConfig::load()?;
80-
let mut client = JetKvmRpcClient::new(config);
81-
82-
if let Err(err) = client.connect().await {
83-
error!("Failed to connect to RPC server: {:?}", err);
84-
std::process::exit(1);
85-
}
86-
// open notepad and say Hello World, copy and paste.
87-
send_windows_key(&client).await.ok();
88-
sleep(Duration::from_millis(100)).await;
89-
rpc_sendtext(&client, "notepad").await.ok();
90-
sleep(Duration::from_millis(100)).await;
91-
send_return(&client).await.ok();
92-
sleep(Duration::from_millis(100)).await;
93-
rpc_sendtext(&client, "Hello World").await.ok();
94-
sleep(Duration::from_millis(100)).await;
95-
send_ctrl_a(&client).await.ok();
96-
sleep(Duration::from_millis(100)).await;
97-
send_ctrl_x(&client).await.ok();
98-
sleep(Duration::from_millis(100)).await;
99-
send_ctrl_v(&client).await.ok();
100-
sleep(Duration::from_millis(100)).await;
101-
send_return(&client).await.ok();
102-
sleep(Duration::from_millis(100)).await;
103-
send_ctrl_v(&client).await.ok();
104-
```
80+
The api is subject to change.
81+
82+
example code for rust:
83+
```rust
84+
let config = JetKvmConfig::load()?;
85+
let mut client = JetKvmRpcClient::new(config);
86+
87+
if let Err(err) = client.connect().await {
88+
error!("Failed to connect to RPC server: {:?}", err);
89+
std::process::exit(1);
90+
}
91+
// open notepad and say Hello World, copy and paste.
92+
send_windows_key(&client).await.ok();
93+
sleep(Duration::from_millis(100)).await;
94+
rpc_sendtext(&client, "notepad").await.ok();
95+
sleep(Duration::from_millis(100)).await;
96+
send_return(&client).await.ok();
97+
sleep(Duration::from_millis(100)).await;
98+
rpc_sendtext(&client, "Hello World").await.ok();
99+
sleep(Duration::from_millis(100)).await;
100+
send_ctrl_a(&client).await.ok();
101+
sleep(Duration::from_millis(100)).await;
102+
send_ctrl_x(&client).await.ok();
103+
sleep(Duration::from_millis(100)).await;
104+
send_ctrl_v(&client).await.ok();
105+
sleep(Duration::from_millis(100)).await;
106+
send_return(&client).await.ok();
107+
sleep(Duration::from_millis(100)).await;
108+
send_ctrl_v(&client).await.ok();
109+
```
110+
111+
example code in lua:
112+
```lua
113+
print("Executing Lua script...")
114+
send_windows_key()
115+
delay(550)
116+
send_text("notepad")
117+
send_return()
118+
delay(250)
119+
delay(250)
120+
send_text("Hello World!")
121+
send_ctrl_a()
122+
send_ctrl_c()
123+
delay(250)
124+
send_ctrl_v()
125+
delay(250)
126+
send_ctrl_v()
127+
```
105128

106129
Check out the examples folder for additional detail.
107130

@@ -135,9 +158,8 @@ JetKVM **relies heavily on WebRTC** for real-time communication, but we encounte
135158
- The Cargo.toml points to the patched https://github.com/davehorner/webrtc/tree/jetkvm_16_bit_patch
136159

137160
## Note
138-
- Password-based authentication is functional.
161+
- Password-less and Password-based local authentication have been tested functional.
139162
- Cloud integration and ICE/STUN support are not implemented yet.
140-
- Password-less authentication has not been tested.
141163
- Contributions for these features are welcome!
142164

143165
## License

lua-examples/windows-notepad-helloworld.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
print("Executing Lua script...")
22
send_windows_key()
3-
delay(250)
3+
delay(550)
44
send_text("notepad")
55
send_return()
66
delay(250)

src/jetkvm_rpc_client.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,16 @@ impl JetKvmRpcClient {
110110

111111
// 7. Send the offer to the server.
112112
let url = self.config.session_url();
113-
debug!("Sending SDP Offer to {}", url);
113+
//debug!("Sending SDP Offer to {}", url);
114114

115115
let response = http_client.post(&url).json(&session_request).send().await?;
116116
let response_text = response.text().await?;
117-
debug!("Received SDP Answer response: {}", response_text);
117+
//debug!("Received SDP Answer response: {}", response_text);
118118

119119
let session_response: WebRTCSessionResponse = serde_json::from_str(&response_text)?;
120120
let decoded_answer = general_purpose::STANDARD.decode(session_response.sd)?;
121121
let answer_value: Value = serde_json::from_slice(&decoded_answer)?;
122-
debug!("Decoded SDP answer: {}", answer_value);
122+
//debug!("Decoded SDP answer: {}", answer_value);
123123

124124
let sdp_field = answer_value
125125
.get("sdp")

src/keyboard.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,71 @@ pub async fn rpc_keyboard_report(
2020
}
2121

2222
/// Convert an ASCII character into a (modifier, keycode) pair, following HID usage tables.
23-
/// Currently supports letters and digits only.
24-
/// - For lowercase letters, modifier = 0, keycode = 0x04 + (c - 'a').
25-
/// - For uppercase letters, modifier = 0x02 (shift), keycode = same as lowercase.
26-
/// - For digits: '1' to '9' map to 0x1E..0x26, '0' maps to 0x27.
23+
///
24+
/// For letters:
25+
/// - Lowercase: modifier = 0, keycode = 0x04 + (c - 'a').
26+
/// - Uppercase: modifier = 0x02 (shift), keycode = same as lowercase.
27+
///
28+
/// For digits:
29+
/// - '1' to '9': keycodes 0x1E to 0x26 respectively,
30+
/// - '0': keycode 0x27.
31+
///
32+
/// For space:
33+
/// - Keycode is 0x2C with no modifier.
34+
///
35+
/// For common punctuation and symbols, the mapping is defined in a static table.
36+
///
37+
/// Returns `None` if the character is not supported.
2738
fn char_to_hid(c: char) -> Option<(u8, u8)> {
2839
if c.is_ascii_alphabetic() {
29-
let base = 0x04;
30-
if c.is_ascii_lowercase() {
31-
Some((0, (c as u8) - b'a' + base))
32-
} else {
33-
// Uppercase letters require SHIFT (modifier 0x02)
34-
Some((0x02, (c.to_ascii_lowercase() as u8) - b'a' + base))
35-
}
40+
let shift = if c.is_ascii_uppercase() { 0x02 } else { 0 };
41+
Some((shift, (c.to_ascii_lowercase() as u8) - b'a' + 0x04))
3642
} else if c.is_ascii_digit() {
3743
if c == '0' {
3844
Some((0, 0x27))
3945
} else {
4046
Some((0, (c as u8) - b'1' + 0x1E))
4147
}
4248
} else if c == ' ' {
43-
// HID usage for space is 0x2C, no modifier.
49+
// HID usage for space.
4450
Some((0, 0x2C))
4551
} else {
46-
// Extend with additional mappings as needed.
47-
None
52+
// Mapping for additional punctuation and symbols.
53+
const MAP: &[(char, (u8, u8))] = &[
54+
('!', (0x02, 0x1E)), // Shift + '1'
55+
('@', (0x02, 0x1F)), // Shift + '2'
56+
('#', (0x02, 0x20)), // Shift + '3'
57+
('$', (0x02, 0x21)), // Shift + '4'
58+
('%', (0x02, 0x22)), // Shift + '5'
59+
('^', (0x02, 0x23)), // Shift + '6'
60+
('&', (0x02, 0x24)), // Shift + '7'
61+
('*', (0x02, 0x25)), // Shift + '8'
62+
('(', (0x02, 0x26)), // Shift + '9'
63+
(')', (0x02, 0x27)), // Shift + '0'
64+
('-', (0, 0x2D)),
65+
('_', (0x02, 0x2D)),
66+
('=', (0, 0x2E)),
67+
('+', (0x02, 0x2E)),
68+
('[', (0, 0x2F)),
69+
('{', (0x02, 0x2F)),
70+
(']', (0, 0x30)),
71+
('}', (0x02, 0x30)),
72+
('\\', (0, 0x31)),
73+
('|', (0x02, 0x31)),
74+
(';', (0, 0x33)),
75+
(':', (0x02, 0x33)),
76+
('\'', (0, 0x34)),
77+
('"', (0x02, 0x34)),
78+
('`', (0, 0x35)),
79+
('~', (0x02, 0x35)),
80+
(',', (0, 0x36)),
81+
('<', (0x02, 0x36)),
82+
('.', (0, 0x37)),
83+
('>', (0x02, 0x37)),
84+
('/', (0, 0x38)),
85+
('?', (0x02, 0x38)),
86+
];
87+
MAP.iter().find_map(|&(ch, pair)| if ch == c { Some(pair) } else { None })
4888
}
4989
}
5090

src/main.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ use anyhow::Result as AnyResult;
22
use clap::{CommandFactory, Parser};
33
use jetkvm_control::jetkvm_config::JetKvmConfig;
44
use jetkvm_control::jetkvm_rpc_client::JetKvmRpcClient;
5-
use tokio::time::{sleep, Duration};
65
use tracing::{error, info, warn};
7-
use tracing_subscriber;
6+
use tracing_subscriber::{fmt, EnvFilter, registry};
7+
use tracing_subscriber::prelude::*;
88

99
#[derive(Parser, Debug)]
1010
#[command(author, version, about, long_about = None)]
@@ -25,6 +25,10 @@ struct CliConfig {
2525
#[arg(short = 'P', long)]
2626
password: Option<String>,
2727

28+
/// Enable verbose logging (include logs from webrtc_sctp).
29+
#[arg(short = 'v', long)]
30+
verbose: bool,
31+
2832
// When the "lua" feature is enabled, the first positional argument is the Lua script path.
2933
#[cfg(feature = "lua")]
3034
/// Path to the Lua script to execute.
@@ -59,15 +63,36 @@ fn load_and_override_config(cli_config: &CliConfig) -> JetKvmConfig {
5963

6064
#[tokio::main]
6165
async fn main() -> AnyResult<()> {
62-
tracing_subscriber::fmt()
63-
.with_max_level(tracing::Level::DEBUG)
64-
.init();
65-
info!("Starting jetkvm_control demo...");
66-
6766
// Parse CLI arguments.
6867
let cli_config = CliConfig::parse();
6968
info!("CLI config provided: {:?}", cli_config);
7069

70+
// Build a filter string: by default, disable webrtc_sctp logging,
71+
// but if verbose is enabled, include all logs.
72+
let filter_directive = if cli_config.verbose {
73+
"debug"
74+
} else {
75+
"debug,\
76+
webrtc_sctp=off,\
77+
webrtc::peer_connection=off,\
78+
webrtc_dtls=off,\
79+
webrtc_mdns=off,\
80+
hyper_util::client=off,\
81+
webrtc_data::data_channel=off,\
82+
webrtc_ice=off"
83+
};
84+
85+
// Initialize tracing subscriber with the constructed filter.
86+
// Create an EnvFilter using the directive.
87+
let env_filter = EnvFilter::new(filter_directive);
88+
89+
// Build a subscriber with the filter layer and formatting layer.
90+
registry()
91+
.with(env_filter)
92+
.with(fmt::layer())
93+
.init();
94+
info!("Starting jetkvm_control demo...");
95+
7196
// Load configuration from file (or default) and override with CLI options.
7297
let config = load_and_override_config(&cli_config);
7398

0 commit comments

Comments
 (0)