From cc8181ebdca6ab4affd050e4be792ee1fd855ea3 Mon Sep 17 00:00:00 2001 From: Nicola Belluti Date: Tue, 6 Oct 2026 12:49:54 +0200 Subject: [PATCH] Turned the repo into a Cargo workspace, with r701 as a member Moving the library into its own r701/ directory makes room for the Tauri GUI client (Oxibadge) to be added as a sibling workspace member in a following commit. edition/license/repository are now inherited from the new workspace root instead of being duplicated per member. Co-Authored-By: Claude Sonnet 5 --- Cargo.toml | 30 ++---------- README.md | 64 +++++--------------------- r701/Cargo.toml | 28 ++++++++++++ r701/README.md | 68 ++++++++++++++++++++++++++++ {src => r701/src}/lib.rs | 0 {src => r701/src}/r701.rs | 0 {src => r701/src}/record.rs | 0 {src => r701/src}/record_iterator.rs | 0 {tests => r701/tests}/e2e.rs | 0 {tests => r701/tests}/mock/mod.rs | 0 10 files changed, 112 insertions(+), 78 deletions(-) create mode 100644 r701/Cargo.toml create mode 100644 r701/README.md rename {src => r701/src}/lib.rs (100%) rename {src => r701/src}/r701.rs (100%) rename {src => r701/src}/record.rs (100%) rename {src => r701/src}/record_iterator.rs (100%) rename {tests => r701/tests}/e2e.rs (100%) rename {tests => r701/tests}/mock/mod.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 55f320b..7785627 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,28 +1,8 @@ -[package] -name = "r701" -version = "0.2.0" +[workspace] +resolver = "3" +members = ["r701"] + +[workspace.package] edition = "2021" license = "AGPL-3.0-or-later" repository = "https://git.nicolabelluti.me/nicolabelluti/r701" - -[dependencies] -async-stream = "0.3.6" -chrono = { version = "0.4.38", default-features = false, features = ["clock"] } -serde = { version = "1.0.203", default-features = false, features = ["derive"], optional = true } -tokio = { version = "1.53.1", default-features = false, features = ["net", "io-util", "sync"] } -tokio-stream = { version = "0.1.19", default-features = false } - -[features] -serde = ["chrono/serde", "dep:serde"] - -[lints.rust] -unsafe_code = "forbid" - -[lints.clippy] -unwrap_used = "deny" -enum_glob_use = { level = "deny", priority = 1 } -pedantic = { level = "deny", priority = -1 } -nursery = { level = "deny", priority = -1 } - -[dev-dependencies] -tokio = { version = "1.53.1", features = ["rt", "macros", "net"] } diff --git a/README.md b/README.md index 34dafba..360f15f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-# R701 🕰️ +# R701 | Oxibadge [![Rust](https://img.shields.io/badge/Rust-f74c00?logo=rust)](https://www.rust-lang.org) [![Claude Code](https://img.shields.io/badge/Claude%20Code-grey?logo=claude&logoColor=d97757)](https://claude.com/product/claude-code) @@ -11,58 +11,16 @@

-> A reverse-engineered library to communicate with the -> [R701](https://ipsattendant.it/rilevatore-presenze-r701/) by [I.P.S. -> Informatica](https://ipsinformatica.info/), written in Rust +> A reverse-engineered client for the +> [R701](https://ipsattendant.it/rilevatore-presenze-r701/) attendance reader by +> [I.P.S. Informatica](https://ipsinformatica.info/) -If you want to read about this reverse engineering attempt, check out -. +This repository is a Cargo workspace with two members: -## Library Usage +- **[`r701/`](r701/README.md)** — the async Rust library that speaks the + device's TCP protocol. +- **`oxibadge/`** — Oxibadge, a minimal Tauri + Svelte desktop client built on + top of the library. *(Coming soon.)* -1. Add the library to you project: - - ```shell - cargo add r701 --git https://git.nicolabelluti.me/nicolabelluti/r701.git - ``` - -2. Use the library in you project: - - This library is async and built on [tokio](https://tokio.rs); add it to your - own `[dependencies]` (e.g. `tokio = { version = "1", features = - ["rt-multi-thread", "macros"] }`) to run the example below. - - ```rust - use r701::R701; - use tokio_stream::StreamExt; - - #[tokio::main] - async fn main() { - let r701 = R701::connect("127.0.0.1:5005").await.unwrap(); - let mut record_stream = r701.into_record_iter().await.unwrap(); - let mut id = 0; - - println!("No\tMchn\tEnNo\t\tName\t\tMode\tIOMd\tDateTime\t"); - while let Some(record) = record_stream.next().await { - let record = record.unwrap(); - let name = match r701.get_name(record.employee_id).await.unwrap() { - Some(Ok(name)) => name, - Some(Err(error)) => String::from_utf8_lossy(error.as_bytes()).into_owned(), - None => format!("user #{}", record.employee_id), - }; - - println!( - "{:0>6}\t{}\t{:0>9}\t{: <10}\t{}\t{}\t{}", - id + 1, - 1, - record.employee_id, - name, - 35, - record.clock as u8, - record.datetime.format("%Y/%m/%d %H:%M:%S"), - ); - - id += 1; - } - } - ``` +If you want to read about the reverse engineering attempt behind the library, +check out . diff --git a/r701/Cargo.toml b/r701/Cargo.toml new file mode 100644 index 0000000..16ab2a8 --- /dev/null +++ b/r701/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "r701" +version = "0.2.0" +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +async-stream = "0.3.6" +chrono = { version = "0.4.38", default-features = false, features = ["clock"] } +serde = { version = "1.0.203", default-features = false, features = ["derive"], optional = true } +tokio = { version = "1.53.1", default-features = false, features = ["net", "io-util", "sync"] } +tokio-stream = { version = "0.1.19", default-features = false } + +[features] +serde = ["chrono/serde", "dep:serde"] + +[lints.rust] +unsafe_code = "forbid" + +[lints.clippy] +unwrap_used = "deny" +enum_glob_use = { level = "deny", priority = 1 } +pedantic = { level = "deny", priority = -1 } +nursery = { level = "deny", priority = -1 } + +[dev-dependencies] +tokio = { version = "1.53.1", features = ["rt", "macros", "net"] } diff --git a/r701/README.md b/r701/README.md new file mode 100644 index 0000000..34dafba --- /dev/null +++ b/r701/README.md @@ -0,0 +1,68 @@ +
+ +# R701 🕰️ + +[![Rust](https://img.shields.io/badge/Rust-f74c00?logo=rust)](https://www.rust-lang.org) +[![Claude Code](https://img.shields.io/badge/Claude%20Code-grey?logo=claude&logoColor=d97757)](https://claude.com/product/claude-code) +[![GNU AGPLv3.0 License](https://img.shields.io/badge/License-GNU%20AGPLv3.0-dark_green?logo=gnu)](https://choosealicense.com/licenses/agpl-3.0) +[![Buymeacoffee](https://img.shields.io/badge/Buymeacoffee-gray?logo=buymeacoffee)](https://buymeacoffee.com/nicolabelluti) +
+[![CI Badge](https://git.nicolabelluti.me/nicolabelluti/r701/actions/workflows/check-format-and-test.yaml/badge.svg)](https://git.nicolabelluti.me/nicolabelluti/r701/actions/?workflow=check-format-and-test.yaml) + +

+ +> A reverse-engineered library to communicate with the +> [R701](https://ipsattendant.it/rilevatore-presenze-r701/) by [I.P.S. +> Informatica](https://ipsinformatica.info/), written in Rust + +If you want to read about this reverse engineering attempt, check out +. + +## Library Usage + +1. Add the library to you project: + + ```shell + cargo add r701 --git https://git.nicolabelluti.me/nicolabelluti/r701.git + ``` + +2. Use the library in you project: + + This library is async and built on [tokio](https://tokio.rs); add it to your + own `[dependencies]` (e.g. `tokio = { version = "1", features = + ["rt-multi-thread", "macros"] }`) to run the example below. + + ```rust + use r701::R701; + use tokio_stream::StreamExt; + + #[tokio::main] + async fn main() { + let r701 = R701::connect("127.0.0.1:5005").await.unwrap(); + let mut record_stream = r701.into_record_iter().await.unwrap(); + let mut id = 0; + + println!("No\tMchn\tEnNo\t\tName\t\tMode\tIOMd\tDateTime\t"); + while let Some(record) = record_stream.next().await { + let record = record.unwrap(); + let name = match r701.get_name(record.employee_id).await.unwrap() { + Some(Ok(name)) => name, + Some(Err(error)) => String::from_utf8_lossy(error.as_bytes()).into_owned(), + None => format!("user #{}", record.employee_id), + }; + + println!( + "{:0>6}\t{}\t{:0>9}\t{: <10}\t{}\t{}\t{}", + id + 1, + 1, + record.employee_id, + name, + 35, + record.clock as u8, + record.datetime.format("%Y/%m/%d %H:%M:%S"), + ); + + id += 1; + } + } + ``` diff --git a/src/lib.rs b/r701/src/lib.rs similarity index 100% rename from src/lib.rs rename to r701/src/lib.rs diff --git a/src/r701.rs b/r701/src/r701.rs similarity index 100% rename from src/r701.rs rename to r701/src/r701.rs diff --git a/src/record.rs b/r701/src/record.rs similarity index 100% rename from src/record.rs rename to r701/src/record.rs diff --git a/src/record_iterator.rs b/r701/src/record_iterator.rs similarity index 100% rename from src/record_iterator.rs rename to r701/src/record_iterator.rs diff --git a/tests/e2e.rs b/r701/tests/e2e.rs similarity index 100% rename from tests/e2e.rs rename to r701/tests/e2e.rs diff --git a/tests/mock/mod.rs b/r701/tests/mock/mod.rs similarity index 100% rename from tests/mock/mod.rs rename to r701/tests/mock/mod.rs