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

Need help with file transfer

ANSWERED

I am trying to transfer a file that I fetch from an Internet API to the device, so I can analyze the data.

I start with the file transfer sample project, and it all works.

When I change the data to the file, it gets stuck into queue and it seems to never write.

 

Companion code

This one works:

 

  fetch(ENDPOINT)
  .then(function (response) {
      response.json()
      .then(function(data) {
         console.log("Sending file...");        
         let data = new Uint8Array(26);
         for (let counter = 0; counter < data.length; counter++) {
data[counter] = "a".charCodeAt(0) + counter;
} console.log(data); outbox.enqueue("alphabits.txt", data).then(function (ft) { // Queued successfully console.log("Transfer of 'file' successfully queued."); }).catch(function (error) { // Failed to queue throw new Error("Failed to queue '" + destFilename + "'. Error: " + error); });

If I try to chage data to others, it does not work. I tried to leave it blank to pass data directly from the response.josn, and I tried all this. None works.

   let data = data;
   let data = JSON.stringify(data);
   let data = JSON.stringify(data).slice(2,8);

 

App code stays the same. I changed the type of file (ascii, json, ...) but it does not seem to make a difference. I always get stuck on "file queued"

import document from "document";
import { inbox } from "file-transfer";
import fs from "fs";

console.log("App App Started");

let statusText = document.getElementById("status");
statusText.innerText = "Waiting...";

inbox.onnewfile = function () { var fileName; do { // If there is a file, move it from staging into the application folder fileName = inbox.nextFile(); if (fileName) { console.log("/private/data/" + fileName + " is now available"); console.log(`Received File: <${fileName}>`); let data = fs.readFileSync(fileName); statusText.innerText = "Received: " + data; console.log("received this: " + data) } } while (fileName); };

 

 

 

Can you please point me in what I am doing wrong?

Thanks!!!

 

Best Answer
0 Votes
1 BEST ANSWER

Accepted Solutions

You were close, the JSON.stringify bit isn't needed. I missed the docs for CBOR too, found it eventually here: https://dev.fitbit.com/reference/device-api/cbor/

Your companion should have code like...

import { encode } from 'cbor';
import { outbox } from 'file-transfer';
...
const myFileInfo = encode(data);
outbox.enqueue('file.txt', myFileInfo)

My inbox logic is more or less a straight copy paste of the docs here in the app code here: https://dev.fitbit.com/guides/communications/file-transfer/#receiving-a-file

The only part it is missing, is after the file is ready, you need to read it. You should be able to do that fairly simply with the File System API:

 

import { readFileSync } from 'fs';
...all the inbox logic in the above link, after the file is ready...
const myFileInfo = readFileSync('file.txt', 'cbor');

I have had reliable success with this method, I was really struggling with the Messaging API. Once I figured this out, I was able to rip out a lot of code and simplify. Let me know if it works or if you have any more questions!

 

EDIT, didn't really answer your CBOR question. As I understand it, you should be able to CBOR encode any regular JS object. If you could call JSON.stringify on it, you should be able to call encode on it instead.

View best answer in original post

Best Answer
6 REPLIES 6

Anyone has feedback on this?

Best Answer
0 Votes

Bumping this up again hoping to get some Thanksgiving help...:)

Best Answer
0 Votes

@agsurf5 I seem to be in the a very similar boat and I'm stuck on this for now. All I can suggest in your code to try to to pass "ascii" as the second parameter in readFileSync, but it sounds like you may have tried that already.  Did you ever make any progress?

 

In my scenario, my outbox.enqueue promise resolves successfully in the companion. I can even get input.nextFile() to return with the correct filename. Unfortunately the data variable I'm setting to the return of readFileSync(fileName, 'ascii') always returns to empty quotes when I know I enqueued a populated string.

 

It is a shame because other than this I much prefer the File Transfer API to the Messaging API.

 

EDIT: I have overcome my immediate issue. I was mistaken that I could simple outbox.enqueue an object.  Once I converted it into an arrayBuffer on the companion side I am able to read the file on the app side as JSON. The trick is TextEncoder which hopefully continues to work as it isn't explicitly documented.

 

 

  const arrayBuffer = new TextEncoder().encode(JSON.stringify(data));

Hopefully you'd had similar luck with your issue @agsurf5

 

SECOND EDIT: Jon pointed out that I should probably be using CBOR.encode instead of TextEncoder, which I completely missed while scanning the documentation. Just a heads up for anyone in the same situation.

Best Answer

@kenjamin I am pretty lost now. I tried to locate info for CBOR and how to write a cbor file, and I was lost for hours. JSON I understand. CBOR seems nowhere to be found apart from the specs of it.

 

Should I just write a JSON and then write something like:

const myFileInfo = new CBOR.encode(JSON.stringify(data));

 

Best Answer
0 Votes

You were close, the JSON.stringify bit isn't needed. I missed the docs for CBOR too, found it eventually here: https://dev.fitbit.com/reference/device-api/cbor/

Your companion should have code like...

import { encode } from 'cbor';
import { outbox } from 'file-transfer';
...
const myFileInfo = encode(data);
outbox.enqueue('file.txt', myFileInfo)

My inbox logic is more or less a straight copy paste of the docs here in the app code here: https://dev.fitbit.com/guides/communications/file-transfer/#receiving-a-file

The only part it is missing, is after the file is ready, you need to read it. You should be able to do that fairly simply with the File System API:

 

import { readFileSync } from 'fs';
...all the inbox logic in the above link, after the file is ready...
const myFileInfo = readFileSync('file.txt', 'cbor');

I have had reliable success with this method, I was really struggling with the Messaging API. Once I figured this out, I was able to rip out a lot of code and simplify. Let me know if it works or if you have any more questions!

 

EDIT, didn't really answer your CBOR question. As I understand it, you should be able to CBOR encode any regular JS object. If you could call JSON.stringify on it, you should be able to call encode on it instead.

Best Answer

Thanks @kenjamin!!!

It seems to be working fine now, as I can transfer file data. Working on the next part now.

I really appreciate your help.

 

Ps on your sample code there is a typo. It should say 

const myFileInfo = fs.readFileSync('file.txt', 'cbor');

 

Best Answer
0 Votes