Need help for error: "Invalid '$.Toybox.Lang.Object' passed as parameter 1 of type '$.Toybox.BluetoothLowEnergy.Device'."

What's wrong with this snippet of code? Compiler complains the _device parameter. But i can't see my error. Code belongs to a BLE delegate.

function disconnectDevice() {

        var _device = Ble.getPairedDevices().next();    // get first device (since we only connect to one at a time)
        if (_device != null)
        {
            Ble.unpairDevice(_device);
        }
        state = State_Disconnected;
    }


ERROR: edge1030plus: Invalid '$.Toybox.Lang.Object' passed as parameter 1 of type '$.Toybox.BluetoothLowEnergy.Device'.

  • Are you sure there's even one paired when this is called?

    If Ble.getPairedDevives() is null, you'd be doing a next() on null

    It's best to do something like

    var device=null;
    var iter=Ble.getPairedDevices();
    if(iter!=null) {
        device=iter.next();
        //other stuff    
    }

  • Good point!
    I changed the code as follows:

    function disconnectDevice() {
            var device=null;
            var iter=Ble.getPairedDevices();
            if(iter!=null)
            {
                device=iter.next();
                Ble.unpairDevice(device);
                state = State_Disconnected;  
            }
        }
    Now the compiler complains the line Ble.unpairDevice(device) with error
    Invalid 'PolyType<Null or $.Toybox.Lang.Object>' passed as parameter 1 of type '$.Toybox.BluetoothLowEnergy.Device'.
    Strange!
  • If Ble.getPairedDevives() is null, you'd be doing a next() on null

    But according to the Monkey C docs, getPairedDevices() always returns a BluetoothLowEnergy.Iterator (and not null). (I realize reality may be different, but in that case, the documentation is wrong.)

    What's wrong with this snippet of code? Compiler complains the _device parameter. But i can't see my error. Code belongs to a BLE delegate.

    BluetoothLowEnergy.Iterator.next() returns an Object or Null, not BluetoothLowEnergy.Device. Whether or not this is seen as a bug/limitation in the API, I think your only choice is to change the code to do an explicit cast. e.g.:

    device = iter.next();
    if (device != null) {
      Ble.unpairDevice(device as BluetoothLowEnergy.Device);
      //...
    }

  • Thanks, the compiler now takes this. Without your hint i never would have solved this. Monkey C is a strange language...

  • Alternatively you could turn off type checking with the runtime parameter -l0

  • Still fighting with the types, now for BLE ScanResults...

    // If a scan is running this will be called when new ScanResults are received
        function onScanResults(iter as Ble.Iterator) {
            debug("onScanResults");

            for (var r = iter.next(); r != null; r = iter.next())
            {
               
                // first try connect via MAC address, if user has set one
                if (MACArray != null)
                {
                    debug("trying MAC address " + MACArray.toString());
                    if (r.hasAddress(MACArray))
                    {
                        connectDevice(r);
                        return;
                    }
                }
    ...
    produces

    Cannot find symbol ':hasAddress' on type '$.Toybox.Lang.Object' for line
    "if (r.hasAddress(MACArray))"
    and 
    Invalid '$.Toybox.Lang.Object' passed as parameter 1 of type '$.Toybox.BluetoothLowEnergy.ScanResult' for line
    "connectDevice(r);"
     
    Again, some help on this would probably save me lots of time... - thanks!
  • Turn off type checking, and make sure things still compile Type checking is on by default with the beta compiler..

    If you want to use type checking, see this https://forums.garmin.com/developer/connect-iq/b/news-announcements/posts/the-road-to-strict-typing-is-paved-with-good-intentions

    as well as this.

    https://developer.garmin.com/connect-iq/monkey-c/monkey-types/

  • It's the same problem as before: the iterator returns a generic Object, but you need a specific type -- in this case, BluetoothLowEnergy.ScanResult.

    Try this (add the bolded line):

    for (var r = iter.next(); r != null; r = iter.next())
    {
      r = r as BluetoothLowEnergy.ScanResult;
      ...
  • bodybatt = Toybox.SensorHistory.getBodyBatteryHistory({
    :period => 1,
    :order => true,
    });

    Invalid '$.Toybox.Lang.Dictionary{:period as $.Toybox.Lang.Number, :order as $.Toybox.Lang.Boolean}' passed as parameter 1 of type 'PolyType<Null or {:period as Null or $.Toybox.Lang.Number or $.Toybox.Time.Duration, :order as $.Toybox.SensorHistory.Order}>'.

    Similar issue after using the SDK 4.1.6 to export my project.I have turned off the type check.

    If I change the sdk version to 4.1.5. it works fine.

  • You are passing a Boolean where the compiler expects a parameter of type $.Toybox.SensorHistory.Order. Change the value from true to SensorHistory.ORDER_OLDEST_FIRST and the warning will go away.

    It looks like you can also use a type cast to tell the compiler the value you are passing is of a specific type.

    var bodybatt = Toybox.SensorHistory.getBodyBatteryHistory({
        :period => 1,
        :order => 1 as SensorHistory.Order,
    });

    I don't think this is a great idea, but you can do it.