02-10-2018 01:02
02-10-2018 01:02
I wanted to ask how I am able to replace values in JSON files, without overriding the whole file and losing the rest of the property values. Because if I do it in the following way:
json_color.hours = element.data.value;
fs.writeFileSync("colors.txt", json_color, "json");I am always replacing the previous file and I only want to change one property value and keep the other remaining property values.
Answered! Go to the Best Answer.
02-10-2018 02:26
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
02-10-2018 02:26
I would write the file only on app unload, and also use CBOR format for speed purposes.
import { me } from "appbit";
me.onunload = () => {
fs.writeFileSync("colors.txt", json_color, "cbor");
}
02-10-2018 02:26
Fitbit Developers oversee the SDK and API forums. We're here to answer questions about Fitbit developer tools, assist with projects, and make sure your voice is heard by the development team.
02-10-2018 02:26
I would write the file only on app unload, and also use CBOR format for speed purposes.
import { me } from "appbit";
me.onunload = () => {
fs.writeFileSync("colors.txt", json_color, "cbor");
}
02-10-2018 06:07
02-10-2018 06:07
For settings, which your example appears to be, then @JonFitbit response is certainly the best solution.
If you were collecting data, for example sensor data for later use, then take a look at writeSync, which is for binary file use. It does add a level of complexity, but also opens up reading or updating particular 'records' at will. Each record will be a fixed byte length. I was 'playing about' with writeSync yesterday and have working code if this route is of interest/use (read/write/update) @Senorts.
02-10-2018 06:54
02-10-2018 06:54
Thank's very much for the help.
Best Answer02-10-2018 08:00 - edited 02-10-2018 08:03
02-10-2018 08:00 - edited 02-10-2018 08:03
As per your message @Senorts, here you are. Please remember this is test code to confirm functionality and usage of writeSync.
import * as fs from "fs";
let fh = 0;
let fileName="filename.bin";
// setup variables for updating the record
var sentBuffer = new ArrayBuffer(1);
var sentFlag = new Uint8Array ( sentBuffer, 0, 1 ); // 1 x 1 bytes
sentFlag[0] = 1;
//setup variables for the record format
let recSize = 58;
var buffer = new ArrayBuffer(recSize);
var dtMillies = new Uint32Array ( buffer, 0, 2 ); // 2 x 4 bytes
var gpsLat = new Float64Array( buffer, 8, 1 ); // 1 x 8 bytes
var gpsLon = new Float64Array( buffer, 16, 1 ); // 1 x 8 bytes
var gpsSpeed = new Float64Array( buffer, 24, 1 ); // 1 x 8 bytes
var gpsAccuracy = new Float64Array( buffer, 32, 1 ); // 1 x 8 bytes
var gpsHeading = new Uint16Array ( buffer, 40, 1 ); // 1 x 2 bytes
var heartRate = new Uint16Array ( buffer, 42, 1 ); // 1 x 2 bytes
var steps = new Uint16Array ( buffer, 44, 1 ); // 1 x 2 bytes
var altitude = new Uint16Array ( buffer, 46, 1 ); // 1 x 2 bytes
var ascent = new Uint16Array ( buffer, 48, 1 ); // 1 x 2 bytes
var descent = new Uint16Array ( buffer, 50, 1 ); // 1 x 2 bytes
var reading = new Uint32Array ( buffer, 52, 1 ); // 1 x 4 bytes
var battery = new Uint8Array ( buffer, 56, 1 ); // 1 x 1 bytes
var sent = new Uint8Array ( buffer, 57, 1 ); // 1 x 1 bytes
let myDate=Date.now()
let recCount=0;
let firstUnsent = 0;
writeRecord();
writeRecord();
showFileDetails();
firstUnsent = findFirstUnsent();
if (firstUnsent>0) {
updateRecordAsSent(firstUnsent);
}
showRecordsToConsole();
function writeRecord() {
fh = fs.openSync(fileName, 'a+');
dtMillies[0] = parseInt(myDate/100000000);
dtMillies[1] = myDate%100000000;
gpsLat[0] = 179.987654321
gpsLon[0] = -179.123456789
gpsHeading[0] = Math.floor(Math.random() * 360);
gpsSpeed[0] = 2.123456791
heartRate[0] = 120 + Math.floor(Math.random() * 80);
gpsAccuracy[0] = 21.2134254723
steps[0] = Math.floor(Math.random() * 3);
altitude[0] = 10 + Math.floor(Math.random() * 1991);
ascent[0] = 4
descent[0] = 0
battery[0] = 78
reading[0] = 1
sent[0] = 0
fs.writeSync(fh, buffer); // write the record
fs.closeSync(fh); // and commit changes -- important if you are about to read from the file
}
function showFileDetails() {
let stats = fs.statSync(fileName);
if (stats) {
recCount=stats.size/recSize;
console.log("File size: " + stats.size + " bytes");
console.log("Number of Records: " + recCount);
console.log("Last modified: " + stats.mtime);
}
}
function getNumberOfRecords() {
recCount=0;
let stats = fs.statSync(fileName);
if (stats) {
recCount=stats.size/recSize;
}
return recCount;
}
function findFirstUnsent() {
let retVal=0;
fh = fs.openSync(fileName, 'a+');
for (let i = 0; i < recCount; i++) {
fs.readSync(fh, buffer, 0, recSize, i*recSize );
if ((sent[0]==0) && (retVal===0)) {
retVal=i+1;
i=recCount;
}
}
fs.closeSync(fh);
return retVal;
}
function updateRecordAsSent(recordID) {
fh = fs.openSync(fileName, 'a+');
fs.writeSync(fh,sentBuffer,0,1,(recSize*recordID)-1);
fs.closeSync(fh);
}
function showRecordsToConsole() {
recCount=getNumberOfRecords();
fh = fs.openSync(fileName, 'r+');
for (let i = 0; i < recCount; i++) {
fs.readSync(fh, buffer, 0, recSize, i*recSize );
console.log("Record: "+(i+1)+" Millies:"+(dtMillies[0]*100000000+dtMillies[1])+" Lat:"+gpsLat[0]+" Lon:"+gpsLon[0]+" Heading:"+gpsHeading[0]+" Speed:"+gpsSpeed[0]+" HR:"+heartRate[0]+" Accuracy:"+gpsAccuracy[0]+" Steps:"+steps[0]+" Alt:"+altitude[0]+" Asc:"+ascent[0]+" Des:"+descent[0]+" Bat:"+battery[0]+" Reading:"+reading[0]+" Sent:"+sent[0]);
}
fs.closeSync(fh);
}
function packString(mystring) {
let i=0;
while (mystring.length<16) { mystring+=' '; }
for (i = 0; i < mystring.length; i++) {
usernameView[i]=mystring.charCodeAt(i);
}
}
function unPackString(usernameView) {
let retVal='';
let i=0;
for (i = 0; i < usernameView.length; i++) {
retVal+=String.fromCharCode(usernameView[i]);
}
return retVal
}
05-15-2020 22:28
05-15-2020 22:28
one really interesting thing i found in using @SunsetRunner's code it looks like the Uint*Arrays need to be in a certain order to pack them into the ArrayBuffer as tightly as possible. for example, i have two Uint*Arrays i'm passing to the buffer. if i put the Uint32Array first, i can get the record size down to 9 bytes. but if the Uint8Array is first, the record size has to be 16 bytes (almost twice as large). otherwise, i get an error. anyone know the logic behind this in the Fitbit SDK? does this have something to do with Endianness? Here's my code sample:
allows for a record size of 9 bytes:
var buffer = new ArrayBuffer(recSize);
var attention = new Uint8Array(buffer, 8, 1);
var dtMillies = new Uint32Array(buffer, 0, 2);
var buffer = new ArrayBuffer(recSize);
var attention = new Uint8Array(buffer, 0, 1);
var dtMillies = new Uint32Array(buffer, 8, 2);
Best Answer