admin 管理员组

文章数量: 1086019

I am building a bluetooth service. I was able to make unary call from client to server to turn on bluetooth and discover device. My Bluetooth engine class "registers events", and listens to changes in the BlueZ list of discovered devices:

_clientBlueZ.deviceAdded.listen((device) => _onDeviceAdded(device));
_clientBlueZ.deviceRemoved.listen((device) => _onDeviceRemoved(device));

Now I need to "publish" the devices to grpc channel so that client can listen to it. I am taking reference from BlueZ sourcecode itself but still have issue:

  • BlueZ packages uses "stream controller" to add device to stream. deviceAdded is like a property, with get function returns _deviceAddedStreamController.stream.
Stream<BlueZDevice> get deviceAdded => _deviceAddedStreamController.stream;
  • When an object is somehow found, the stream adds that object.
_adapterAddedStreamController.add(BlueZAdapter(this, object));
  • To get changes from the stream, then _onDeviceAdded.listen is used.

Fair enough. I try to replicate the same concept and publish the discovered devices to grpc channel and then to client with the following steps, but they don't work quite right:

  1. First, I initialize an instance of stream controller in my BluetoothEngine class:
final StreamController<AllDeviceStatusRes> _deviceStatusController 
    = StreamController<AllDeviceStatusRes>();

  StreamController<AllDeviceStatusRes> get deviceStatusController 
    => _deviceStatusController;
  1. in _onDeviceAdd I invoke another function _addToStream to add to the stream the device:
void _addToStream(String deviceId, String deviceName, String address, bool isPaired, bool isConnected){
    // add to stream so that BluetoothService can send to grpc
    BluetoothDeviceRes deviceRes = BluetoothDeviceRes()
      ..deviceId = deviceId
      ..deviceName = deviceName
      ..deviceAddress = address
      ..isPaired = isPaired
      ..isConnected = isConnected;

    _deviceStatusController.add(AllDeviceStatusRes()..device = deviceRes);
  }
  1. BluetoothService is the actually class that sends data to the grpc server. It implements streamDeviceStatus function that return stream of devices. Of course BluetoothEngine is initialized within BluetoothService
class BluetoothService extends BluetoothServiceBase{
  final BluetoothEngine _bleCtrl = BluetoothCEngine();
 @override
  Stream<AllDeviceStatusRes> streamDeviceStatus(grpc.ServiceCall call, AllDeviceStatusReq 
    request) {
    print ("send device status update to grpc");
    return _bleCtrl.deviceStatusController.stream;
  }
}
  1. On the client side, I implement streamDeviceStatus.
class BluetoothClient {
  // it is like a Client, thus it makes connection to grpc first:
  late final ClientChannel channel;
  late final BluetoothServiceClient _stup;
  BluetoothClient() {
    channel = ClientChannel(
      'localhost', 
      port: 50051, 
      options: const ChannelOptions(credentials: ChannelCredentials.insecure()),
    );
    _stup = BluetoothServiceClient(channel);
    print('client listens to port 50051');
  }
   Future<void> streamDeviceStatus(AllDeviceStatusReq request) async {
    final responseStream = await _stup.streamDeviceStatus(request);
    responseStream.listen((response) {
      print("Received device status:  ${response.device.deviceName} 
            ${response.device.deviceAddress} ${response.device.isPaired} 
             ${response.device.isConnected} ");
      // do other changes to models, and views on client sides 
    });
  }
}

I think step 2 or 4 may be wrong. I expect that streamDeviceStatus is invoked on client side, and that the console must at least prints out the device information on client side. But I don't have any yet.

I run command bluetoothctl and check console log on server and client and see that the prerequisite steps have been done. There was starting bluetooth, scanning on both server and client side. There was device discovered on server side.

Please help me.

本文标签: flutterHow to receive update or stream of data from server using dart grpc packageStack Overflow