AntPlus::BikePower - basic use problems..

Hi

I'm a complete noob to Connect IQ, any pointers would be massively appreciated!

I have been making a few simple Datafields without issue but have got stuck on accessing the data from BikePower. I'm pretty sure I must be missing something obvious but from looking through the API Documentation, Programmers Guide and this forum I have gotten any further :(

So i'm just setting up a class so I can call the functions from the main View code. Should I be creating the BikePowerListener object inside the BikePower object? Or is this just the completely wrong approach? (someone telling me I've completely missed the point would even be helpful at this point ;) )

using Toybox.WatchUi as Ui;
using Toybox.System as Sys;
using Toybox.Time as Time;
using Toybox.AntPlus as Ant;

class PowerObject {

var data;
var CalculatedCadence;
var CalculatedPower;
var CalculatedWheelDistance;
var CalculatedWheelSpeed;
var PedalPowerBalance;
var TorqueEffectivenessPedalSmoothness;
var bike_listener;
var bike_power;

function initialize() {
bike_listener = Ant.BikePowerListener;
bike_listener = new TestBikePowerListener();
bike_listener.initialize();

bike_power = Ant.BikePower;
bike_power = new TestBikePower(bike_listener);
bike_power.initialize(bike_listener);
}

function return_power() {
//data = bike_listener.onCalculatedPowerUpdate(data);
System.println("AAAA " + data);

data = bike_power.getCalculatedPower();
System.println("BBBB " + data);
return data;
}
}

class TestBikePowerListener extends Ant.BikePowerListener {
var PowerList_Var;
var Id = 1;
var data;
var return_data;

function initialize() {
BikePowerListener.initialize;
}

function onCalculatedPowerUpdate(data)
{
return_data = data;//(CalculatedPower);
System.println("CALL? ");
return return_data;
//TestBikePower.getCalculatedPower(data)
}
}

class TestBikePower extends Ant.BikePower {
var bike_listener;
var data;
var CalculatedPower;

function initialize(bike_listener) {
BikePower.initialize(bike_listener);
}

function getCalculatedPower() {
//System.println("TES TEST TEST " + bike_listener.onCalculatedPowerUpdate() );
BikePower.getCalculatedPower(CalculatedPower);
System.println("CCC " + CalculatedPower);
data = CalculatedPower;
return data;
}
}
  • Two things...

    • It appears that there are lots of things wrong with your code (assigning references to classes, then to class instances, and explicitly calling initialize on already initialized objects). I'm not going to bother fixing them unless you really need it. Let me know...
    • I've not even tinkered with the BikePower classes. I'm just going by the API documentation, so I could be wrong.


    So there are two ways to get bike power data to your application classes. You can query the bike power values (via a call to one of the BikePower.get...() functions like getCalculatedPower() on a BikePower object instance), or you can be notified when the bike power value changes (via the BikePowerListener.on...(data) callback functions like onCalculatedPowerUpdate()). You can do both as well.

    If all you want to do is to be able to query the bike power values, it seems that you could do this...

    using Toybox.AntPlus as AntPlus;
    using Toybox.Timer as Timer;
    using Toybox.System as Sys;
    using Toybox.WatchUi as Ui;

    class MyView extends Ui.View
    {
    hidden var _M_bikePower;
    hidden var _M_bikePowerListener;

    function initialize() {
    View.initialize();
    _M_bikePowerListener = new AntPlus.BikePowerListener();
    _M_bikePower = new AntPlus.BikePower(_M_bikePowerListener);
    }

    hidden var _M_timer;

    function onShow() {
    _M_timer = new Timer.Timer();
    _M_timer.start(self.method(:requestUpdate), 1000, true);
    }

    function onHide() {
    _M_timer.stop();
    _M_timer = null;
    }

    function onUpdate(dc) {
    var data = _M_bikePower.getCalculatedPower();
    Sys.println(data.power);
    }
    }


    The above code just prints null repeatedly in the simulator, and I'm too lazy to try it on a device right now, but I'm pretty sure it will work.

    If you want to be notified asynchronously of updates, you could derive your own BikePowerListener that updates the view, something like this...

    // MonkeyC doesn't support multiple inheritance. This delegate class allows any class
    // that matches the interface to BikePowerListener to behave as if it inherited from
    // BikePowerListener (If BikePowerListener is an empty class, then this
    // machinery is unnecessary).

    using Toybox.AntPlus as AntPlus;
    using Toybox.Timer as Timer;
    using Toybox.System as Sys;
    using Toybox.WatchUi as Ui;

    class MyBikePowerDelegate extends AntPlus.BikePowerListener
    {
    function initialize() {
    BikePowerListener.initialize();
    }

    hidden var _M_client;

    function setClient(client) {
    _M_client = client;
    }

    function onCalculatedCadenceUpdate(data) {

    // call through to the client class if we have a valid reference and if the
    // client supports the data that we are passing through.

    if (_M_client == null) {
    return;
    }
    if (_M_client has :onCalculatedCadenceUpdate) {
    _M_client.onCalculatedCadenceUpdate(data);
    }
    }

    function onCalculatedPowerUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onCalculatedPowerUpdate) {
    _M_client.onCalculatedPowerUpdate(data);
    }
    }

    function onCalculatedWheelDistanceUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onCalculatedWheelDistanceUpdate) {
    _M_client.onCalculatedWheelDistanceUpdate(data);
    }
    }

    function onCalculatedWheelSpeedUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onCalculatedWheelSpeedUpdate) {
    _M_client.onCalculatedWheelSpeedUpdate(data);
    }
    }

    function onPedalPowerBalanceUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onPedalPowerBalanceUpdate) {
    _M_client.onPedalPowerBalanceUpdate(data);
    }
    }

    function onTorqueEffectivenessPedalSmoothnessUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onTorqueEffectivenessPedalSmoothnessUpdate) {
    _M_client.onTorqueEffectivenessPedalSmoothnessUpdate(data);
    }
    }

    function onBatteryStatusUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onBatteryStatusUpdate) {
    _M_client.onBatteryStatusUpdate(data);
    }
    }

    function onDeviceStateUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onDeviceStateUpdate) {
    _M_client.onDeviceStateUpdate(data);
    }
    }

    function onManufacturerInfoUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onManufacturerInfoUpdate) {
    _M_client.onManufacturerInfoUpdate(data);
    }
    }

    function onProductInfoUpdate(data) {
    if (_M_client == null) {
    return;
    }
    if (_M_client has :onProductInfoUpdate) {
    _M_client.onProductInfoUpdate(data);
    }
    }
    }

    class MyView extends Ui.View
    {
    hidden var _M_bikePower;
    hidden var _M_bikePowerDelegate;

    function initialize() {
    View.initialize();
    _M_bikePowerDelegate = new MyBikePowerDelegate();
    _M_bikePower = new AntPlus.BikePower(_M_bikePowerDelegate);
    }

    function onShow() {
    _M_bikePowerDelegate.setClient(self);
    }

    function onHide() {
    _M_bikePowerDelegate.setClient(null);
    }

    // will get called if this view is being shown and power is updated
    function onCalculatedPowerUpdate(data) {
    Sys.println(data.power);

    // you could also call Ui.requestUpdate() in here to force a later call to onUpdate()
    // if you need to update the display
    }
    }
  • Thanks for your response and the examples! Cleared up a lot for me.. I think I had attempted the structure in you first example once, but kept on getting null returned, it all spiralled into a bit of a mess after that..

    So a big question that's come out of this for me - In the device simulator info.averagePower data is produced when '/Simulation/FIT data/Simulate Data' is activated from the menu but not AntPlus data? I had assumed both would be produced..? (first mistake! ;) )

    Using your first example I've made another Datafield that shows both info.averagePower & _M_bikePower.getCalculatedPower. In the device simulator I get a result for info.averagePower but nothing for _M_bikePower.getCalculatedPower (I also tried one of my own FIT files with power data with the same result). When I build the programme and test it on my Edge 520 on my bike with Vector pedals i again get a result for info.averagePower but now for _M_bikePower.getCalculatedPower i get a result of "Obj: 27" (the full value printed to screen is BIKEPOWER = Obj:27" due to the line 'data_new = "BIKEPOWER = " + _M_bikePower.getCalculatedPower();' )

    Maybe I've broken something when converting your example to a datafield?? Below is the code used:

    using Toybox.WatchUi as Ui;
    using Toybox.System as Sys;

    class fffView extends Ui.SimpleDataField {

    var data_new;
    var counter = 0;
    hidden var _M_bikePower;
    hidden var _M_bikePowerListener;

    // Set the label of the data field here.
    function initialize() {

    SimpleDataField.initialize();
    label = "BIKEPOWER TEST";
    _M_bikePowerListener = new AntPlus.BikePowerListener();
    _M_bikePower = new AntPlus.BikePower(_M_bikePowerListener);
    }

    function compute(info) {

    if (counter == 1)
    {
    Sys.println("in 1");
    if (_M_bikePower.getCalculatedPower() != null)
    {
    data_new = "BIKEPOWER = " + _M_bikePower.getCalculatedPower();
    }
    }

    if (counter == 2)
    {
    Sys.println("in 2");
    if (info.averagePower != null)
    {
    data_new = "AVERAGE POWER = " + info.averagePower;
    }
    }
    counter++;
    if(counter > 2)
    {
    counter = 0;
    return "START";
    }
    return data_new;
    }
    }


    Thanks again for your help!!
  • Thanks for your response and the examples! Cleared up a lot for me.. I think I had attempted the structure in you first example once, but kept on getting null returned, it all spiralled into a bit of a mess after that..

    So a big question that's come out of this for me - In the device simulator info.averagePower data is produced when '/Simulation/FIT data/Simulate Data' is activated from the menu but not AntPlus data? I had assumed both would be produced..? (first mistake! ;) )

    Using your first example I've made another Datafield that shows both info.averagePower & _M_bikePower.getCalculatedPower. In the device simulator I get a result for info.averagePower but nothing for _M_bikePower.getCalculatedPower (I also tried one of my own FIT files with power data with the same result). When I build the programme and test it on my Edge 520 on my bike with Vector pedals i again get a result for info.averagePower but now for _M_bikePower.getCalculatedPower i get a result of "Obj: 27" (the full value printed to screen is BIKEPOWER = Obj:27" due to the line 'data_new = "BIKEPOWER = " + _M_bikePower.getCalculatedPower();' )

    Maybe I've broken something when converting your example to a datafield?? Below is the code used:

    using Toybox.WatchUi as Ui;
    using Toybox.System as Sys;

    class fffView extends Ui.SimpleDataField {

    var data_new;
    var counter = 0;
    hidden var _M_bikePower;
    hidden var _M_bikePowerListener;

    // Set the label of the data field here.
    function initialize() {

    SimpleDataField.initialize();
    label = "BIKEPOWER TEST";
    _M_bikePowerListener = new AntPlus.BikePowerListener();
    _M_bikePower = new AntPlus.BikePower(_M_bikePowerListener);
    }

    function compute(info) {

    if (counter == 1)
    {
    Sys.println("in 1");
    if (_M_bikePower.getCalculatedPower() != null)
    {
    data_new = "BIKEPOWER = " + _M_bikePower.getCalculatedPower();
    }
    }

    if (counter == 2)
    {
    Sys.println("in 2");
    if (info.averagePower != null)
    {
    data_new = "AVERAGE POWER = " + info.averagePower;
    }
    }
    counter++;
    if(counter > 2)
    {
    counter = 0;
    return "START";
    }
    return data_new;
    }
    }


    Thanks again for your help!!
  • the full value printed to screen is BIKEPOWER = Obj:27" due to the line 'data_new = "BIKEPOWER = " + _M_bikePower.getCalculatedPower();'


    The thing returned by getCalculatedPower() is a AntPlus.CalculatedPower object instance. If you want to see the power value, you've got to look at the power member (as I did in my code above)..

    var data = _M_bikePower.getCalculatedPower();
    Sys.println(data.power);


    Travis
  • Ahh, should have seen that, sorry. I've got this working now, thanks so much!