Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stuck on "Provisioning" #212

Closed
Fristi opened this issue Jun 19, 2023 · 1 comment
Closed

Stuck on "Provisioning" #212

Fristi opened this issue Jun 19, 2023 · 1 comment

Comments

@Fristi
Copy link

Fristi commented Jun 19, 2023

Hi,

  • Using Chrome 114.0.5735.133 on a MacBook M1 Pro
  • I see the GATT server and it's services + characteristics at about://bluetooth-internals
  • Using the JS SDK button at https://www.improv-wifi.com/code/ I'm able to connect to the Improv BLE server, after that I need to enter my SSID + password. After that it's stuck on "Provisioning".

When I look in my GATT server console I see a client connected, but no RPC messages being received.

I'm writing a Rust GATT version of Improv. I'm using a ESP32 + IDF + Bluedroid

The setup works when I connect with Lightblue and use the following hex string 011e0c4d79576972656c6573734150106d7973656375726570617373776f7264.
I see the GATT server picks up the message.

I've also managed to connect and successfully send the byte string message like this:

<html>
    <head>
        <script>

            const fromHexString = (hexString) =>
                Uint8Array.from(hexString.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)));

            function handleConnect() {
                

                const service = "00467768-6228-2272-4663-277478268000";

                navigator.bluetooth.requestDevice({ filters: [{ services: [service] }] })
                    .then(device => device.gatt.connect())
                    .then(server => {
                        return server.getPrimaryService(service);
                    })
                    .then(service => {
                        return service.getCharacteristic("00467768-6228-2272-4663-277478268003");
                    })
                    .then(characteristic => {
                        const byteString = "011e0c4d79576972656c6573734150106d7973656375726570617373776f7264";
                        const bytes = fromHexString(byteString);
                        characteristic.writeValue(bytes);
                    })
                    .catch(error => { console.error(error); });
            }
        </script>
    </head>
    <body>
        <button onclick="handleConnect()">Connect</button>
    </body>
</html>

GATT server:

fn main() -> ! {
    // It is necessary to call this function once. Otherwise some patches to the runtime
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
    esp_idf_sys::link_patches();
    // Bind the log crate to the ESP Logging facilities
    esp_idf_svc::log::EspLogger::initialize_default();

    let state = Arc::new(RwLock::new(State::Authorized));
    let state_read = state.clone();
    let error = Arc::new(RwLock::new(Error::None));
    let error_read = error.clone();

    let current_state = Characteristic::new(BleUuid::from_uuid128_string(IMPROV_STATUS_UUID))
        .name("Current state")
        .permissions(AttributePermissions::new().read())
        .properties(CharacteristicProperties::new().read().notify())
        .show_name()
        .on_read(move |_| {
            let s = state_read.read().unwrap();
            let ss = *s;
            vec![ss.into()]
        })
        .build();

    let error_state = Characteristic::new(BleUuid::from_uuid128_string(IMPROV_ERROR_UUID))
        .name("Error state")
        .permissions(AttributePermissions::new().read())
        .properties(CharacteristicProperties::new().read().notify())
        .show_name()
        .on_read(move |_| {
            let s = error_read.read().unwrap();
            let ss = *s;
            vec![ss.into()]
        })
        .build();

    let rpc_command = Characteristic::new(BleUuid::from_uuid128_string(IMPROV_RPC_COMMAND_UUID))
        .name("RPC command handler")
        .permissions(AttributePermissions::new().write())
        .properties(CharacteristicProperties::new().write())
        .on_write(move |bytes, _| {
            match ImprovCommand::from_bytes(bytes.as_slice()) {
                Ok(ImprovCommand::WifiSettings { ssid, password }) => {
                    info!("Got ssid and password: {} {}", ssid, password);
                    *state.write().unwrap() = State::Provisioning;
                    *error.write().unwrap() = Error::None;
                    match wifi(&ssid, &password) {
                        Ok(_) => {
                            *state.write().unwrap() = State::Provisioned;
                            info!("Connected")
                        },
                        Err(err) => {
                            info!("Error {}", err);
                            *error.write().unwrap() = Error::UnableToConnect;
                            *state.write().unwrap() = State::Authorized;
                            return ()
                        }
                    }
                    return ()
                }
                Ok(cmd) => {
                    info!("Command not processed {:?}", cmd);
                    return ()
                }
                Err(err) => {
                    info!("Error {:?}", err);
                    return ()
                }
            }
        })
        .show_name()
        .build();


    let rpc_result = Characteristic::new(BleUuid::from_uuid128_string(IMPROV_RPC_RESULT_UUID))
        .name("RPC result")
        .permissions(AttributePermissions::new().read())
        .properties(CharacteristicProperties::new().read().notify())
        .show_name()
        .build();

    let capabilities = Characteristic::new(BleUuid::from_uuid128_string(IMPROV_CAPABILITIES_UUID))
        .name("Capabilities")
        .permissions(AttributePermissions::new().read())
        .properties(CharacteristicProperties::new().read())
        .show_name()
        .set_value([0x00])
        .build();


    let service = Service::new(BleUuid::from_uuid128_string(IMPROV_SERVICE_UUID))
        .name("Improv Service")
        .primary()
        .characteristic(&rpc_command)
        .characteristic(&rpc_result)
        .characteristic(&current_state)
        .characteristic(&error_state)
        .characteristic(&capabilities)
        .build();

    let profile = Profile::new(0x0001)
        .name("Default Profile")
        .service(&service)
        .build();

    GLOBAL_GATT_SERVER
        .lock()
        .unwrap()
        .profile(profile)
        .device_name("Improve onboarding")
        .appearance(bluedroid::utilities::Appearance::GenericComputer)
        .advertise_service(&service)
        .start();

    loop {
        std::thread::sleep(Duration::from_millis(100));
    }
}
@Fristi
Copy link
Author

Fristi commented Sep 12, 2023

Closing due inactivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant