shamblett / coap

A Coap package for dart
Other
16 stars 13 forks source link

observe() can not initialize localEndpoint #24

Closed TerryLiu closed 3 years ago

TerryLiu commented 3 years ago

Hi, @shamblett and @pedromassango

When I using observe() in a Flutter App, I got a fatal error:

E/flutter (12606): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'localEndpoint' was called on null. E/flutter (12606): Receiver: null E/flutter (12606): Tried calling: localEndpoint E/flutter (12606): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5) E/flutter (12606): #1 CoapEndpointManager.getDefaultEndpoint (package:coap/src/net/coap_endpoint_manager.dart:24:33) E/flutter (12606): #2 CoapClient._getEffectiveEndpoint (package:coap/src/coap_client.dart:300:34) E/flutter (12606): #3 CoapClient._observeAsync (package:coap/src/coap_client.dart:346:22) E/flutter (12606): #4 CoapClient._observe (package:coap/src/coap_client.dart:335:22) E/flutter (12606): #5 CoapClient.observe (package:coap/src/coap_client.dart:212:12) E/flutter (12606): #6 _MyHomePageState._loadData (package:flutter_firstapp/main.dart:74:25)

my first version code:

final Uri uri = Uri(scheme: 'coap',host:'192.168.0.100', port: 5683);
    // Client
   client = CoapClient(uri, config);

   final CoapRequest request = CoapRequest.newGet();
   request.addUriPath('hello');
   client.request = request;

   client.request.responses.listen((event) {
     setState(() {
       _isLoading = false;
       _data = event ?? 'No Data';
     });
   });
   var observe = client.observe();

and then after debugging, the observe() called _observeAsync()


CoapObserveClientRelation _observeAsync(CoapRequest request,
    ActionGeneric<CoapResponse> notify, ActionGeneric<FailReason> error) {
  final endpoint = _getEffectiveEndpoint(request);   // Throw the error above
  final relation = CoapObserveClientRelation(request, endpoint, _config);
  _doPrepare(request);   
  request.send();
  return relation;
}

looks as _getEffectiveEndpoint(request) need that _doPrepare(request) be called previously.

Please check it. Thanks

TerryLiu commented 3 years ago

I tried add await client.prepare(request) before var observe = client.observe() , but got a new error:

E/flutter (13991): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: type 'Future' is not a subtype of type 'CoapResponse' E/flutter (13991): #0 CoapClient._observe (package:coap/src/coap_client.dart:336:24) E/flutter (13991): #1 CoapClient.observe (package:coap/src/coap_client.dart:212:12) E/flutter (13991): #2 _MyHomePageState._loadData (package:flutter_firstapp/main.dart:74:25)

The source code is:

CoapObserveClientRelation _observe(CoapRequest request,
      ActionGeneric<CoapResponse> notify, ActionGeneric<FailReason> error) {
    final relation = _observeAsync(request, notify, error);
    final CoapResponse response = relation.request.waitForResponse(timeout);  // this line throw the error
    if (response == null || !response.hasOption(optionTypeObserve)) {
      relation.cancelled = true;
    }
    relation.current = response;
    return relation;
  }
TerryLiu commented 3 years ago

btw, the client.prepare(request) has the probability of being executed multiple times

pedromassango commented 3 years ago

Assuming that your code is correct, this may be an issue with this package and @shamblett could take a look

shamblett commented 3 years ago

I'm not sure what you are trying to do, if you want to observe a remote resource you simply add 'obs' to the URI path and listen to the incoming updates as @pedromassango has already said, here is an example that works in the VM -

import 'dart:async';
import 'package:coap/coap.dart';
import 'config/coap_config.dart';

FutureOr main() async {
  // Create a configuration class. Logging levels can be specified in the
  // configuration file.
  final conf = CoapConfig();
  print('ISSUE: max retransmit from configuration is ${conf.maxRetransmit}');

  // Build the request uri, note that the request paths/query parameters can be changed
  // on the request anytime after this initial setup.
  const host = 'coap.me';

  final uri = Uri(scheme: 'coap', host: host, port: conf.defaultPort);

  // Create the client.
  // The method we are using creates its own request so we do not
  // need to supply one.
  // The current request is always available from the client.
  final client = CoapClient(uri, conf);

  // Create the request for the get request
  final request = CoapRequest.withType(CoapCode.methodGET);
  request.addUriPath('obs');
  print('ISSUE: max retransmit from request is ${request.maxRetransmit}');

  // You can override the configured maxretransmit setting on a request by request basis
  //request.maxRetransmit = 2;
  print('ISSUE: max retransmit from request is now ${request.maxRetransmit}');
  // Getting responses from the observable resource
  request.responses.listen((CoapResponse response) {
    print('ISSUE: - payload: ${response.payloadString}');
  });

  client.request = request;

  print('ISSUE: - Sending get request to '
      '$host, waiting for responses ....');
  await client.get();
}

These kind of errors 'E/flutter (12606): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)' are usually produced when you dispose of a resource and use it again or something like that. I can't check your code above as I've said I don't use flutter.

shamblett commented 3 years ago

Forgot to mention, if you look through the closed issues you will find a few examples of flutter code using the package with no problems.

TerryLiu commented 3 years ago

Forgot to mention, if you look through the closed issues you will find a few examples of flutter code using the package with no problems.

ok, Thanks for reply. I'm try agin.