Dealing with uint8_t in javascript - javascript

G'day peoples,
I'm using MavLink to obtain GPS information. One of the message types is GPS_STATUS which is described by MavLink using a series of uint8_t[20].
If I run the following code:
console.log(' sat prn: ' + message.satellite_prn);
console.log(' sat prn: ' + JSON.stringify(message.satellite_prn));
console.log(' sat prn: ' + JSON.stringify(new Uint8Array(message.satellite_prn)));
I get the following output:
sat prn: <weird charcaters...>
sat prn: "\u0002\u0005\n\f\u000f\u0012\u0015\u0019\u001a\u001b\u001d\u001e\u001f\u0000\u0000\u0000\u0000"
sat prn: {"BYTES_PER_ELEMENT":1,"buffer":{"byteLength":0},"length":0,"byteOffset":0,"byteLength":0}
So obviously it's not working. I need a means to get the int value of each element.
I found this https://developer.mozilla.org/en-US/docs/JavaScript/Typed_arrays?redirectlocale=en-US&redirectslug=JavaScript_typed_arrays
Which made me think I would be able to do the following:
satellite_prn = Array.apply([], new Uint8Array(message.satellite_prn));
satellite_prn.length === 20;
satellite_prn.constructor === Array;
But when I stringify it via JSON it reports [], I presume this is an empty array.
Anyone know how I can do this? I know that the data is an array of 20 unsigned 8 bit integers. I just need to know how to access or parse them.
Note: I'm using node.js, but that shouldn't affect what I'm doing. This is why I'm using console.log, as it's avail in node.js.

Two issues with your code:
message.satellite_prn is a string not an array
Unit8Array needs to be loaded with .set
To get an array of numbers from message.satellite_prn, do this:
var array = message.satellite_prn.map(function(c) { return c.charCodeAt(0) })
To load an ArrayBuffer, do this:
var buffer = new ArrayBuffer(array.length);
var uint8View = new Uint8Array(buffer);
uint8View.set(array);
Ideally you wouldn't need to go through the string. If you are obtaining the data from an up-to-date implementation of XMLHttpRequest, such as xhr2, you can set:
responseType = "arraybuffer"

Looks like the problem is my understanding on how to deal with binary data within javascript. I found that I can just do the following to get the data as base 10 via charCodeAt().
The following is the code that allowed me to iterate through the 20 unsigned 8 bit integers and get each value as a decimal:
for(var i = 0, l = message.satellite_prn.length; i < l; i++) {
console.log(' Satellite ' + i + ', id: ' +
parseInt(message.satellite_prn.charCodeAt(i), 10)
);
}
I suspect that there may be a function that allows me to convert the binary data into an array, but for an unknown reason Uint8Array didn't appear to be working for me. However the above does.

Related

Return array value from JSON parse that contains a certain phrase

I'm trying to only return array values that contain a specific phrase in the string of 'Corp'
This returns all the values, but I only need the ones that contain "Corp"
var url = "/iaas/api/image-profiles";
System.debug("getImageProfiles url: "+url);
var response=System.getModule("pso.vra.util.rest").genericRestAPI(url,null,null);
var responseJSON=JSON.parse(response.contentAsString);
System.log("Response : "+JSON.stringify(responseJSON));
var imageProfilesContent=responseJSON.content;
var imageProfiles = [];
System.log("Checking : "+Object.keys(responseJSON.content[0].imageMappings.mapping));
var imageProfiles = JSON.stringify(Object.keys(responseJSON.content[0].imageMappings.mapping));
System.log(imageProfiles);
return JSON.parse(imageProfiles);
0 Windows Server 2022
1 Windows Server 2019
2 Windows Server 2022 - Corp
3 Windows Server 2019 - Corp
4 Rhel8 - Corp
5 Rhel8
...
I tried using filter() but could not figure out how to use it.
To use filter I believe you'll want something like this:
filteredImageProfiles = imageProfiles.filter(item => item.includes('Corp'));
I'm not exactly sure what the structure of your object is but that is an example of a filter ^^^. Just make sure you have whatever item is is a string to test against Corp
Let me know if that isn't helpful though I can come back, but without know the structure of the object this is as close as I can get you.
I'm sure #Rhett's answer will work for someone who knows javascript better than I do but I got it to work with a for loop:
function checkCorp() {
for ( i = profiles.length - 1; i >= 0; i--) {
var element = profiles[i];
if (element.toLowerCase().indexOf("Corp".toLowerCase()) == -1) {
profiles.splice(i, 1);
}
}
System.log(profiles);
}

Leading and trailing zeros in numbers

I am working on a project where I require to format incoming numbers in the following way:
###.###
However I noticed some results I didn't expect.
The following works in the sense that I don't get an error:
console.log(07);
// or in my case:
console.log(007);
Of course, it will not retain the '00' in the value itself, since that value is effectively 7.
The same goes for the following:
console.log(7.0);
// or in my case:
console.log(7.000);
JavaScript understands what I am doing, but in the end the actual value will be 7, which can be proven with the following:
const leadingValue = 007;
const trailingValue = 7.00;
console.log(leadingValue, trailingValue); // both are exactly 7
But what I find curious is the following: the moment I combine these two I get a syntax error:
// but not this:
console.log(007.000);
1) Can someone explain why this isn't working?
I'm trying to find a solution to store numbers/floats with the exact precision without using string.
2) Is there any way in JS/NodeJS or even TypeScript to do this without using strings?
What I currently want to do is to receive the input, scan for the format and store that as a separate property and then parse the incoming value since parseInt('007.000') does work. And when the user wants to get this value return it back to the user... in a string.. unfortunately.
1) 007.000 is a syntax error because 007 is an octal integer literal, to which you're then appending a floating point part. (Try console.log(010). This prints 8.)
2) Here's how you can achieve your formatting using Intl.NumberFormat...
var myformat = new Intl.NumberFormat('en-US', {
minimumIntegerDigits: 3,
minimumFractionDigits: 3
});
console.log(myformat.format(7)); // prints 007.000
Hi
You can use an aproach that uses string funtions .split .padStart and .padEnd
Search on MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
Here you have an example:
const x = 12.1;
function formatNumber( unformatedNumber) {
const desiredDecimalPad = 3;
const desiredNonDecimalPad = 3;
const unformatedNumberString = unformatedNumber.toString();
const unformatedNumberArr = unformatedNumberString.split('.');
const decimalStartPadded = unformatedNumberArr[0].padStart(desiredDecimalPad, '0');
const nonDecimalEndPadded = unformatedNumberArr[1].padEnd(desiredNonDecimalPad, '0');
const formatedNumberString = decimalStartPadded + '.' + nonDecimalEndPadded;
return formatedNumberString;
}
console.log(formatNumber(x))

Sorting and filtering on Date

I have a date column and need to be able to both sort and filter on it. The data comes in as strings like 2010-12-23 and can pre-processed as needed. It should be shown as 23.12.2010. Some internationalization will come later.
I wonder what's the proper internal representation:
a string like "23.12.2010" is bad for sorting (it could be done by sorting on function result, but it'd be slow)
a string like "2010-12-23" sorts correctly, can be formatted easily, but filtering for 23.12 does not work (it could be done, but it'd be slow)
Date would probably get sorted correctly, but filtering would be slow
moment could be the solution, no idea
My current idea is to create an object containing both milliseconds and the displayed string, so that all operations can be fast. But I'd bet that someone was that smart before me....
Let's assume that showing dates in the form like 2010-12-23 is unacceptable, otherwise the problem is solved. To summarize, the problem is that I need to
display and filter in the DD.MM.YYYY format
sort according to the numerical value (or equivalently, as if it was in th ISO format).
I think the method you're proposing wouldn't run in to too many performance issues, unless you're going for really old browsers or mobile devices.
I've mocked up an example to do a quick (performance) test. First, I'm defining an object that holds a value optimized for sorting, and a value optimized for display:
var MyDate = function(dateString) {
var date = new Date(dateString);
var displayValue = "{0}.{1}.{2}"
.replace("{0}", prefixZeroIfNeeded(date.getUTCDate()))
.replace("{1}", prefixZeroIfNeeded(date.getUTCMonth() + 1))
.replace("{2}", date.getUTCFullYear());
return {
sortKey: date.getTime(),
displayValue: displayValue
};
};
The prefixZeroIfNeeded method ensures we get the DD.MM format rather than the dd.mm one:
var prefixZeroIfNeeded = function(nr) {
return nr < 10 ? "0" + nr : "" + nr;
};
Then, we need some data to convert:
var data = [];
var myDates = data
.map(MyDate)
.sort(function(date1, date2) {
return date1.sortKey - date2.sortKey;
});
Finally, a quick example of a very basic search function:
var searchMyDates = function(str) {
return myDates.filter(function(myDate) {
return myDate.displayValue.indexOf(str) !== -1;
});
};
Now, we can create some mockup data and check how long it would actually take to A) map and sort the raw strings to the MyDate objects, and B) search for a string in our collection.
Here's how I generated the raw data:
for (var i = 0; i < 10000; i += 1) {
var y = Math.floor(Math.random() * 101) + 1900;
var m = prefixZeroIfNeeded(Math.floor(Math.random() * 13));
var d = prefixZeroIfNeeded(Math.floor(Math.random() * 29));
data.push(y + "-" + d + "-" + m);
}
Using console.time to measure, processing the data on my machine (A) takes around 40ms. Searching for the string .12. takes around 5-10ms.
Concluding: I think you were definitely on the right track and could continue work in the proposed direction. However, in my personal experience, I've learned that whenever I start work on a feature that involves dates and times, moment.js is the way to go. You'll eventually run in to daylight saving time, time zones, you name it and regret you thought it was simple...
Let me know if this is of any help.
Edit: the code in a snippet (check your browser console for output)
var data = [];
var prefixZeroIfNeeded = function(nr) {
return nr < 10 ? "0" + nr : "" + nr;
};
// Generate random data:
for (var i = 0; i < 10000; i += 1) {
var y = Math.floor(Math.random() * 101) + 1900;
var m = prefixZeroIfNeeded(Math.floor(Math.random() * 13));
var d = prefixZeroIfNeeded(Math.floor(Math.random() * 29));
data.push(y + "-" + d + "-" + m);
}
var MyDate = function(dateString) {
var date = new Date(dateString);
var displayValue = "{0}.{1}.{2}"
.replace("{0}", prefixZeroIfNeeded(date.getUTCDate()))
.replace("{1}", prefixZeroIfNeeded(date.getUTCMonth() + 1))
.replace("{2}", date.getUTCFullYear());
return {
sortKey: date.getTime(),
displayValue: displayValue
};
};
console.time("Map and sorting");
var myDates = data
.map(MyDate)
.sort(function(date1, date2) {
return date1.sortKey - date2.sortKey;
});
var searchMyDates = function(str) {
return myDates.filter(function(myDate) {
return myDate.displayValue.indexOf(str) !== -1;
});
};
console.timeEnd("Map and sorting");
console.time("Search");
console.log("Searching for the month 12, %d results.", searchMyDates(".12.").length);
console.timeEnd("Search");
This may help you a bit. I have used the same thing working with React. Here is a link for Moment.js -
http://momentjs.com/docs/#/displaying/format/
If you go under Display -> Format on the right menu bar, you'll see localized formats, you will need to use format L - pre defined format from moment which will show you 09/04/1986 (September 4, 1986); otherwise you can create your own using DD-MM-YYYY format.
For Example, The way I used in React for my exercise is
To define a variable using let:
let deadlineFormated = Moment(this.props.ToDoItem.deadline).format('llll');
Hope this helps for Angular!
Gist: Decouple sorting and filtering. Do sorting on the internal representation and filtering on the presentation.
Sort on internal representation that is in any naturally sortable format. Your raw YYYY-MM-DD date strings would work, so would parsing them into Date objects. The performance difference could be negligible unless you're dealing with lots and lots of rows -- but in that case you would already have other issues with latency and rendering performance.
It's more intuitive if free-text filtering is done on what's displayed (the presentation). So if you're formatting the dates as "May 7, 2016", do a substring match on that. If you're formatting the dates as DD.MM.YYYY, do a substring match on that.
If filtering is driven by actual date selections from controls like a date picker or a select field, you can do the filtering on the internal representation.
Try with this:
Get Unixtimestamp for date (i.e. Numeric format) and use jquery sort.
Please check this example for jquery sort. Regarding example replace your unixtimestamp to value.
<ul id="datelist">
<li value="1360013296">Date 1</li>
<li value="1360013297">Date 2</li>
<li value="1360013298">Date 3</li>
<li value="1360013299">Date 4</li>
</ul>
https://jsfiddle.net/ajaygokhale/bohgoq8o/
To reliably implement sorting converting it into a Date Object is recommended (new Date(str))
If you need to be flexible in formatting moment has formatting support (check moment.format()) as well. Moment has pretty deep locale support as well.
You can always keep it a Date Object as the source of truth and for filtering you could do Date.toString() just at the time of filtering. This returns a string you could then filter with.

Is there Any Way to Convert Mongo ObjectId into string by javascript/jquery

Is it possible to convert mongo objectId into string.
The above pictures shows data i received and shown in console.I need id value in string form .but ObjectId is returning as object
In Database id is look like this- 565d3bf4cefddf1748d1fc5e -objectId and i need id exactly like this –
According to the Mongo documentation:
a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.
You can check it out here: https://docs.mongodb.org/manual/reference/object-id/
So in javascript you could do something like this.
var mId = {
Timestamp:1448950573,
Machine:13565407,
Pid:1756,
Increment:8888962
};
function getId(mongoId) {
var result =
pad0(mongoId.Timestamp.toString(16), 8) +
pad0(mongoId.Machine.toString(16), 6) +
pad0(mongoId.Pid.toString(16), 4) +
pad0(mongoId.Increment.toString(16), 6);
return result;
}
function pad0(str, len) {
var zeros = "00000000000000000000000000";
if (str.length < len) {
return zeros.substr(0, len-str.length) + str;
}
return str;
}
console.log(getId(mId))
It produces "565d3b2dcefddf06dc87a282" which was not exactly the id you had, but that might just be a tweak or i was working with different data :D.
EDIT
Added a padding function so that zeros are not truncated.
Hope that helps
EDIT:
I assume you are using c# to connect to and serve documents from the mongo DB. In that case, there is a driver that also supports toString().
Here is an example using the mongo csharp driver:
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
// ...
string outputFileName; // initialize to the output file
IMongoCollection<BsonDocument> collection; // initialize to the collection to read from
using (var streamWriter = new StreamWriter(outputFileName))
{
await collection.Find(new BsonDocument())
.ForEachAsync(async (document) =>
{
using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonWriter(stringWriter))
{
var context = BsonSerializationContext.CreateRoot(jsonWriter);
collection.DocumentSerializer.Serialize(context, document);
var line = stringWriter.ToString();
await streamWriter.WriteLineAsync(line);
}
});
}
ORIGINAL:
These are Mongo ObjectId's and if you haven't already deserialised the document they should support a toString method that will return a hexadecimal string.
but if you want this applied to the whole document, using JSON.stringify(MogoDocument) should deserialize this for you into a plain object.

Converting CSV to JSON in a strange format

I have a lot of geo's which I want to use in webgl globe.
The format for Webgl is
Sample for Googles .json file in their working webgl globe source [["1993",[long, lat,weight,long, lat,weight],["1994",[long, lat,weight,long, lat,weight,long, lat,weight,long, lat,weight]]]
I've been looking for a way to convert this but i can't find a converter online.
Does anyone know where I can find a converter for this format or suggest a way to do this.
Sample of my data:
- Year Latitude Longitude Magnitude
- 1995 -82.8627519 -135 0.11
- 1995 -54.423199 3.413194 0.01
- 1994 -53.08181 73.504158 0.01
- 1994 -51.796253 -59.523613 0.04
- 1993 -49.280366 69.348557 0.02
- 1993 -41.4370868 147.1393767 0.18
Looking at this more, I think the json file Google are using is a nested json array of arrays. This
There are multiple ways to parse the data.
The first step is to save the data to a file.
For example:
Year Latitude Longitude Magnitude
1995 -82.8627519 -135 0.11
1995 -54.423199 3.413194 0.01
1994 -53.08181 73.504158 0.01
1994 -51.796253 -59.523613 0.04
1993 -49.280366 69.348557 0.02
1993 -41.4370868 147.1393767 0.18
in raw.txt
The second step is to load and parse data.
With parsing there are a couple of things to keep in mind:
The raw data has an inconsistent number of white spaces separating values, so those need to be collapsed first so we can split a row/line by the space character. Luckily the data doesn't contains names containing spaces so we can use a RegEx like so /\s{2,}/g
We want to gather all the data pertaining to one year into a single list. One way is to use an array and continuously check if it has the year value already. Another is to simply use an Object/associative array/dictionary and not worry about any checks.
Once the data is correctly gathered in a object we pop it into a an array so it matches the format of the data being used.
Here's what I mean:
xhr = new XMLHttpRequest();
xhr.open('GET', '/globe/raw.txt', true);
xhr.onreadystatechange = function(e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var lines = xhr.responseText.split("\n");//split .txt file into lines
var data = [];//prepare an array to hold the end result
var dict = {};//use an Object/Dictionary to collapse data from same key/year
for(var i = 1 ; i < lines.length; i++){//for each line
var line = lines[i].replace(/\s{2,}/g, ' ').split(' ');//collapse white spaces and split into an array of values
if( !dict[line[0]]) dict[line[0]] = [];//if there isn't an array to store that data yes, make one
dict[line[0]].push(parseFloat(line[1]));//append data into the coresponding key/year
dict[line[0]].push(parseFloat(line[2]));
dict[line[0]].push(parseFloat(line[3]));
}
for(var key in dict) data.push([key,dict[key]]);//at the end, loop through the object and populate an array
console.log(data);
}
}
};
xhr.send(null);
so if you use something like this:
xhr = new XMLHttpRequest();
xhr.open('GET', '/globe/raw.txt', true);
xhr.onreadystatechange = function(e) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var lines = xhr.responseText.split("\n");//split .txt file into lines
var data = [];//prepare an array to hold the end result
var dict = {};//use an Object/Dictionary to collapse data from same key/year
for(var i = 1 ; i < lines.length; i++){//for each line
var line = lines[i].replace(/\s{2,}/g, ' ').split(' ');//collapse white spaces and split into an array of values
if( !dict[line[0]]) dict[line[0]] = [];//if there isn't an array to store that data yes, make one
dict[line[0]].push(parseFloat(line[1]));//append data into the coresponding key/year
dict[line[0]].push(parseFloat(line[2]));
dict[line[0]].push(parseFloat(line[3]));
}
for(var key in dict) data.push([key,dict[key]]);//at the end, loop through the object and populate an array
window.data = data;
for (i=0;i<data.length;i++) {
globe.addData(data[i][1], {format: 'magnitude', name: data[i][0], animated: true});
}
globe.createPoints();
settime(globe,0)();
globe.animate();
}
}
};
xhr.send(null);
in the WebGL Globe experiment running on a server you will see your data.

Categories