How to parse JSON value from MQTT client to plotly javascript - javascript

Hi I have this json type data how can I access P , T , F , W and M data using javascript?
{"PHILMG":[{"P":"10"}, {"T":"5"}, {"F":"0"}, {"W":"0"}, {"M":"0"}]}
so far I tried.
function onMessageArrived(message) {
ss = message.payloadString;
console.log(ss);
// var p = ss.PHILMG.P;
// var time = ss.PHILMG.T;
// var f = ss.PHILMG.F;
// var w = ss.PHILMG.W;
// var m = ss.PHILMG.M;
// var timecollect = [];
// var windcollect = [];
// timecollect.push(time);
// windcollect.push(wind);
// console.log(windcollect);
// var data =
// {
// type:'scatter',
// x: time,
// y: w
// };
// Plotly.newPlot(document.getElementById('PhilMg'), data);
}
But Im getting an error
Object {errorCode: 5, errorMessage: "AMQJS0005E Internal error. Error Message: Cannot r…ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js:19:132)"}

Parse your JSON string with JSON.parse, then loop over the array and push the keys and values to the data which is visualized with Plotly.
var message = '{"PHILMG":[{"P":"10"}, {"T":"5"}, {"F":"0"}, {"W":"0"}, {"M":"0"}]}';
var msg = JSON.parse(message);
var x = [];
var y = [];
var i = 0;
var j;
var k;
for (k in msg) {
for (i = 0; i < msg[k].length; i += 1) {
for (j in msg[k][i]) {
x.push(j);
y.push(msg[k][i][j]);
}
}
}
var data = [{
x: x,
y: y,
type: 'bar'
}];
Plotly.newPlot('myDiv', data);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id='myDiv'></div>

You should use the correct index of the array you have in your object to reach the respective inner object at each assignment.
// var p = ss.PHILMG[0].P;
// var time = ss.PHILMG[1].T;
// var f = ss.PHILMG[2].F;
// var w = ss.PHILMG[3].W;
// var m = ss.PHILMG[4].M;

You can see the log in developer tools,
If you see this,
Object {PHILMG: Array[5]}
You should use the index of the array to get the object, then use key to get the value.
If you see this,
"{"PHILMG":[{"P":"10"}, {"T":"5"}, {"F":"0"}, {"W":"0"}, {"M":"0"}]}"
You should use ss = JSON.parse(ss), and same as above.

Related

construct array back together

My script reads EventSource, and on a message it will get some line data from a variable. That variable will be a array, my script breaks the array down and for each point it flips the x with the y value. It then sends each point as a post request. Is there anyway I can reconstruct the array back together, and then send the post request after flipping each x and y value?
here's my script:
var evtSource = new EventSource("http://URL.com/");
evtSource.onmessage = function(e) {
var obj = JSON.parse(e.data);
var line = JSON.stringify(obj.line)
var line22 = obj.line
//console.log(line22)
line22.forEach(function(point, index){
console.log(JSON.stringify(point)); // console log example// -> "[120,250]"
const [x, y] = point;
console.log(`x: ${x}, y: ${y}`);
var FlipXYvalues = "[[" + y + "," + x + "]]"; // Complies it again... flips the values..
var ident = "String"
if (obj.ident === ident) //the string...
{
$.post("http://URL.com/", {
l: (FlipXYvalues),
w : (obj.lineWidth),
c: (obj.lineColor.replace("#", "")),
o: ("100"),
f: ("1"),
_: ("false")
})
}
});
}
You can use Array#map() to create a new array based on some other array
line22 = [[1,2],[3,4],[5,6],[7,8]];
var newLines = line22.map(point => {
return [point[1], point[0]];
});
//using array destructuring
//if you dont want to mess with specifying indexes
var newLines = line22.map(([x,y]) => {
return [y,x];
});
console.log(JSON.stringify(newLines));
//$.post("http://URL.com/", {l:newLines});

Optimize javascript loop on CSV data

I am plotting a graph using d3.js by loading an external .CSV file.
The code i have so far works fine with a small amount of data but when i load a larger file with thousands of lines then it kills the page.
The data has a usage column which is a value for every 30 mins throughout the day, which will go on over several months.
See Plunker example.
var avgClientArr = [];
var dateArr = [];
var dateGroupArr = [];
function csvParseClient() {
d3.xhr('client.csv').get(function(err, response) {
var dirtyCSV = response.responseText;
var initialClientKeys = /TYPE,DATE,START TIME,END TIME,USAGE,UNITS,NOTES/i;
var newClientKeys = "TYPE,x,startTime,endTime,y,UNITS,NOTES";
var csvDataClient = dirtyCSV.replace(initialClientKeys, newClientKeys);
var validData = csvDataClient.substr(csvDataClient.indexOf(newClientKeys));
var csvData = d3.csv.parse(validData);
csvData.customForEach(function(val, i) {
// filter data
//var keep = ['x', 'startTime', 'endTime', 'UNITS', 'y'];
//for (var key in val[i]) {
// if (keep.indexOf(key) === -1) {
// delete val[i][key];
// }
//}
// parse data
var date = val.x;
var usage = val.y;
var startTime = val.startTime;
var endTime = val.endTime;
var x = new Date(date);
var y = parseFloat(usage);
dateArr.push({
"date": x,
"usage": y
})
dateGroupArr = groupBy(dateArr, 'date');
})
console.log(dateGroupArr);
var objDates = objectValues(dateGroupArr);
objDates.customForEach(function(f) {
var avg = f.reduce(function(a, b) {
return a + b.usage;
}, 0) / f.length;
var date = f.reduce(function(a, b) {
return new Date(b.date);
}, 0);
avgClientArr.push({
"x": date,
"y": avg
})
})
//console.log("avgClientArr", avgClientArr);
document.getElementById('arrayDiv').innerHTML = '<pre>' + JSON.stringify(avgClientArr, null, 4) + '</pre>';
})
}
function groupBy(arr, key) {
var reducer = (grouped, item) => {
var group_value = item[key]
if (!grouped[group_value]) {
grouped[group_value] = []
}
grouped[group_value].push(item)
return grouped
}
return arr.reduce(reducer, {})
}
function objectValues(object) {
var values = []
for (var property in object) {
if (object.hasOwnProperty(property)) {
values.push(object[property])
}
}
return values
}
function foreach(fn) {
var arr = this;
var len = arr.length;
for (var i = 0; i < len; ++i) {
fn(arr[i], i);
}
}
Object.defineProperty(Array.prototype, 'customForEach', {
enumerable: false,
value: foreach
});
var t0 = performance.now();
csvParseClient();
var t1 = performance.now();
console.log("Call csvParseClient() " + (t1 - t0) + " milliseconds.");
What i need to happen
I need the average value of usage for the whole day returned as y and the date for that day returned as x for each day.
The slow process i have
Start the loop from a specified line in the CSV file as there is unwanted data on the first few lines.
Group unique date and store each usage value for that date in an object.
Average the usage values for each date.
Output an array of objects with property x being the date and y being the average usage value.
If you can give me any help on how to make this run faster that would be great!
I solved this by using the d3 nest() and rollup() functions, its simple and really fast.
d3.nest()
.key(function(d) {
return d.x;
})
.rollup(function(d) {
var avg = d3.mean(d, function(g) {return g.y; });
return avg;
}).entries(dateArr);

Iterating over an object in a Google Apps script and printing to Google Sheets

I'm having trouble printing more than one row to my google sheet with this loop.
The first row appends fine, but I want the function to append all objects from the data var.
The data object is properly pulling from Firebase when I verify with a Logger.
var firebaseUrl = "https://test.firebaseio.com/alerts";
var secret = "sssssssssssssssssssss";
var base = FirebaseApp.getDatabaseByUrl(firebaseUrl, secret);
var data = base.getData();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("feed");
var selection = sheet.getActiveRange();
var range = sheet.getActiveRange();
var values = range.getValues();
var columns = selection.getNumColumns();
var rows = selection.getNumRows();
var num = 2;
function writeToSheets() {
for(var i in data) {
var values = [
[ data[i].id, data[i].two, data[i].three, data[i].four ]
];
var keys = Object.keys(values[0]);
var sheetRow = [];
var entryKeys;
for (j in keys) {
sheetRow = [];
entryKeys = Object.keys(values[keys[j]])
for (k in entryKeys) {
sheetRow.push(values[keys[j]][entryKeys[k]]);
}
sheet.appendRow(sheetRow);
}
}
}
I've just tried this code (assuming that I guessed the data structure correctly):
function myFunction() {
var data = [
{'id': 1, 'two': 'test2', 'three': 'test3', 'four': 'test4'},
{'id': 2, 'two': 'test2-2', 'three': 'test3-2', 'four': 'test4-2'}
]
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("feed");
var selection = sheet.getActiveRange();
var range = sheet.getActiveRange();
var values = range.getValues();
var columns = selection.getNumColumns();
var rows = selection.getNumRows();
var num = 2;
function writeToSheets() {
for(var i in data) {
var values = [
[ data[i].id, data[i].two, data[i].three, data[i].four ]
];
var keys = Object.keys(values[0]);
var sheetRow = [];
var entryKeys;
for (j in keys) {
sheetRow = [];
entryKeys = Object.keys(values[keys[j]])
for (k in entryKeys) {
sheetRow.push(values[keys[j]][entryKeys[k]]);
}
sheet.appendRow(sheetRow);
}
}
}
writeToSheets();
}
When I run it, it fails after printing the first line with an error TypeError: Expected argument of type object, but instead had type undefined. (line 26, file "Code").
And it is easy to see what exactly happens if you run it in debug mode:
You have values array with one element (line 18)
The var keys = Object.keys(values[0]); becomes [0,1,2,3] (we have 4 values inside the first element of values array)
Then, having j from 0 to 3 we get entryKeys = Object.keys(values[keys[j])
When j = 0, values[keys[j]] = values[0] - we get the first element from values
When j = 1, values[keys[j]] = values[1] - here we fail, because there is only 1 element in values
I am not really sure what you are trying to do here with all these keys, but if you just want to print the data, it can be done simpler:
function writeToSheets() {
for(var i in data) {
var item = data[i];
sheetRow = [];
for (key in item) {
sheetRow.push(item[key]);
}
sheet.appendRow(sheetRow);
}
}

How to dictionary in this case with GAS?

I'm a newbie and non-native...
function fetch_json() {
var result = UrlFetchApp.fetch("https://api.ookami.me/v1/news/public?sport_id=1");
var obj = JSON.parse(result.getContentText());
var ss = SpreadsheetApp.openById("1ecv2r3qBEuHWyP4XH7FkGktQ7YHqegd7CztRoARzKac");
var sheet = ss.getSheetByName("soccer");
for (var n=0; n < 10; n++) {
var news = json["news"][n];
var a = news["id"];
var b = news["title"];
var c = news["summary"];
var d = news["media_name"];
var e = news["url"];
var f = news["image"];
var array = [a, b, c, d, e, f];
var columnA = sheet.getRange(2, 1);
var valuesA = columnA.getValues();
var maxid = valuesA[0][0];
if (a > maxid) {
sheet.appendRow(array);
}else{
break
}
sheet.setColumnWidth(6, 120);
var last_row = sheet.getLastRow();
if (f != null) {
var cell = sheet.getRange(last_row, 6);
var image_cell = "=IMAGE(\"" + f + "\", 1)";
cell.setValue(image_cell);
sheet.setRowHeight(last_row, 72);
}else{
sheet.setRowHeight(last_row, 72);
}
}
sheet.autoResizeColumn(1);
sheet.sort(1, false);
}
This is a complete code. I want to run same function simply to other sheets by using other url.
var result= UrlFetchApp.fetch("https://api.ookami.me/v1/news/public?sport_id=1");
"sport_id=1" → "sport_id=2", "sport_id=3"..."sport_id=37".
And
var sheet = ss.getSheetByName("soccer");
"soccer" → "baseball", "tennis"..."sportsbusiness"(37 sheets).
baseball:2(id), tennis:3..., sportsbusiness:37
And I imagine like this
function a () {
//I don't know the code I want to write
function fetch_json ()
}
Is it possible?
I don't understand about "dictionary" method, so if there're other ways, plz teach me.
If I understand correctly, you want to get data from different urls and write the data to different sheets in the same spreadsheet based on the sport. I would first define an object for all of the sports:
var sportIds = {
0: 'soccer',
1: 'baseball',
2: 'tennis',
...
36: 'sportsbusiness'
};
In the above object, the keys are the IDs in your url and the values are the sheet names. Then, you can loop through the object and grab/write the data using something like:
var urlBase = "https://api.ookami.me/v1/news/public?sport_id=";
for (var id in sportIds){
var url = urlBase+id; // Generate the url using the id/key from the object
var result = UrlFetchApp.fetch(url);
var sheet = ss.getSheetByName(sportIds[id]);
// write to the sheet as desired
}
Here, you generate the url using the key in the object and get the sheet you want to write to using the corresponding value. It seems like that should do it. Please comment if this isn't what you're looking for.

Can't loop through JSON Object

I am creating a JS object, then stringifying it and trying to loop through the key-value pairs, but it is giving weird results. Please help.
var gv_array = {};
var gv_cookie_name = "_gv";
var gv_cookie_expiry = 1;
var $inv = jQuery.noConflict();
$inv('.product-image').bind('inview', function(event, isInView) {
if (isInView) {
var a = $inv(this).data('productid');
if(jQuery.inArray(a,gv_array) === -1){
gv_array[a]=0;
}
// Converting the array into JSON to save it to cookie
var json_gv_arr = JSON.stringify(gv_array);
setCookie(gv_cookie_name,json_gv_arr,gv_cookie_expiry);
}
});
$inv(document).ready(function(){
setInterval('sendGV()',3000);
});
function sendGV(){
var gv_cookie_val = getCookie(gv_cookie_name);
gv_cookie_val = JSON.parse(gv_cookie_val);
var gv_cookie_array = new Array();
$inv.each( gv_cookie_val, function( key, value ) {
if(value == 0){
gv_cookie_array.push(key);
}
});
alert(gv_cookie_array);
}
The JS Object looks like this when i try to alert it.
{"2234":0,"4563":0,"4555":0}
I need to send ids from the object whose value is 0 to insert into database and just after a receive the success msg from AJAX, i need to change the status of the ids in the object to 1.
UPDATE: Even after parsing the JSON string, it doesnt do anything.
try as like following:
var data = {"2234":0,"4563":0,"4555":0};
$.each(data,function(key,value){
console.log(key+":"+value);
})
Pure javacript:
data = {"2234":0,"4563":0,"4555":0};
keys = Object.keys(data); // ["2234", "4563", "4555"]
for(i = 0; i < keys.length; i++){
console.log(data[keys[i]]); // 0, 0, 0
}
and for set the values:
for(i = 0; i < keys.length; i++){
data[keys[i]] = 1
}
console.log(data); // Object { 2234=1, 4563=1, 4555=1}

Categories