diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..26d29c7 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + # Check for updates every Monday + schedule: + interval: "weekly" \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f7849bf --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,51 @@ +name: Build + +on: [push] + +# Stops the running workflow of previous pushes +concurrency: + # cancel per workflow + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint-and-docs: + name: Lints and check docs + runs-on: ubuntu-latest + + steps: + + - name: Checkout + uses: actions/checkout@v4 + + - name: Rust setup (nightly) for docs + uses: dtolnay/rust-toolchain@nightly + with: + components: rust-docs, clippy, rustfmt + + - name: Lint - rustfmt + run: cargo fmt --all -- --check + + - name: Lint - clippy + run: cargo clippy --all --no-deps -- -D warnings + + - name: Docs + env: + RUSTDOCFLAGS: -D warnings --cfg docsrs + run: cargo doc --no-deps --all-features + + check-and-test: + name: Cargo check and test + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Rust setup (stable) + uses: dtolnay/rust-toolchain@stable + + - uses: Swatinem/rust-cache@v2 + + - run: cargo check --all-features + - run: cargo test --all-features \ No newline at end of file diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml new file mode 100644 index 0000000..1808c52 --- /dev/null +++ b/.github/workflows/msrv.yml @@ -0,0 +1,38 @@ +name: MSRV build + +on: + push: + # will checkout the default branch `development` + schedule: + # run every Friday at 17:00 + - cron: '00 17 * * 5' + # Or ran manually + workflow_dispatch: + +# Stops the running workflow of previous pushes +concurrency: + # cancel per workflow + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + RUST_MSRV_VERSION: '1.70' + +jobs: + build: + name: Test and build + runs-on: ubuntu-latest + + steps: + - name: Rust setup (MSRV) + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ env.RUST_MSRV_VERSION }} + + - uses: Swatinem/rust-cache@v2 + + - name: Checkout + uses: actions/checkout@v4 + + - run: cargo check + - run: cargo test \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 2a925e0..32dfa79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "http" version = "1.1.0" @@ -242,6 +248,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "object" version = "0.32.2" @@ -555,6 +571,7 @@ dependencies = [ "bytes", "libc", "mio", + "num_cpus", "pin-project-lite", "socket2", "tokio-macros", diff --git a/Cargo.toml b/Cargo.toml index 5123656..00c164d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,10 +12,12 @@ categories = ["api-bindings", "asynchronous", "visualization", "data-structures" keywords = ["arduino", "plotting", "protocol", "json"] repository = "https://github.com/LechevSpace/arduino-plotter" +rust-version = "1.70" + [dependencies] tracing = "0.1" -thiserror = "1.0.60" +thiserror = "1" serde_json = "1" serde = { version = "1", features = ["derive"] } @@ -33,4 +35,4 @@ rand = "0.8" [dev-dependencies] tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } -tokio = { version = "1", features = ["net", "sync", "macros"] } +tokio = { version = "1", features = ["net", "sync", "macros", "rt-multi-thread"] } diff --git a/README.md b/README.md index 884ea1a..240c282 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -# arduino-plotter -## Protocol crate and CLI used to communicate with Arduino serial plotter +# `arduino-plotter` +## API bindings (protocol) with Client/Server crate for interacting with Arduino Serial Plotter -### Arduino serial plotter: https://github.com/arduino/arduino-serial-plotter-webapp +### Arduino Serial Plotter: https://github.com/arduino/arduino-serial-plotter-webapp +[![sponsor-us]](https://github.com/sponsors/LechevSpace) [![crates-io]](https://crates.io/crates/arduino-plotter) [![docs-rs]](https://docs.rs/arduino-plotter) [![build-yml]](https://github.com/LechevSpace/arduino-plotter/actions/workflows/build.yml) #### Running arduino-serial-plotter webapp -**Arduino Serial Plotter** uses websocket to communicate by sending or receiving commands. +**Arduino Serial Plotter** uses WebSockets to communicate by sending or receiving commands. Requirements: - Node v10 @@ -23,7 +24,7 @@ Default port: **3000** #### Connecting -The **Arduino serial plotter** will send a request to our CLI and the CLI is waiting for a connection on the websocket, this is why you need to open the arduino plotter app after starting the CLI: +The **Arduino Serial Plotter** will send a request to our CLI and the CLI is waiting for a connection on the websocket, this is why you need to open the arduino plotter app after starting the CLI: `http://localhost:3000` (with default port **3000**) @@ -36,7 +37,7 @@ subscriber, however, you can use the `RUST_LOG` env. variable to override it. Running the `minimal` example will give you the most basic use of the crate but it will not be able to send data or handle change of End of Line messages -from the arduino serial plotter application. +from the Arduino Serial Plotter application. `cargo run --example minimal` @@ -52,10 +53,15 @@ random data to the `arduino-serial-plotter-webapp`: - Sends initial settings - Sends Random data with 2 different data lines -- Receives settings from the **Arduino serial plotter** and confirms a new End of Line by sending a settings message back to it -- Receives data messages sent from the **Arduino serial plotter** UI and logs them using `tracing` to the console +- Receives settings from the **Arduino Serial Plotter** and confirms a new End of Line by sending a settings message back to it +- Receives data messages sent from the **Arduino Serial Plotter** UI and logs them using `tracing` to the console ### License Licensed under either of [Apache License, Version 2.0](./LICENSE-APACHE) or [MIT license](./LICENSE-MIT) at your option. -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. \ No newline at end of file +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[build-yml]: https://img.shields.io/github/actions/workflow/status/LechevSpace/arduino-plotter/build.yml?branch=main&style=for-the-badge +[crates-io]: https://img.shields.io/crates/v/arduino-plotters?logo=rust&style=for-the-badge +[docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +[sponsor-us]: https://img.shields.io/github/sponsors/LechevSpace?color=bf3989&label=Sponsor%20us&style=for-the-badge&logoColor=bf3989&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogICAgPHBhdGggZmlsbD0iI2JmMzk4OSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNC4yNSAyLjVjLTEuMzM2IDAtMi43NSAxLjE2NC0yLjc1IDMgMCAyLjE1IDEuNTggNC4xNDQgMy4zNjUgNS42ODJBMjAuNTY1IDIwLjU2NSAwIDAwOCAxMy4zOTNhMjAuNTYxIDIwLjU2MSAwIDAwMy4xMzUtMi4yMTFDMTIuOTIgOS42NDQgMTQuNSA3LjY1IDE0LjUgNS41YzAtMS44MzYtMS40MTQtMy0yLjc1LTMtMS4zNzMgMC0yLjYwOS45ODYtMy4wMjkgMi40NTZhLjc1Ljc1IDAgMDEtMS40NDIgMEM2Ljg1OSAzLjQ4NiA1LjYyMyAyLjUgNC4yNSAyLjV6TTggMTQuMjVsLS4zNDUuNjY2LS4wMDItLjAwMS0uMDA2LS4wMDMtLjAxOC0uMDFhNy42NDMgNy42NDMgMCAwMS0uMzEtLjE3IDIyLjA3NSAyMi4wNzUgMCAwMS0zLjQzNC0yLjQxNEMyLjA0NSAxMC43MzEgMCA4LjM1IDAgNS41IDAgMi44MzYgMi4wODYgMSA0LjI1IDEgNS43OTcgMSA3LjE1MyAxLjgwMiA4IDMuMDIgOC44NDcgMS44MDIgMTAuMjAzIDEgMTEuNzUgMSAxMy45MTQgMSAxNiAyLjgzNiAxNiA1LjVjMCAyLjg1LTIuMDQ1IDUuMjMxLTMuODg1IDYuODE4YTIyLjA4IDIyLjA4IDAgMDEtMy43NDQgMi41ODRsLS4wMTguMDEtLjAwNi4wMDNoLS4wMDJMOCAxNC4yNXptMCAwbC4zNDUuNjY2YS43NTIuNzUyIDAgMDEtLjY5IDBMOCAxNC4yNXoiPjwvcGF0aD4KPC9zdmc%2BCg%3D%3D diff --git a/examples/run.rs b/examples/run.rs index afd86ef..6e992db 100644 --- a/examples/run.rs +++ b/examples/run.rs @@ -106,7 +106,7 @@ async fn run_client_task(client: Client) { } let data1_str = format!("L1:{},L2:{},L3:{}\n", data[0], data[1], data[2]); let data2_str = format!("A:{},B:{},C:{}\n", data[3], data[4], data[5]); - let data = vec![data1_str, data2_str]; + let data: Vec<&str> = vec![&data1_str, &data2_str]; let send_result = client.send(&data).await; match send_result { diff --git a/src/api.rs b/src/api.rs index 822f5d7..dbe8ee2 100644 --- a/src/api.rs +++ b/src/api.rs @@ -110,7 +110,6 @@ impl Client { } } - /// Send a [`MonitorSettings`] ([`MiddlewareCommand`]) to the Arduino Serial Plotter UI /// through an already established connection. pub async fn set_monitor_settings( @@ -131,10 +130,8 @@ impl Client { } /// Send a Data lines message to the Arduino Serial Plotter UI to plot. - /// - /// pub async fn send(&self, data: &[&str]) -> Result<(), Error> { - let data_json = serde_json::to_string(&data).expect("Should always be serializable!"); + let data_json = serde_json::to_string(data).expect("Should always be serializable!"); self.ws_sink .lock() diff --git a/src/lib.rs b/src/lib.rs index 14a93ff..d514b12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,37 @@ +//! [![sponsor-us]](https://github.com/sponsors/LechevSpace) [![crates-io]](https://crates.io/crates/arduino-plotter) [![docs-rs]](https://docs.rs/arduino-plotter) +//! +//! `arduino-plotter` provides API bindings (the [`protocol`]) and +//! [`Server`]/[`Client`] implementation for interacting with the Arduino +//! Serial Plotter web applicatoin. +//! +//! [crates-io]: https://img.shields.io/crates/v/arduino-plotters?logo=rust&style=for-the-badge +//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K +//! [sponsor-us]: https://img.shields.io/github/sponsors/LechevSpace?color=bf3989&label=Sponsor%20us&style=for-the-badge&logoColor=bf3989&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyBoZWlnaHQ9IjE2IiB2aWV3Qm94PSIwIDAgMTYgMTYiIHZlcnNpb249IjEuMSIgd2lkdGg9IjE2IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogICAgPHBhdGggZmlsbD0iI2JmMzk4OSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNC4yNSAyLjVjLTEuMzM2IDAtMi43NSAxLjE2NC0yLjc1IDMgMCAyLjE1IDEuNTggNC4xNDQgMy4zNjUgNS42ODJBMjAuNTY1IDIwLjU2NSAwIDAwOCAxMy4zOTNhMjAuNTYxIDIwLjU2MSAwIDAwMy4xMzUtMi4yMTFDMTIuOTIgOS42NDQgMTQuNSA3LjY1IDE0LjUgNS41YzAtMS44MzYtMS40MTQtMy0yLjc1LTMtMS4zNzMgMC0yLjYwOS45ODYtMy4wMjkgMi40NTZhLjc1Ljc1IDAgMDEtMS40NDIgMEM2Ljg1OSAzLjQ4NiA1LjYyMyAyLjUgNC4yNSAyLjV6TTggMTQuMjVsLS4zNDUuNjY2LS4wMDItLjAwMS0uMDA2LS4wMDMtLjAxOC0uMDFhNy42NDMgNy42NDMgMCAwMS0uMzEtLjE3IDIyLjA3NSAyMi4wNzUgMCAwMS0zLjQzNC0yLjQxNEMyLjA0NSAxMC43MzEgMCA4LjM1IDAgNS41IDAgMi44MzYgMi4wODYgMSA0LjI1IDEgNS43OTcgMSA3LjE1MyAxLjgwMiA4IDMuMDIgOC44NDcgMS44MDIgMTAuMjAzIDEgMTEuNzUgMSAxMy45MTQgMSAxNiAyLjgzNiAxNiA1LjVjMCAyLjg1LTIuMDQ1IDUuMjMxLTMuODg1IDYuODE4YTIyLjA4IDIyLjA4IDAgMDEtMy43NDQgMi41ODRsLS4wMTguMDEtLjAwNi4wMDNoLS4wMDJMOCAxNC4yNXptMCAwbC4zNDUuNjY2YS43NTIuNzUyIDAgMDEtLjY5IDBMOCAxNC4yNXoiPjwvcGF0aD4KPC9zdmc%2BCg%3D%3D +//! +//! ## Arduino Serial Plotter: +//! +//! ## Running arduino-serial-plotter webapp +//! +//! **Arduino Serial Plotter** uses WebSockets to communicate by sending or receiving commands. +//! +//! Requirements: +//! - Node v10 +//! +//! ```bash +//! git clone https://github.com/arduino/arduino-serial-plotter-webapp +//! # or when using ssh: +//! # git clone git@github.com:arduino/arduino-serial-plotter-webapp.git +//! cd arduino-serial-plotter-webapp +//! npm i && npm start +//! ``` +//! +//! Default port: **3000** +//! +//! ## Connecting +//! +//! The **Arduino Serial Plotter** will send a request to our CLI and the CLI is waiting for a connection on the websocket, this is why you need to open the arduino plotter app after starting the CLI: +//! +//! `http://localhost:3000` (with default port **3000**) #![deny(clippy::all)] #![deny(rustdoc::broken_intra_doc_links)] // only enables the `doc_cfg` feature when