'Web bluetooth sending and receiveing issue#2

My issue is simple. Can receive data, cannot send data.

I try to send and receive to and from BLE device by web bluetooth. This app runs on Android. This device has a pincode authentication.(I can't disable pincode, just can change) When I run requestDevice() api function, I get this exception: DOM exception: GATT operation is not permitted. I went through web bluetooth api about this exception and this doesn't help me. Even though this error occurs, I can receive from BLE device but not send data(seems not happening). Here is my code.

import React, { useEffect, useState } from "react";
import { Button, Col, Container, Row } from "reactstrap";
import "./App.css";
import Swal from 'sweetalert2';
import { NotificationContainer, NotificationManager } from 'react-notifications';
let bluetoothDevice, sendCharacteristic, receiveCharacteristic;

let primaryServiceUuid = null;
let receiveCharUuid = null;
let sendCharUuid = null;


const App = () => {

  const [isEnabled, setIsEnabled] = useState(true);

  useEffect(() => {
    navigator.bluetooth.getAvailability().then(available => {
      if (available) {
        NotificationManager.success('Success to access Bluetooth');
        setIsEnabled(true);
      }
      else {
        Swal.fire({
          title: 'Sorry, Your device is not Bluetoothable.',
          icon: 'error',
          confirmButtonColor: 'rgb(200, 35, 51)'
        });
        setIsEnabled(false);
      }
    });
  }, []);

  const onClickConnect = async () => {
    let serviceUuid = document.getElementById('serviceUuid').value;
    if(!serviceUuid) return NotificationManager.error('Please fill Service UUID.');
    if (serviceUuid.startsWith('0x')) {
      primaryServiceUuid = parseInt(serviceUuid);
    } else return NotificationManager.error('Wrong Format: Service UUID.');
    let sendUuid = document.getElementById('sendUuid').value;
    if(!sendUuid) return NotificationManager.error('Please fill Send UUID.');
    if (sendUuid.startsWith('0x')) {
      sendCharUuid = parseInt(sendUuid);
    } else return NotificationManager.error('Wrong Format: Send UUID.');
    // let receiveUuid = document.getElementById('receiveUuid').value;
    // if(!receiveUuid) return NotificationManager.error('Please fill Recieve UUID.');
    // if (receiveUuid.startsWith('0x')) {
    //   receiveCharUuid = parseInt(sendUuid);
    // };
    bluetoothDevice = null;
    bluetoothDevice = await navigator.bluetooth.requestDevice({
                acceptAllDevices: true,
                optionalServices: [primaryServiceUuid]
    });
    const server = await bluetoothDevice.gatt.connect();
    if (!server) {
      return NotificationManager.error('Whoops, failed. Retry: server not found');
    }
    const service = await server.getPrimaryService(primaryServiceUuid);
    if (!service) {
      return NotificationManager.error('Whoops, failed. Retry: service not found');
    }
    // receiveCharacteristic = await service.getCharacteristic(receiveCharUuid);
    // if (!receiveCharacteristic) {
    //   return NotificationManager.error('Whoops, failed. Retry: Receive characteristic not found.');
    // }
    sendCharacteristic = await service.getCharacteristic(sendCharUuid);
    if (!sendCharacteristic) {
      return NotificationManager.error('Whoops, failed. Retry: Send characteristic not found.');
    }
    receiveCharacteristic = sendCharacteristic;
    document.getElementById('connected').innerHTML = 'connected';
    document.getElementById('connected').style.backgroundColor = 'green';
    NotificationManager.success('Success to pair Bluetooth Device');
  }

  const listen = async () => {
    if (receiveCharacteristic) {
      receiveCharacteristic
        .addEventListener('characteristicvaluechanged',
          (evt) => {
            const value = evt.target.value.getInt16(0, true);
            document.getElementById('receiveValue').value = value;
          });

      receiveCharacteristic.startNotifications();
    }
  }

  const disconnect = () => {
    bluetoothDevice = null;
    receiveCharacteristic = null;
    sendCharacteristic = null;
    document.getElementById('connected').innerHTML = 'disconnected';
    document.getElementById('connected').style.backgroundColor = '';
  }

  const onClickDisconnect = () => {
    if (!bluetoothDevice) {
      return NotificationManager.warning('No device connected.');
    }
    if (bluetoothDevice.gatt.connected) {
      bluetoothDevice.gatt.disconnect();
      disconnect();
      NotificationManager.success('Disconnected.');
    } else {
      NotificationManager.warning('Alredy disconnected');
    }
  }

  const onClickSend = async () => {
    if(!bluetoothDevice) return NotificationManager.warning('No device connected.');
    const sendText = document.getElementById('sendText').value;
    if (!sendText) return NotificationManager.error('Please fill send field.');
    var _sendText = String(sendText);
    // console.log(_sendText, new TextEncoder().encode(_sendText));
    if (sendCharacteristic) sendCharacteristic.writeValue(new TextEncoder().encode(_sendText));
    else NotificationManager.error('Whoops, sorry , retry : send:send');
  }

  const onClickReceive = () => {
    if(!bluetoothDevice) return NotificationManager.warning('No device connected.');
    return listen();
  }

  return (
    <div className="App">
      <Container>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Service UUID: </span>
          </Col>
          <Col xs={8} md={6} lg={4} className="d-flex align-items-center">
            <input placeholder="ex: 0xFFE0" type="text" id="serviceUuid" className="col-10 rounded"></input>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Send UUID: </span>
          </Col>
          <Col xs={8} md={6} lg={4} className="d-flex align-items-center">
            <input placeholder="ex: 0xFFE1" type="text" id="sendUuid" className="col-10 rounded"></input>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Recieve UUID: </span>
          </Col>
          <Col xs={8} md={6} lg={4} className="d-flex align-items-center">
            <input placeholder="ex: 0xFFE2" type="text" id="receiveUuid" className="col-10 rounded"></input>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Send &nbsp;&nbsp;&nbsp;&nbsp;: </span>
          </Col>
          <Col xs={8} md={6} lg={4} className="d-flex align-items-center">
            <input placeholder="Type here..." type="text" id="sendText" className="col-10 rounded"></input>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Receive : </span>
          </Col>
          <Col xs={8} md={6} lg={4} className="d-flex align-items-center">
            <input placeholder="Receive text will be displayed here." id="receiveValue" className="col-10 bg-white rounded" disabled></input>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around my-2">
          <Col xs={4} md={3} lg={2} className="text-right">
            <span className="text-white">Status &nbsp; :</span>
          </Col>
          <Col xs={8} md={6} lg={4}>
            <div id="connected" className="col-10 text-white text-center border rounded-lg px-2">
              disconnected
            </div>
          </Col>
        </Row>
        <Row className="d-flex justify-content-around">
          <Col xs={6} md={3} lg={2} className="text-center my-3">
            <Button className="w-75" color="primary" onClick={onClickConnect} disabled={!isEnabled}>Connect</Button>
          </Col>

          <Col xs={6} md={3} lg={2} className="text-center my-3">
            <Button className="w-75" color="success" onClick={onClickReceive} disabled={!isEnabled}>Recieve</Button>
          </Col>

          <Col xs={6} md={3} lg={2} className="text-center my-3">
            <Button className="w-75" color="info" onClick={onClickSend} disabled={!isEnabled}>Send</Button>
          </Col>

          <Col xs={6} md={3} lg={2} className="text-center my-3">
            <Button className="w-75" color="danger" onClick={onClickDisconnect} disabled={!isEnabled}>Disconnect</Button>
          </Col>
        </Row>
        <NotificationContainer />
      </Container>
    </div >
  );
};

export default App;

Anybody knows solution?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source