I cant use JSON on the usualy way. I have a problem with the following code:
if (inJSON != "") {
var each;
for (each in inJSON)
{
this.log(each);
if (each == 'sensors') {
// this.log(inJSON[each]);
this.log(inJSON['sensors']); // this line is working
}
}
this.log(inJSON['sensors']); // this line throws error: TypeError: Cannot read property 'sensors' of undefined
}
there is two same line, but only the first is workingā¦
Any idea?
Does it matter? In that point (where it throws the error), if I just print the JSON out to the console, there is no problem.
This is just a simplified example code to find, and show the problemā¦
No, it doesnāt. I rewrote your simplified example to test it:
const inJSON = { foo: 'bar', sensors : 'xxx' };
this.log = console.log;
if (inJSON != "") {
var each;
for (each in inJSON)
{
this.log(each);
if (each == 'sensors') {
// this.log(inJSON[each]);
this.log(inJSON['sensors']); // this line is working
}
}
this.log(inJSON['sensors']); // this line throws error: TypeError: Cannot read property 'sensors' of undefined
}
This works just fine. Like I said, your issue is not with this code but with the context in which it is used.
ok. here is my full app.js.
It connects to myIO server, and ask a JSON (inJSON) (first, with descriprions, after that a faster same JSON, without descriptions) in the setInterval(). This is a string, parsing to JSON ), and refreshing the server_data variable (it is a JSON).
My problem is, I canāt reach this JSON from the driver.js and from the device.js⦠(I tried it many ways)
So if the server_data is refreshed⦠it is set to the settings⦠(homey.settings.set(āserver_dataā, server_data)
And I can red that from other .js files⦠so it is working now⦠but a example at the end is throwing the errorā¦
'use strict';
const Homey = require('homey');
const { createSecureContext } = require('tls');
var XMLHttpRequest = require('xhr2');
var server_data;
class myIO_App extends Homey.App {
/**
* onInit is called when the app is initialized.
*/
async onInit() {
var inJSON;
var _responseTXT;
var string2send;
var updated_settings;
// get settings variables
var defaultSettings = this.homey.settings.get('defaultSettings');
var address = this.homey.settings.get('address');
var http_port = this.homey.settings.get('http_port');
var app_port = this.homey.settings.get('app_port');
var username = this.homey.settings.get('username');
var password = this.homey.settings.get('password');
// if it is the first time to start app, fill the settings with default variables
if (defaultSettings == null) {
this.homey.settings.set('address', '192.168.1.170');
this.homey.settings.set('http_port', '80');
this.homey.settings.set('app_port', '843');
this.homey.settings.set('username', 'admin');
this.homey.settings.set('password', 'admin');
this.homey.settings.set('defaultSettings', 'set');
}
this.homey.settings.set('updated_settings', 'true'); // set this from the index.htm to true
this.homey.settings.set('server_data', "");
// refreshing the server_data JSON
setInterval(() => {
updated_settings = this.homey.settings.get('updated_settings');
if (updated_settings == 'true') { //if index.html changed the settings or first turn
this.homey.settings.set('server_data', "");
address = this.homey.settings.get('address');
http_port = this.homey.settings.get('http_port');
app_port = this.homey.settings.get('app_port');
username = this.homey.settings.get('username');
password = this.homey.settings.get('password');
//log settings variables
this.log(address+" "+http_port+" "+app_port+" "+username+" "+password);
string2send = "/d_sens_out.json";
this.log("Settings_updated");
this.homey.settings.set('updated_settings', 'false');
} else {
string2send = "/sens_out.json";
}
//this.log('Try to connect to myIO server');
var request = new XMLHttpRequest();
request.open('POST', "http://" + address + ":" + http_port + string2send, true);
var enc = Buffer.from(username + ":" + password).toString('base64');
request.setRequestHeader("Authorization", "Basic " + enc);
var _tempThis = this; // because I will need it in the next function.
request.onload = function () {
_responseTXT = this.responseText;
try {
inJSON = JSON.parse(_responseTXT);
if (string2send == "/d_sens_out.json"|| server_data==null || server_data=="") {
server_data = JSON.parse(JSON.stringify(inJSON));
} else if (server_data!=null && server_data!=""){
var key, number, element;
for (key in inJSON) {
if (key == 'relays') {
for (number = 0; number < Object.keys(inJSON[key]).length; number++ ) {
for (element in inJSON[key][number]) {
server_data[key][number][element] = inJSON[key][number][element];
}
}
}
}
}
console.log("succesfull server_data update: " + server_data['relays'][0]['state']);
_tempThis.homey.settings.set('server_data', server_data);
}
catch (e) {
console.log("JSON parse error: "+e);
}
};
// this is just a simple example to show the anomaly
if (inJSON != "") {
var each;
for (each in inJSON)
{
this.log(each);
if (each == 'sensors') {
this.log(inJSON[each]);
this.log(inJSON['sensors']); // this line is working
}
}
this.log(inJSON['sensors']); // this line throws error: TypeError: Cannot read property 'sensors' of undefined
}
try {
request.send();
console.log("request ok.");
} catch (e) {
console.log("request error: " + e);
}
}, 5000);
this.log('MyApp has been initialized');
}
}
module.exports = myIO_App;
The location of your example code is outside the (asynchronous) onload handler. Only inside the onload handler can you be sure that inJSON is initialized.
To make your life easier, I would suggest dropping XMLHttpRequest (which is a browser API anyway) and use a Promise-based module for HTTP requests, like http.min: