shamblett / mqtt_client

A server and browser based MQTT client for dart
Other
548 stars 176 forks source link

MqttBrowserClient Error: Expected a value of type 'ByteBuffer', but got one of type 'String' #473

Closed naychrist closed 1 year ago

naychrist commented 1 year ago

hi there, I need to have a MQTT client working in both flutter web and flutter desktop. In some cases this will work with a local mosquito broker and in others it will work with Ably's MQTT adapter.

First I am trying to get the browser client to connect to Ably. The example code connects fine with 'wss://test.mosquitto.org' and port 8081. But when I try and connect to the ably broker I get an error. I can connect to it in javascript without issue as outlined here. But this is the log when trying to do the same using this lib:

1-2023-07-04 12:34:58.929 -- MqttClient::connect - Connection timeout period is 5000 milliseconds
1-2023-07-04 12:34:58.930 -- MqttClient::connect - keep alive is enabled with a value of 15 seconds
1-2023-07-04 12:34:58.931 -- MqttConnectionKeepAlive:: Initialised with a keep alive value of 15 seconds
1-2023-07-04 12:34:58.931 -- MqttConnectionKeepAlive:: Disconnect on no ping response is disabled
1-2023-07-04 12:34:58.931 -- MqttConnectionHandlerBase::connect - server wss://mqtt.ably.io, port 8883
1-2023-07-04 12:34:58.931 -- SynchronousMqttBrowserConnectionHandler::internalConnect entered
1-2023-07-04 12:34:58.931 -- SynchronousMqttBrowserConnectionHandler::internalConnect - initiating connection try 0, auto reconnect in progress false
1-2023-07-04 12:34:58.931 -- SynchronousMqttBrowserConnectionHandler::internalConnect - calling connect
1-2023-07-04 12:34:58.932 -- MqttBrowserWsConnection::connect - entered
1-2023-07-04 12:34:58.932 -- MqttBrowserWsConnection::connect -  WS URL is wss://mqtt.ably.io:8883
1-2023-07-04 12:34:58.933 -- MqttBrowserWsConnection::connect - connection is waiting
1-2023-07-04 12:34:59.228 -- MqttBrowserWsConnection::connect - websocket is open
1-2023-07-04 12:34:59.228 -- MqttBrowserConnection::_startListening
1-2023-07-04 12:34:59.228 -- SynchronousMqttBrowserConnectionHandler::internalConnect - connection complete
1-2023-07-04 12:34:59.228 -- SynchronousMqttBrowserConnectionHandler::internalConnect sending connect message
1-2023-07-04 12:34:59.228 -- MqttConnectionHandlerBase::sendMessage - MQTTMessage of type MqttMessageType.connect
Header: MessageType = MqttMessageType.connect, Duplicate = false, Retain = false, Qos = MqttQos.atMostOnce, Size = 0
Connect Variable Header: ProtocolName=MQTT, ProtocolVersion=4, ConnectFlags=Connect Flags: Reserved1=false, CleanStart=false, WillFlag=false, WillQos=MqttQos.atMostOnce, WillRetain=false, PasswordFlag=true, UserNameFlag=true, KeepAlive=15
MqttConnectPayload - client identifier is : 

1-2023-07-04 12:34:59.230 -- SynchronousMqttBrowserConnectionHandler::internalConnect - pre sleep, state = Connection status is connecting with return code of noneSpecified and a disconnection origin of none
1-2023-07-04 12:34:59.230 -- MqttBrowserConnection::_onData
Error: Expected a value of type 'ByteBuffer', but got one of type 'String'
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 288:49                           throw_
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 121:3                            castError
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 529:12                       cast
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/classes.dart 638:14                          as_C
packages/mqtt_client/src/connectionhandling/browser/mqtt_client_mqtt_browser_connection.dart 41:26     onData
packages/mqtt_client/src/connectionhandling/browser/mqtt_client_mqtt_browser_ws_connection.dart 208:9  <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 367:37                       _checkAndCall
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 372:39                       dcall
dart-sdk/lib/html/dart2js/html_dart2js.dart 37236:58                                                   <fn>
1-2023-07-04 12:34:59.313 -- MqttBrowserConnection::_startListening - websocket is closed
1-2023-07-04 12:34:59.314 -- MqttConnectionBase::_onDone - calling disconnected callback

Any advice? stripped back version of my code below:

    // client = MqttBrowserClient('wss://test.mosquitto.org', '');
    client = MqttBrowserClient.withPort('wss://mqtt.ably.io','',8883);

    /// Set logging on if needed, defaults to off
    client.logging(on: true);
    /// Set the correct MQTT protocol for mosquito
    client.setProtocolV311();
    /// If you intend to use a keep alive you must set it here otherwise keep alive will be disabled.
    client.keepAlivePeriod = 15;
    /// The connection timeout period can be set if needed, the default is 5 seconds.
    client.connectTimeoutPeriod = 5000; // milliseconds

    /// Set the appropriate websocket headers for your connection/broker.
    /// Mosquito uses the single default header, other brokers may be fine with the
    /// default headers.
    client.websocketProtocols = MqttClientConstants.protocolsSingleDefault;

    /// Create a connection message to use or use the default one. The default one sets the
    /// client identifier, any supplied username/password and clean session,
    /// an example of a specific one below.
    final connMess = MqttConnectMessage()
        .authenticateAs(username, password);
    print('EXAMPLE::Mosquitto client connecting....');
    client.connectionMessage = connMess;

    /// Connect the client
    try {
      print('about to connect...');
      await client.connect();
    } on Exception catch (e) {
      print('EXAMPLE::client exception - $e');
      client.disconnect();
      return -1;
    }
naychrist commented 1 year ago

I put a trace in and the string I am getting back from the broker is {"action":9,"error":{"message":"No authentication information provided. (See https://help.ably.io/error/40101 for help.)","code":40101,"statusCode":401,"nonfatal":false,"href":"https://help.ably.io/error/40101"},"timestamp":1688445446903} despite me sending the correct username and pass. took a look at the link to see what I am missing but credentials are correct: https://faqs.ably.com/40101-invalid-credentials

I think the issue may be that ably only supports mqtts:// not wss://, which is the reverse of what this lib supports. Is it trivial to add support for mqtts? (i have reach out to ably support also)

shamblett commented 1 year ago

OK, mqtts is just MQTT with secure working, see here as far as I can see, the client does support this using secure working but on the server side only, in the browser you can't use secure sockets only web sockets.

The broker should have responded to you using a correctly formed connect ack message with the relevant return code which in your case should be notAuthorized. It shouldn't return an arbitrary json string to an MQTT client.

naychrist commented 1 year ago

Ok, looks like for flutter web I would need to wrap mqtt.js using dart's js interop. Still planning to use your MqttServerClient for Flutter Mac and Windows Desktop. Have passed on your note re response to ably team. Thanks!

EDIT - actually makes more sense to wrap ably SDK when talking to that but will use browser client for another use case talking to local mosquitto server