commit 143b3b057b30209a13db48fb760410b15b86ab59 Author: Dave Date: Tue Jul 30 11:17:58 2024 -0400 Initial tutorial commit diff --git a/gem-remotes-esp32/.cargo/config.toml b/gem-remotes-esp32/.cargo/config.toml new file mode 100644 index 0000000..6065d79 --- /dev/null +++ b/gem-remotes-esp32/.cargo/config.toml @@ -0,0 +1,18 @@ +[build] +target = "xtensa-esp32-espidf" + +[target.xtensa-esp32-espidf] +linker = "ldproxy" +runner = "espflash flash --monitor" # Select this runner for espflash v3.x.x +rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110 + +[unstable] +build-std = ["std", "panic_abort"] + +[env] +MCU="esp32" +# Note: this variable is not used by the pio builder (`cargo build --features pio`) +ESP_IDF_VERSION = "v5.2.2" + +# Workaround for https://github.com/esp-rs/esp-idf-template/issues/174 +CRATE_CC_NO_DEFAULTS = "1" diff --git a/gem-remotes-esp32/.github/workflows/rust_ci.yml b/gem-remotes-esp32/.github/workflows/rust_ci.yml new file mode 100644 index 0000000..4cb27b8 --- /dev/null +++ b/gem-remotes-esp32/.github/workflows/rust_ci.yml @@ -0,0 +1,40 @@ +name: Continuous Integration + +on: + push: + paths-ignore: + - "**/README.md" + pull_request: + workflow_dispatch: + +env: + CARGO_TERM_COLOR: always + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +jobs: + rust-checks: + name: Rust Checks + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + action: + - command: build + args: --release + - command: fmt + args: --all -- --check --color always + - command: clippy + args: --all-targets --all-features --workspace -- -D warnings + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Rust + uses: esp-rs/xtensa-toolchain@v1.5 + with: + default: true + buildtargets: esp32 + ldproxy: true + - name: Enable caching + uses: Swatinem/rust-cache@v2 + - name: Run command + run: cargo ${{ matrix.action.command }} ${{ matrix.action.args }} diff --git a/gem-remotes-esp32/.gitignore b/gem-remotes-esp32/.gitignore new file mode 100644 index 0000000..73a638b --- /dev/null +++ b/gem-remotes-esp32/.gitignore @@ -0,0 +1,4 @@ +/.vscode +/.embuild +/target +/Cargo.lock diff --git a/gem-remotes-esp32/Cargo.toml b/gem-remotes-esp32/Cargo.toml new file mode 100644 index 0000000..e8f08a6 --- /dev/null +++ b/gem-remotes-esp32/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "gem-remotes-esp32" +version = "0.1.0" +authors = ["Dave "] +edition = "2021" +resolver = "2" +rust-version = "1.77" + +[[bin]] +name = "gem-remotes-esp32" +harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors + +[profile.release] +opt-level = "s" + +[profile.dev] +debug = true # Symbols are nice and they don't increase the size on Flash +opt-level = "z" + +[features] +default = ["std", "embassy", "esp-idf-svc/native"] + +pio = ["esp-idf-svc/pio"] +std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] +alloc = ["esp-idf-svc/alloc"] +nightly = ["esp-idf-svc/nightly"] +experimental = ["esp-idf-svc/experimental"] +embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"] + +[dependencies] +log = { version = "0.4", default-features = false } +esp-idf-svc = { version = "0.49", default-features = false } +esp32-nimble = "0.7.0" +esp-idf-hal = "0.44.1" +esp-idf-sys = "0.35.0" + +[build-dependencies] +embuild = "0.32.0" diff --git a/gem-remotes-esp32/build.rs b/gem-remotes-esp32/build.rs new file mode 100644 index 0000000..112ec3f --- /dev/null +++ b/gem-remotes-esp32/build.rs @@ -0,0 +1,3 @@ +fn main() { + embuild::espidf::sysenv::output(); +} diff --git a/gem-remotes-esp32/rust-toolchain.toml b/gem-remotes-esp32/rust-toolchain.toml new file mode 100644 index 0000000..a2f5ab5 --- /dev/null +++ b/gem-remotes-esp32/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "esp" diff --git a/gem-remotes-esp32/sdkconfig.defaults b/gem-remotes-esp32/sdkconfig.defaults new file mode 100644 index 0000000..8bb42fe --- /dev/null +++ b/gem-remotes-esp32/sdkconfig.defaults @@ -0,0 +1,19 @@ +# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K) +CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000 + +# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default). +# This allows to use 1 ms granuality for thread sleeps (10 ms by default). +#CONFIG_FREERTOS_HZ=1000 + +# Workaround for https://github.com/espressif/esp-idf/issues/7631 +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n +#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n + +# NimBLE flags for bluetooth +CONFIG_BT_ENABLED=y +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=n +CONFIG_BT_NIMBLE_ENABLED=y + +# Store BLE info in NVS +CONFIG_BT_NIMBLE_NVS_PERSIST=y \ No newline at end of file diff --git a/gem-remotes-esp32/src/main.rs b/gem-remotes-esp32/src/main.rs new file mode 100644 index 0000000..c6312c6 --- /dev/null +++ b/gem-remotes-esp32/src/main.rs @@ -0,0 +1,81 @@ + + +use esp32_nimble::{enums::*, uuid128, BLEAdvertisementData, BLEDevice, NimbleProperties}; +use esp_idf_hal::delay::FreeRtos; +use esp_idf_sys as _; + +fn main() { + esp_idf_sys::link_patches(); + + // Bind the log crate to the ESP Logging facilities + esp_idf_svc::log::EspLogger::initialize_default(); + + // Take ownership of device + let ble_device = BLEDevice::take(); + + // Obtain handle for peripheral advertiser + let ble_advertiser = ble_device.get_advertising(); + + // Configure Device Security + ble_device + .security() + .set_auth(AuthReq::all()) + .set_passkey(123456) + .set_io_cap(SecurityIOCap::DisplayOnly) + .resolve_rpa(); + + // Obtain handle for server + let server = ble_device.get_server(); + + // Define server connect behaviour + server.on_connect(|server, clntdesc| { + // Print connected client data + println!("{:?}", clntdesc); + // Update connection parameters + server + .update_conn_params(clntdesc.conn_handle(), 24, 48, 0, 60) + .unwrap(); + }); + + // Define server disconnect behaviour + server.on_disconnect(|_desc, _reason| { + println!("Disconnected, back to advertising"); + }); + + // Create a service with custom UUID + let my_service = server.create_service(uuid128!("9b574847-f706-436c-bed7-fc01eb0965c1")); + + // Create a characteristic to associate with created service + let my_service_characteristic = my_service.lock().create_characteristic( + uuid128!("681285a6-247f-48c6-80ad-68c3dce18585"), + NimbleProperties::READ | NimbleProperties::READ_ENC, + ); + + // Modify characteristic value + my_service_characteristic.lock().set_value(b"Start Value"); + + // Configure Advertiser Data + ble_advertiser + .lock() + .set_data( + BLEAdvertisementData::new() + .name("ESP32 Server") + .add_service_uuid(uuid128!("9b574847-f706-436c-bed7-fc01eb0965c1")), + ) + .unwrap(); + + // Start Advertising + ble_advertiser.lock().start().unwrap(); + + // (Optional) Print dump of local GATT table + // server.ble_gatts_show_local(); + + // Init a value to pass to characteristic + let mut val = 0; + + loop { + FreeRtos::delay_ms(1000); + my_service_characteristic.lock().set_value(&[val]).notify(); + val = val.wrapping_add(1); + } +}