Cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Not able to Do a file transfer every 30 seconds

ANSWERED

Hello Community, 

 

We are developing a SDK app to work with our virtual fitness application (both Android and iOS). 

I am trying to do a file transfer (json file) every 30 seconds to send the Heart Rate and Calorie details to the app to show on the app UI. 

The issue I am facing here is, the file transfer works fine until the point the display is active. As soon as the display goes off the file transfer stops. 

Is there a way to make the file transfer more consistent?  

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

I think setInterval() might be your best bet, but there may not be a lot of point doing it every second. I think heart rate values are normally only updated every 5 seconds, and calorie values every minute. That said, I've never tried the Exercise API; if you're using that, you may indeed get HR changes every second.

Peter McLennan
Gondwana Software

View best answer in original post

Best Answer
0 Votes
15 REPLIES 15

Are you relying on ontick()?

Peter McLennan
Gondwana Software
Best Answer
0 Votes

No, I am basically calling the function to do the file transfer in onRender. 

 

something like this. 

onRender() {
    if (exercise && exercise.stats) {
      console.log("onRender");
      msg.addScoreData({
        currHR : exercise.stats.heartRate.current || 0,
        score : 0,
        calories : exercise.stats.calories || 0
      });
      
    }

and in Messaging something like this

 

export function addScoreData(data) {
  if (MinTimer == 0) {
      // pushing the heart rate to an array. 
      // Doing some calculations needed to to compute the score. 
      var scoreData = {
                       score : currScore, 
                       currHR : data.currHR, 
                       cal : data.calories,
                       hRate : [tempHR],
                       timeStamp : Date.now()
                      }
      addMinScoreData(scoreData);
      minTimer = 60;
    } else {
      if (minTimer == 30) {
         var scoreData = { currHR : data.currHR, cal : data.calories, hRate : [heartRate], score : score , timeStamp : Date.now()};  
         console.log("Score 30 seconds", scoreData);
         addMinScoreData(scoreData);
      }
      minTimer = minTimer - 1;
      // push the heart rate to an array. 
    }
  }
}


export function add5minScoreData(data) {
  var newData = encode(data);
  outbox.enqueue("scoredata.json", newData)
   .then(ft => {
    console.log(`Transfer of ${ft.name} successfully queued.`);
  })
  .catch(err => {
    console.log(`Failed to schedule transfer: ${err}`);
  })
}

 

Best Answer
0 Votes

I'm new around here, but I'd venture to bet that when the screen is off it's not rendering.

Best Answer
0 Votes

So what is the correct method that I should be using instead of onRender? 

Best Answer
0 Votes

I think you'd probably want to use ontick:

//at top of file
import clock from "clock";

clock.granularity = "minutes";

clock.ontick = evt => {
  //code to run once per minute
}

 

I'm not sure if passing evt is required for your purposes, but it holds information about the current date/time

Best Answer
0 Votes

Ok. 

Can I use it for every 30 seconds? 

Best Answer
0 Votes

I don't know what onRender() is. I don't think ontick() will solve your problem either, because it doesn't fire when the display is off. I think you'll need setInterval().

Peter McLennan
Gondwana Software
Best Answer
0 Votes

@Gondwana I have to gather the Heart Rate and calorie every second and then after 30 seconds I have to make the file transfer. 
Do you think I can make this happen using setInterval() ? 

FYI, onRender() is from a method in the Lib which is from the demo project for Exercise SDK app from Fitbit. 

Best Answer
0 Votes

I think setInterval() might be your best bet, but there may not be a lot of point doing it every second. I think heart rate values are normally only updated every 5 seconds, and calorie values every minute. That said, I've never tried the Exercise API; if you're using that, you may indeed get HR changes every second.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

Adapted from the heart rate documentation (per my other post there are actually some issues with the example there):

if (HeartRateSensor && appbit.permissions.granted("access_heart_rate")) {
  //1 reading per second, 30 readings per batch for one batch every 30 sec
  let hrm = new HeartRateSensor({ frequency: 1, batch: 30 });
  hrm.addEventListener("reading", () => {
    for (let index = 0; index < hrm.readings.timestamp.length; index++) {
      console.log(
        `HeartRateSensor Reading: \
          timestamp=${hrm.readings.timestamp[index]}, \
          [${hrm.readings.heartRate[index]}]`
      );
    };
  });
  hrm.start();
} else {
   console.log("This device does NOT have a HeartRateSensor or permission not granted");
}

This will create an event listener for when a "reading" is complete, in this case we are actually setting it up to return a batch of readings so it will fire the event after 30 seconds and return an array containing 30 timestamp/heartrate combinations. I've tested and this continues to run when the display is off.

 

Cheers

Best Answer
0 Votes

I am new around here. So it would be great if you can help.

@Gondwana I am trying your approach at this moment. 
Adding setInterval() this is how my code looks. 

import document from "document";
import exercise from "exercise";
import { HeartRateSensor } from "heart-rate";
import { Application, View, $at } from "../lib/view";
import * as msg from "../lib/messaging";
import { me } from "appbit";

const $ = $at("#view-exercise");

export class ViewExercise extends View {
  el = $();

  handlePopupNo = () => {
  };

  handlePopupYes = () => {
  };

  handleToggle = () => {
  };

  handlePause = () => {
  };

  handleResume = () => {
  };

  handleFinish = () => {
  };

  handleCancel = () => {
  }

  handleRefresh = () => {
    this.render();
  }

  handleButton = (evt) => {
  }
  
  addData() {
    setInterval( () => {
      console.log("AddData", this.excercise.stats);
      if (this.exercise && this.exercise.stats) {
        console.log("AddData in the loop");
        this.msg.addScoreData({
        currHR : exercise.stats.heartRate.current || 0,
        score : 0,
        calories : exercise.stats.calories || 0
      });
      }  
    }, 1000 * 10)
  }

  onMount() {
    utils.hide(this.btnFinish);
    // utils.hide(this.btnToggle);
    utils.hide(this.btnResume);

    this.btnToggle.addEventListener("click", this.handleToggle);
    this.btnResume.addEventListener("click", this.handleResume);
    this.btnFinish.addEventListener("click", this.handleFinish);
    document.addEventListener("keypress", this.handleButton);
    
    utils.show(this.btnToggle);
    exercise.start(config.exerciseName, config.exerciseOptions);
    this.addData();
  }

  onRender() {
    if (exercise && exercise.stats) {

    }
  }

  onUnmount() { 
    this.cycle.removeEvents();

    this.btnToggle.removeEventListener("click", this.handleToggle);
    this.btnFinish.removeEventListener("click", this.handleFinish);
    this.btnResume.removeEventListener("click", this.handleResume);
    document.removeEventListener("keypress", this.handleButton);
  }
}

 

I am unable to access exercise in setInterval() which is in addData(). Can you suggest what am I missing here? 
I get this,
Unhandled exception: TypeError: Cannot read property 'stats' of undefined

 

Best Answer
0 Votes
excercise

😁

Peter McLennan
Gondwana Software
Best Answer
0 Votes

@Gondwana I mistyped in here 😄 
There are no typos in the code that I have. 

Best Answer
0 Votes

**ahem**! 😉

Next guess: sometimes you have this.exercise and sometimes just exercise. One or the other is perhaps wrong.

Peter McLennan
Gondwana Software
Best Answer
0 Votes

It's just exercise. It worked 🙂 
Thanks @Gondwana 

I ll also try your suggestion @kozm0naut 🙂 

Best Answer