Basic BodyBattery code example

I'm trying to make a widget or an app that will query BodyBattery. I have this piece of code that compiles, but never enters the `if (ActivityMonitor has :getBodyBatteryHistory)` even though I'm trying it in the simulator on Venu 2 System 5 preview, with targetApiLevel: 4.1.x and minApiLevel: 4.1.0.beta1.

I'm not sure what permissions are needed (Garmin, it would be nice to be able to know it from the documentation...), so I have these in the manifest:

<iq:permissions>
<iq:uses-permission id="Background"/>
<iq:uses-permission id="PersistedContent"/>
<iq:uses-permission id="Sensor"/>
<iq:uses-permission id="SensorHistory"/>
</iq:permissions>

I have this in my view:

    function onUpdate(dc as Dc) as Void {
    	if (ActivityMonitor has :getBodyBatteryHistory) { // this is always false
    		var bbIter = ActivityMonitor.getBodyBatteryHistory();
    		if (bbIter != null) {
    			var bbData = bbIter.next();
    			if (bbData != null) {
    				System.println("BB: " + bbData);
    			}
    		}
    	}
        // Call the parent onUpdate function to redraw the layout
        View.onUpdate(dc);
    }

(Garmin!!!!!!!!!!!!! Why there isn't Monkey C in the code languages????? Why My formatted code is displayed like this in the editor?????)


Any idea what am I doing wrong?

  • Since the release of the 4.1.0 SDK beta, we moved the new body battery & stress history APIs from the ActivityMonitor class to the SensorHistory class to better align the feature with other, similar APIs. This change was influenced by feedback we received from developers using the beta SDK. The new API is as follows:

    getBodyBatteryHistory(options as { :period as Lang.Number or Time.Duration or Null, :order as SensorHistory.Order } or Null) as SensorHistory.SensorHistoryIterator

    Get the body battery history for the given period. This function always returns the most recent sensor history samples. The time between each `SensorSample` in the iterator may be device dependent.

    Parameters:

        options — (Lang.Dictionary) — Dictionary of options. Can be null.
            :period — (Lang.Number, Time.Duration) — The period of time from which to retrieve the samples:
                If null, the entire available history is retrieved
                If a Duration, then the history for the given Duration is retrieved
                If a Number, then the last specified Number of entries are retrieved
            :order — (Lang.Boolean) — The order in which to retrieve the samples:
                If null, the samples will be ORDER_NEWEST_FIRST
                Use the ORDER_* enumeration to explicitly select ORDER_NEWEST_FIRST or ORDER_OLDEST_FIRST

    Example:

    Shows the use of BodyBatteryIterator

    using Toybox.SensorHistory;
    using Toybox.System;
    
      // Create a method to get the SensorHistoryIterator object
      function getIterator() {
          // Check device for SensorHistory compatibility
          if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) {
              // Set up the method with parameters
              return Toybox.SensorHistory.getBodyBatteryHistory({});
          }
          return null;
      }
      // get the body battery iterator object
      var bbIterator = getIterator();
      var sample = bbIterator.next();                         // get the body battery data
    
      while (sample != null) {
          System.println("Sample: " + sample.data);           // print the current sample
          sample = bbIterator.next();
      }


    Returns:

    SensorHistory.SensorHistoryIterator — An iterator for the body battery history for the given period. Samples returned by this iterator are ranges from 0-100. A 0 indicates that the body is drained and a 100 indicates the body is rested and charged.

    What this means in the short term is that the body battery APIs as available in the 4.1.0 beta must use the above syntax on System 5 products, such as the Venu 2, since the devices have already integrated the changes that moved body battery history to be part of SensorHistory. We will address this discrepancy in an upcoming SDK release.

  • Thanks @Brandon.ConnectIQ.
    What about Forerunner245 that has updated to FW 9.0 and thus has CIQ 3.3.1? Does all the above also apply to it?

  • Yes, I built a sideload using the beta1 sdk and it's running on a 245 device with 9.0.  I was using ActivityMonitor, but switched to SensorHistory, and seeing both body battery as well as stress (stress is also now in SensorHistory).

    You won't be able to run and test in the sim.

  • Oh, finally it works.
    But it's a nightmare, because I'm relatively new in CIQ so I make many mistakes, and I can't debug in the sim, so I have to connect the watch, sideload the app, then disconnect, start it and then reconnect, download the logs and try to find out what caused it to crash... I hope both the updated docs and even more the working sim will be released soon!

  • With the sim, Brandon gave a a "sneak peek" at something that's changed since the beta SDK.  At some point there will be another beta or a production 4.1 SDK.  Since you are also new to CIQ, you may want to hold off on some things until there's an update to a 4.1 (System 5) SDK.

  • Our beta SDKs are true betas, so any new features are subject to change. It's not very often that we completely move a new API like this, but it's worth keeping in mind that it can happen. We'll usually make tweaks to the new APIs between the beta and the production release (along with fixing bugs), and we'll sometimes either pull a feature that isn't ready or include new things that weren't ready for the beta release.

    I think it's generally safe to use the beta to start implementing new features into one of your apps as long as you're willing to make adjustments if things change like they have with stress history and body battery. I know it's pretty enticing to try out sweet, new features, especially if it's something you've been waiting for! Slight smile

  • All that's understandable about beta.

    What I am missing is the communication / documentation after the things were changed and were RELEASED to production.

  • Yep - this is actually a little bit of a unique situation where we have product on a newer VM than what the production SDK supports. I think that's the main source of your confusion. We usually try to coordinate these releases, but since one of the goals of Connect IQ is backward compatibility, it's perfectly okay for a device to be ahead of the SDK.

    I think we should have messaged the change to everyone when Venu 2 was released so developers would be aware these SDKs wouldn't work as expected with the beta.

  • There is and error when I try new code for BB from sensor (SDK 4.1.0 Beta1 - Venu 2 System 5 Preview, sim).

    Error: System Error
    Details: Failed invoking <symbol>
    Stack:

    BTW, When can we expect a new SDK?

  • Hi, Brandon, I am using SDK 4.1.4 to get BB with this function 

    function getBodyBattery() {
        var bodybatt = null;
        if (
          Toybox has :SensorHistory &&
          Toybox.SensorHistory has :getBodyBatteryHistory
        ) {
          bodybatt = Toybox.SensorHistory.getBodyBatteryHistory({ :period => 1 });
        } else {
          return "N";
        }
        if (bodybatt != null) {
          bodybatt = bodybatt.next();
        }
        if (bodybatt != null) {
          bodybatt = bodybatt.data;
        }
    
        if (bodybatt != null && bodybatt >= 0 && bodybatt <= 100) {
          return bodybatt.format("%d");
        } else {
          return "-";
        }
      }
    But my user told me sometimes it works sometimes not, any suggestions?