01-29-2018 13:13
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

01-29-2018 13:13
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
I have an app that the user will input text in the settings portion and the data is sent to the device via the companion. the resulting string would be like the example below.
{"data":{"key":"userName","newValue":"{\"name\":\"Joe User\"}"}}
I need to have these settings stay with the device when the phone is not around. I attempting to write these settings to a file that the app can then access for the data but I am having issues constructing what needs to happen.
I have been up and down the FS API and File System Guides trying different things and combed through the community forums with no luck.
Can someone give a better explaination on how to do this?
01-29-2018 18:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post


01-29-2018 18:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
See if this helps.
Gondwana Software

02-01-2018 08:00 - edited 02-01-2018 08:01
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-01-2018 08:00 - edited 02-01-2018 08:01
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
This gave a better insight but did not give me the answer I was looking for. It is possible my way of going about this is incorrect, so let me try to explain a bit more.
In my Settings/index.js I have 4 textInputs all identical to below.
<TextInput
label="Label 1:"
placeholder="Label 1"
settingsKey="label1"
/>
<TextInput
label="Label 2:"
placeholder="Label 2"
settingsKey="label2"
/>
<TextInput
label="Label 3:"
placeholder="Label 3"
settingsKey="label3"
/>
<TextInput
label="Label 4:"
placeholder="Label 4"
settingsKey="label4"
/>
Then in my resources/index gui I have a <text> placement for each.
<text id="label_1" x="30" y="100"
font-family="System-Bold" fill="black"
font-size="30"
text-length= "50"
text-anchor="start">-</text>
<text id="label_2" x="30" y="130"
font-family="System-Bold" fill="black"
font-size="30"
text-length= "50"
text-anchor="start">-</text>
<text id="label_3" x="30" y="160"
font-family="System-Bold" fill="black"
font-size="30"
text-length= "50"
text-anchor="start">-</text>
<text id="label_4" x="30" y="165"
font-family="System-Bold" fill="black"
font-size="30"
text-length= "50"
text-anchor="start">-</text>
In my companion/index.js I am using the standard messaging onchange events to move the data from settings to the app.
// Fires when a user changes settings
settingsStorage.onchange = evt => {
let data = {
key: evt.key,
newValue: evt.newValue
};
sendVal(data);
};
//Fires when the Message Socket Opens
// Restore any previously saved settings and send to the device
function restoreSettings() {
for (let index = 0; index < settingsStorage.length; index++) {
let key = settingsStorage.key(index);
if (key) {
let data = {
key: key,
newValue: settingsStorage.getItem(key)
};
sendVal(data);
}}}
Then finally in my app/index.js file I am recieving the data sent from settings and making it display on the gui.
messaging.peerSocket.onmessage = evt => {
if (evt.data.key === "label1" && evt.data.newValue) {
let label1 = JSON.parse(evt.data.newValue).name;
var label_1 = document.getElementById("label_1");
label_1.text = label1;
}
if (evt.data.key === "label2" && evt.data.newValue) {
let label2 = JSON.parse(evt.data.newValue).name;
var label_2 = document.getElementById("label_2");
label_2.text = label2;
}
if (evt.data.key === "label3" && evt.data.newValue) {
let label3 = JSON.parse(evt.data.newValue).name;
var label_3 = document.getElementById("label_3");
label_3.text = label3;
}
if (evt.data.key === "label4" && evt.data.newValue) {
let label4 = JSON.parse(evt.data.newValue).name;
var label_4 = document.getElementById("label_4");
label_4.text = label1;
}
};
This will send and display the data as long as the watch has connectivity to the phone. I will need to write the data that is transmitted to a file which is stored on the watch. At which point, I will change my code so that the gui pulls the text to be displayed from the file. In addition, I need to be able to write/rewrite the file on watch when new data is entered or changed by the settings.
Ideally, I would like to compile the data in a single json file.
I am using the fs.writeFileSync method, but cannot get all the data into one file. If I use a seperate file for each entry, I am unable to overwrite the file when data changes.
So my question is what is the best method to save the data locally on the watch as it is being passed from settings on the onChange event?

02-01-2018 12:14 - edited 02-01-2018 12:15
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-01-2018 12:14 - edited 02-01-2018 12:15
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
At the end of your onmessage in the device app method:
let json_data={
"label1" : label1,
"label2" : label2,
"label3" : label3,
"label4" : label4
}
fs.writeFileSync('mysettings.txt', json_data, 'cbor');
That would persist your settings into a file.
What of course you need to do then read them in on application start before you open the messaging socket to the companion.
let json_object = fs.readFileSync("mysettings.txt", "cbor");
label1=json_object.label1;
label2=json_object.label2;
label3=json_object.label3;
label4=json_object.label4;
Hope the above helps 🙂

02-02-2018 07:34
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-02-2018 07:34
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Thanks for your help Rob. This has ALMOST got me where I need to be.
I have added this to my onmessage portion:
let json_data = {
"label1" : label1,
"label2" : label2,
"label3" : label3,
"label4" : label4
}
//Put this in to verify that the file was written
fs.writeFileSync('mysettings.txt', json_data, 'cbor');
let json_read = fs.readFileSync("mysettings.txt", "cbor");
console.log(json_read);
//
And added this before my socket onopen portion:
//Load data from files to app at startup
let json_object = fs.readFileSync("mysettings.txt", "cbor");
//Verify that the file is read
console.log(json_object);
//
label1=json_object.label1;
label2=json_object.label2;
label3=json_object.label3;
label4=json_object.label4;
// Verify the the file has been read and associated with labels
console.log(label1);
console.log(label2);
console.log(label3);
console.log(label4);
//
However I am getting an "Unhandled ReferenceError: label1 is not defined" starting on the label1=json_object.label1; line.
I verified that the console.log line before it is indeed returning [object Object].

02-02-2018 07:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-02-2018 07:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
In addtion - if I do the following instead:
//Load data from files to app at startup
let json_object = fs.readFileSync("mysettings.txt", "cbor");
let label1=json_object.label1;
let label2=json_object.label2;
let label3=json_object.label3;
let label4=json_object.label4;
And then:
//Associate the labels with the index.gui
var label_1 = document.getElementById("label_1");
label_1.text = label1;
var label_2 = document.getElementById("label_2");
label_2.text = label2;
var label_3 = document.getElementById("label_3");
label_3.text = label3;
var label_4 = document.getElementById("label_4");
label_4.text = label4;
I get the data to persist on the device, however only label2 shows correctly where the others show "undefined". I am assuming because label 2 is the last bit of information sent onmessage so that is all that is written in json_data.

02-02-2018 08:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-02-2018 08:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @jomis003
You will need to make reference to your svg object before you can set it. My bad for not explaining more clearly. Am at work at the moment - I will post up a little later.

02-02-2018 12:39
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-02-2018 12:39
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @jomis003
Sorry didn't fully have my head on when first posting up:
You need to write the file after all settings have been received, the best place will be in a document.onunload function. Am just home from work - if you require it, I can post some code up tomorrow.

02-02-2018 12:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-02-2018 12:54
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi - @SunsetRunner
I will work on that to see what I can do. If its possible to post a sample, that would be great!
Thanks in advance for your help./

02-02-2018 12:56
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-02-2018 12:56
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @SunsetRunner
I will work on it to see what I can do. If you could post some sample code, that would be great!!
Thanks in advance.

02-02-2018 14:34 - edited 02-02-2018 14:36
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-02-2018 14:34 - edited 02-02-2018 14:36
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
- Who Voted for this post?
import document from "document"; import * as messaging from "messaging"; import * as fs from "fs"; import { me } from "appbit"; let label1text=document.getElementById("label1"); let label2text=document.getElementById("label2"); let label3text=document.getElementById("label3"); let label4text=document.getElementById("label4"); try { let json_data = fs.readFileSync("settings.txt", "cbor"); label1text.text=json_data.label1; label2text.text=json_data.label2; label3text.text=json_data.label3; label4text.text=json_data.label4; } catch(err) { // file does not exist
} messaging.peerSocket.onmessage = evt => { if (evt.data.newValue) { let textField=document.getElementById(evt.data.key); textField.text=JSON.parse(evt.data.newValue).name; } };
me.onunload = () => { json_data.label1=label1text.text; json_data.label2=label2text.text; json_data.label3=label3text.text; json_data.label4=label4text.text; fs.writeFileSync('settings.txt', json_data, 'cbor'); }
Went for the me.onunload instead of document.onunload as document.onunload didn't appear to function.
Hope that helps ....
02-03-2018 13:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-03-2018 13:35
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Hi @SunsetRunner
When trying to run this code I am getting "Cannot set property 'text' of null" on the line below:
if (evt.data.newValue) {
let textField=document.getElementById(evt.data.key.newValue);
textField.text=JSON.parse(evt.data.newValue).name;
}
};
My thought is that we are not writing the (evt.data.newValue).name to the settings.txt file as the data is being recieved by the app. Would we not still need to write the file within onmessage:
let json_data = {
"label1"://data for label1,
"label2"://data for label2,
"label3"://data for label3,
"label4"://data for label4
}
fs.writeFileSync('settings.txt', json_data, 'cbor');
If so, then wouldnt the data need to be identified and set as it comes in?
if (evt.data.key === "labe l" && evt.data.newValue) {
let label1 = JSON.parse(evt.data.newValue).name;
var label_1 = document.getElementById("label_1");
label_1.text = label1;
Am I thinking of this the wrong way?

02-03-2018 13:52 - edited 02-03-2018 13:52
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-03-2018 13:52 - edited 02-03-2018 13:52
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Doh!!
Change the me.onunload to
me.onunload = () => { let json_data = {}; let label1text=document.getElementById("label1"); let label2text=document.getElementById("label2"); let label3text=document.getElementById("label3"); let label4text=document.getElementById("label4"); json_data.label1=label1text.text; json_data.label2=label2text.text; json_data.label3=label3text.text; json_data.label4=label4text.text; fs.writeFileSync('settings.txt', json_data, 'cbor'); }
Been a long week this week .... apologies for messing you about. Was trying to save a few lines of code and didn't test afterwards.
The above code is tested and it does work.

02-03-2018 18:04
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-03-2018 18:04
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
@SunsetRunner
No worries! Believe me when I say I appreciate all the help!
I replaced the code and am still getting the same error in the onmessage section. It is almost as if the code is not the data or writing the settings.txt when the onmessage fires. I am going to post some screen shots. Would you be so kind to look them over and see if I am missing something simple?
app index.js

02-03-2018 23:06 - edited 02-03-2018 23:09
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-03-2018 23:06 - edited 02-03-2018 23:09
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
In your SVG your text fields are label_1, label_2, label_3, label_4
In index.js you have label1, label2, label3 and label4 in the onunload code. Change these to include the underscores and all should be good there.
Then in settings.jsx change settingsKey to match, I.e. label_3 instead of label3.

02-05-2018 11:50
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-05-2018 11:50
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
@SunsetRunner
Thanks for the extra set of eyes. I made those changes and was still getting the same "Cannot set property 'text' of null" error on that line.
I found what I needed to do was to define both the key and the value of the data coming in.
messaging.peerSocket.onmessage = evt => {
console.log(`App received: ${JSON.stringify(evt.data.key)}`);
if (evt.data.newValue) {
let textField=document.getElementById(evt.data.key);
let labelName = JSON.parse(evt.data.newValue).name;
textField.text = labelName;
}
};
This allowed the data to change when changed in the settings and persist on the watch. Thank you for all your help with that!
Now the unintended consequence is that if I clear the settings using props.settingsStorage.clear, it sends a null back to the app, but the json_data is not reset back to its default state. The mysetttings.txt info still persists afterwards.
I am researching on how to set it back to the default state as when the app was installed.

02-05-2018 11:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-05-2018 11:57
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Check to see if the data received is null (===null) then delete the file (un sync it) is the first thought.

02-05-2018 12:16
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-05-2018 12:16
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
That was my first thought. I put in the check for null. It doesn't seem to help.
if (evt.data.newValue) {
let textField = document.getElementById(evt.data.key);
let labelName = JSON.parse(evt.data.newValue).name;
textField.text = labelName;
}
if (evt.data.key === null) {
fs.unlinkSync("settings.txt");
}
};

02-05-2018 12:48
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

SunsetRunner
02-05-2018 12:48
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
Isn't JSON.parse(evt.data.newValue).name
going to contain the null value?
On a second thought, would it not be better to set each field to a default value?
Something like this maybe?
if (evt.data.newValue) { let textField = document.getElementById(evt.data.key);
if (JSON.parse(evt.data.newValue).name === null) {
let labelName = "Blank";
} else {
let labelName = JSON.parse(evt.data.newValue).name;
}
textField.text = labelName;
}

02-08-2018 09:18
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post

02-08-2018 09:18
- Mark as New
- Bookmark
- Subscribe
- Permalink
- Report this post
I am going to cirlcle back on removing values for now. What I have works great until I introduce an element like an additive list. I am working on adapting the code, but think I need a little better understanding of it.
//onmessage event
if (evt.data.newValue) {
let textField = document.getElementById(evt.data.key);
let labelName = JSON.parse(evt.data.newValue).name;
textField.text = labelName;
If I enter "first label" into the first textInput label1 essentially what this is doing(correct me if I am wrong) is making the keyname(label1) equal to the value that is inserted. ("first label")
So essentially
label1=first label
Now we write the data to the settings.txt file
me.onunload = () => {
let json_data = {};
let L1Text = document.getElementById("L1");
json_data.L1 = L1Text.text;
fs.writeFileSync('settings.txt', json_data, 'cbor');
}
When the app starts, it then reads the data and associates it to the gui
let L1Text = document.getElementById("L1");
try {
let json_data = fs.readFileSync("settings.txt", "cbor");
L1Text.text = json_data.L1;
}
Question - When we set the value "first label", how does it get associated with L1 on the gui?

