How can we find out battery level info of Beacons - node.js

I am detecting beacons and getting JSON data from which I can get Mac Address of Beacon but I need information about battery level.
Currently I am using node js and using Noble module for searching beacons.
var https = require('https'),
myip = require('quick-local-ip'),
noble = require('noble'),
os = require('os'),
amqp = require('amqp');
noble.on('stateChange', function (state) {
if (state === 'poweredOn') {
console.log("start scanning");
noble.startScanning([], true);
} else {
noble.removeAllListener();
noble.stopScanning();
console.log("stop scanning, is Bluetooth on?");
}
noble.on('discover', function (peripheral) {console.log("peripheral - "+peripheral);}
Output -
{
"id": "ac233f244b34",
"address": "ac:23:3f:24:4b:34",
"addressType": "public",
"connectable": true,
"advertisement": {
"manufacturerData": {
"type": "Buffer",
"data": [76, 0, 2, 21, 226, 197, 109, 181, 223, 251, 72, 210, 176, 96, 208, 245, 167, 16, 150, 224, 0, 1, 0, 1, 129]
},
"serviceData": [{
"uuid": "feaa",
"data": {
"type": "Buffer",
"data": [32, 0, 12, 120, 24, 0, 0, 0, 251, 140, 1, 223, 146, 120]
}
}],
"serviceUuids": ["feaa"],
"solicitationServiceUuids": [],
"serviceSolicitationUuids": []
},
"rssi": -48,
"state": "disconnected"
}
How can I Get to know about Battery level from this data.

Related

Update list of Objects with a value from an array

I had an issue earlier and received some help with it earlier but now i'm having an issue updating/adding a link to earlier issue.
I have a slightly different setup at this point because i couldn't figure out how to update my data.
At this point. I need to get the data from my Array A (filepath) into my list of objects as another property in my sub object with a key of "-i".
I feel like i should be able to iterate through the array and add one of these values to my object but i've tried using the reduce and loop features but haven't been able to get my desired output, if there's a easier way from starting with my last post issue i'd be happy to go back to that state.
//Desired ouput
{
process0000x0000: {-i:"D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0000.png, tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' },
process0000x0001: {-i:"D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0001.png", tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' },
process0000x0002: {-i:"D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0002.png", tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' }
}
//Array A
"outputParameters": [
{
"name": "0000x0000",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0000.png"
},
{
"name": "0000x0001",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0001.png"
},
{
"name": "0000x0002",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0002.png"
}]
// current output
{
process0000x0000: { tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' },
process0000x0001: { tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' },
process0000x0002: { tr: 16, tc: 16, ofr: 16, ofc: 16, outfile: 'D:\\Code\\Process\\1' }
}
UPDATE:
so i added the below but i'm still receiving the last "filepath" for each entry in my consoleparamscompiled data. I tried your way and the way i have shown below but with the same results.
//results
},
process13x21: {
'-i': 'D:\\Code\\UnitTest\\ConsoleApp\\1\\13x23.png',
'-tr': 16,
'-tc': 16,
'-ofr': 16,
'-ofc': 16,
'-outfile': '"D:\\Code\\UnitTest\\ConsoleApp\\Process\\1"'
},
process13x22: {
'-i': 'D:\\Code\\UnitTest\\ConsoleApp\\1\\13x23.png',
'-tr': 16,
'-tc': 16,
'-ofr': 16,
'-ofc': 16,
'-outfile': '"D:\\Code\\UnitTest\\ConsoleApp\\Process\\1"'
},
process13x23: {
'-i': 'D:\\Code\\UnitTest\\ConsoleApp\\1\\13x23.png',
'-tr': 16,
'-tc': 16,
'-ofr': 16,
'-ofc': 16,
'-outfile': '"D:\\Code\\UnitTest\\ConsoleApp\\Process\\1"'
}
}
// ADDED CODE
// loop through each data we want to add and add a property.
` consoleOutputParamsOBJ.forEach((obj) => {
var processname = dynamicTaskNameBaseOBJ + obj.name;
console.log(processname);
//taskparamscompiled.processname['-i'] = obj.filepath;
taskparamscompiled[processname]['-i'] = obj.filepath;
// console.log(dynamicTaskNameBaseOBJ + obj.name);
});
console.log(taskparamscompiled);`
I'm not 100% sure I understand your question, but here goes.
You can access an objects property by a string by using [] instead of .
E.g.
let x = {name: "chris"};
x.name = 'Sam';
x['name'] = 'Ben';
The above will both change the name property
Here is a code example with the data you provided.
let data = [{
"name": "0000x0000",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0000.png"
}, {
"name": "0000x0001",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0001.png"
}, {
"name": "0000x0002",
"filepath": "D:\\Code\\UnitTest\\Tests\\Run_01_TEMP\\0000x0002.png"
}];
let result = {
process0000x0000: {
tr: 16,
tc: 16,
ofr: 16,
ofc: 16,
outfile: 'D:\\Code\\Process\\1'
},
process0000x0001: {
tr: 16,
tc: 16,
ofr: 16,
ofc: 16,
outfile: 'D:\\Code\\Process\\1'
},
process0000x0002: {
tr: 16,
tc: 16,
ofr: 16,
ofc: 16,
outfile: 'D:\\Code\\Process\\1'
}
}
// loop through each data we want to add and add a property.
data.forEach(obj => {
result[`process${obj.name}`]["-i"] = obj.filepath
})
console.log(result)
And the output is :
{
process0000x0000: {
-i: "D:\Code\UnitTest\Tests\Run_01_TEMP\0000x0000.png",
ofc: 16,
ofr: 16,
outfile: "D:\Code\Process\1",
tc: 16,
tr: 16
},
process0000x0001: {
-i: "D:\Code\UnitTest\Tests\Run_01_TEMP\0000x0001.png",
ofc: 16,
ofr: 16,
outfile: "D:\Code\Process\1",
tc: 16,
tr: 16
},
process0000x0002: {
-i: "D:\Code\UnitTest\Tests\Run_01_TEMP\0000x0002.png",
ofc: 16,
ofr: 16,
outfile: "D:\Code\Process\1",
tc: 16,
tr: 16
}
}

SageMakerRuntime invokeEndpoint: Parsing this JSON is giving me undefined

I am trying to invoke function invokeEndpoint and parse response. I am getting data as undefined
I tried to parse this JSON but I can't figure out why it's giving me undefined
sagemakerruntime.invokeEndpoint(params2, function (err, result) {
if (err) {
console.log("INVOKE ENDPOINT ERROR!!!" + err);
} else {
console.log(JSON.stringify(result));
}
});
JSON printed:
{
"ContentType": "text/csv; charset=utf-8",
"InvokedProductionVariant": "variant-name-1",
"Body": {
"type": "Buffer",
"data": [
123,
34,
54,
50,
102,
55,
48,
51,
53,
102,
45,
99,
102,
52,
52,
45,
52,
53,
50,
50,
99,
100,
49,
48,
50,
49,
51,
97,
51,
52,
52,
34,
58,
32,
34,
81
]
}
}
Tried:
console.log(JSON.stringify(result["Body"].data));
Keeps giving me undefine.. unsure why. Tried doing result["Body"].data.toString('utf8'); doesn't work either. Anyone know what I'm doing wrong?
According to doc: SageMakerRuntime.html, Body is buffer type.
Try this:
sagemakerruntime.invokeEndpoint(params2, function (err, result) {
if (err) {
console.log("INVOKE ENDPOINT ERROR!!!" + err);
} else {
console.log(JSON.stringify(result.Body.toString('utf8')));
}
});

Write Array in nodeOpcua

Hiii, some body know how i can write Uint16Array in kepserver i got some error:
ConstantStatusCode {
_value: 2147483648,
_description: 'The value is bad but no specific reason is known.',
_name: 'Bad' } ]
i'm try this:
var valor = new Uint16Array([ 2, 23, 23, 12, 24, 3, 25, 3, 26, 3, 27, 3, 28, 1, 43690, 1, 1261, 0, 0, 0, 0, 0, 0, 0, 65535, 11 ])
nodeToWrite[0] = {
nodeId: resolveNodeId("ns=2;s=" + endereco[0].ADDRESS),
attributeId: opcua.AttributeIds.Value,
value: /new DataValue(/{ value: {/ Variant /
dataType: 5,
arrayType: 1,
value: valor,
}
}
}
const {AttributeIds, OPCUAClient, DataType, VariantArrayType} = require("node-opcua");
const endpointUrl = "opc.tcp://localhost:48010";
(async () => {
const client = OPCUAClient.create({ endpoint_must_exist: false});
await client.withSessionAsync(endpointUrl, async (session) => {
const arrayOfvalues = new Uint16Array([ 2, 23, 23, 12, 24, 3, 25, 3, 26, 3, 27, 3, 28, 1, 43690, 1, 1261, 0, 0, 0, 0, 0, 0, 0, 65535, 11 ]);
const nodeToWrite = {
nodeId: "ns=2;s=Demo.Static.Arrays.UInt16",
attributeId: AttributeIds.Value,
value: {
value: {
dataType: DataType.UInt16,
arrayType: VariantArrayType.Array,
value: arrayOfvalues,
}
}
}
const statusCode = await session.write(nodeToWrite);
console.log("write statusCode = ",statusCode.toString());
});
})();
As demonstrated above, writing a Array of Uint16 is ok when addressing node ns=2;s=Demo.Static.Arrays.UInt16 of UAServerCPP from Unified Automation.
I would contact Kepware for support.

How to render a graph as image in node

I want to render a stacked bar graph in image format on the server.
The intended use is to push to a service like twitter that doesn't support SVG. As well as the code being being deployable to services like Heroku
I've already tried Plotly (their node package is horribly out of date and their API docs poor). I've also looked at Google Graph, Chart.js and AnyChart but they do not support rendering images far as I can see
You can accomplish this with Vega
Vega is a visualization grammar, a declarative format for creating, saving, and sharing interactive visualization designs. With Vega you can describe data visualizations in a JSON format, and generate interactive views using either HTML5 Canvas or SVG.
For example, using the stacked bar chart example spec you can render the chart to PNG file with the following code:
// START vega-demo.js
var vega = require('vega')
var fs = require('fs')
var stackedBarChartSpec = require('./stacked-bar-chart.spec.json');
// create a new view instance for a given Vega JSON spec
var view = new vega
.View(vega.parse(stackedBarChartSpec))
.renderer('none')
.initialize();
// generate static PNG file from chart
view
.toCanvas()
.then(function (canvas) {
// process node-canvas instance for example, generate a PNG stream to write var
// stream = canvas.createPNGStream();
console.log('Writing PNG to file...')
fs.writeFile('stackedBarChart.png', canvas.toBuffer())
})
.catch(function (err) {
console.log("Error writing PNG to file:")
console.error(err)
});
// END vega-demo.js
// START stacked-bar-chart.spec.json
{
"$schema": "https://vega.github.io/schema/vega/v3.0.json",
"width": 500,
"height": 200,
"padding": 5,
"data": [
{
"name": "table",
"values": [
{"x": 0, "y": 28, "c":0}, {"x": 0, "y": 55, "c":1},
{"x": 1, "y": 43, "c":0}, {"x": 1, "y": 91, "c":1},
{"x": 2, "y": 81, "c":0}, {"x": 2, "y": 53, "c":1},
{"x": 3, "y": 19, "c":0}, {"x": 3, "y": 87, "c":1},
{"x": 4, "y": 52, "c":0}, {"x": 4, "y": 48, "c":1},
{"x": 5, "y": 24, "c":0}, {"x": 5, "y": 49, "c":1},
{"x": 6, "y": 87, "c":0}, {"x": 6, "y": 66, "c":1},
{"x": 7, "y": 17, "c":0}, {"x": 7, "y": 27, "c":1},
{"x": 8, "y": 68, "c":0}, {"x": 8, "y": 16, "c":1},
{"x": 9, "y": 49, "c":0}, {"x": 9, "y": 15, "c":1}
],
"transform": [
{
"type": "stack",
"groupby": ["x"],
"sort": {"field": "c"},
"field": "y"
}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": {"data": "table", "field": "x"}
},
{
"name": "y",
"type": "linear",
"range": "height",
"nice": true, "zero": true,
"domain": {"data": "table", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "table", "field": "c"}
}
],
"axes": [
{"orient": "bottom", "scale": "x", "zindex": 1},
{"orient": "left", "scale": "y", "zindex": 1}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "x"},
"width": {"scale": "x", "band": 1, "offset": -1},
"y": {"scale": "y", "field": "y0"},
"y2": {"scale": "y", "field": "y1"},
"fill": {"scale": "color", "field": "c"}
},
"update": {
"fillOpacity": {"value": 1}
},
"hover": {
"fillOpacity": {"value": 0.5}
}
}
}
]
}
// END stacked-bar-chart.spec.json
Will output PNG file:
I capture charts, visualizations and reports under Node.js using the Nightmare headless browser.
Using Nightmare allows you to use any of the wide variety of browser-based visualization frameworks under Node.js, including C3 and D3 which are both awesome.
I've actually created a npm module called c3-chart-maker that wraps up Nightmare and allows you to render a chart under Node.js by feeding it some data and a C3 chart definition.
Install it like this:
npm install --save c3-chart-maker
Use it like this:
const c3ChartMaker = require('c3-chart-maker');
const yourData = ... your data ...
const chartDefinition = { ... c3 chart definition ... }
const outputFilePath = "your-chart-output-file.png";
c3ChartMaker(yourData, chartDefinition, outputFilePath)
.then(() => {
console.log('Done');
})
.catch(err => {
console.error(err);
});
Please check out the C3 example gallery for examples of charts and to see what a C3 chart definition looks like.
You can also use Nightmare manually to be able to capture any web page or browser-based visualization.
To install Nightmare:
npm install --save nightmare
Here's an example that can capture a web page:
const Nightmare = require('nightmare');
// This is the web page to capture.
// It can also be a local web server!
// Or serve from the file system using file://
const urlToCapture = "http://my-visualization.com";
const outputFilePath = "your-chart-output-file.png";
const nightmare = new Nightmare(); // Create Nightmare instance.
nightmare.goto(urlToCapture) // Point the browser at the requested web page.
.wait("svg") // Wait until the specified HTML element appears on the screen.
.screenshot(outputImagePath) // Capture a screenshot to an image file.
.end() // End the Nightmare session. Any queued operations are completed and the headless browser is terminated.
.then(() => {
console.log("Done!");
})
.catch(err => {
console.error(err);
});
I've written more extensively about this on my blog.
I've also dedicated a whole chapter to this in my book Data Wrangling with JavaScript.
Simple Headless NodeJS (not localhost or web-based)
For my purposes, I wanted to just plot a chart without spinning up a localhost server or anything. So I used chartjs-node-canvas and chart.js
Install with:
npm i chartjs-node-canvas chart.js
In this I write it to a file to show it worked but I personally just needed the Base64 string to upload somewhere
// Install libs with: npm i chartjs-node-canvas chart.js
// Docs https://www.npmjs.com/package/chartjs-node-canvas
// Config documentation https://www.chartjs.org/docs/latest/axes/
const fs = require('fs');
const { ChartJSNodeCanvas } = require('chartjs-node-canvas');
const width = 400; //px
const height = 400; //px
const backgroundColour = 'white'; // Uses https://www.w3schools.com/tags/canvas_fillstyle.asp
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height, backgroundColour });
const configuration = {
type: 'line', // for line chart
data: {
labels: [2018, 2019, 2020, 2021],
datasets: [{
label: "Sample 1",
data: [10, 15, -20, 15],
fill: false,
borderColor: ['rgb(51, 204, 204)'],
borderWidth: 1,
xAxisID: 'xAxis1' //define top or bottom axis ,modifies on scale
},
{
label: "Sample 2",
data: [10, 30, 20, 10],
fill: false,
borderColor: ['rgb(255, 102, 255)'],
borderWidth: 1,
xAxisID: 'xAxis1'
},
],
},
options: {
scales: {
y: {
suggestedMin: 0,
}
}
}
}
async function run() {
const dataUrl = await chartJSNodeCanvas.renderToDataURL(configuration);
const base64Image = dataUrl
var base64Data = base64Image.replace(/^data:image\/png;base64,/, "");
fs.writeFile("out.png", base64Data, 'base64', function (err) {
if (err) {
console.log(err);
}
});
return dataUrl
}
run()
Here's the docs https://www.npmjs.com/package/chartjs-node-canvas and the Config documentation is here https://www.chartjs.org/docs/latest/axes/

MongoDB MapReduce weird bug

I'm trying this simple MapReduce operation:
function map() {
var gameDay = Math.floor((this.matchCreation - 1427846400000) / 86400000) + 1; // day of april 2015 when the game was played
this.teams.forEach (function (team){
**team.bans.forEach(function (ban){** // says bans is undefined
var value ={
banned : 1,
firstBanned: ( ((ban.pickTurn == 1) || (ban.pickTurn == 2))? 1 : 0 )
}
emit({championId: ban.championId,
day: Number(gameDay)}, value);
emit({championId: ban.championId,
day: "all"}, value);
});
});
}
function reduce(key, values) {
var a = values[0];
for(var i = 1 ; i<values.length ; i++){
var b = values[i]; // will merge 'b' into 'a'
a.banned += (b.banned? b.banned : 0);
a.firstBanned += (b.firstBanned? b.firstBanned : 0);
for (var attrname in b){
if(attrname != "banned" && attrname != "firstBanned")
a[attrname] = b[attrname];
}
}
return a;
}
matchesCollection.mapReduce(map, reduce, {
out: { reduce: "mapReduceResults" }
}, function (err, data){
if(err)
return callback (err);
callback (null, "OK");
});
It used to work before, but just when I tried to deploy the app after testing for a while, it seems to fail in this line: team.bans.forEach(function (ban){, says team.bans is undefined, although every one of the documents has a "teams" array and a "bans" array inside of each object in it, I even double checked it by querying the database and there is no document in which those fields dont exist.
So weird. The reduce function is a bit more complex but it seems to work alright, yet the map one (unlike Reduce, its supposed to be called just once per original document, right?) throws this unexplainable error. Could anyone give me some insight?
Sample input:
{
"_id": {
"$oid": "5531a63f2a3f135c11ed14a8"
},
"matchId": 1778704162,
"region": "NA",
"platformId": "NA1",
"matchMode": "CLASSIC",
"matchType": "MATCHED_GAME",
"matchCreation": 1427864425511,
"matchDuration": 1431,
"queueType": "URF_5x5",
"mapId": 11,
"season": "SEASON2015",
"matchVersion": "5.6.0.194",
"participants": [
{
"teamId": 100,
"spell1Id": 12,
"spell2Id": 4,
"championId": 81,
"highestAchievedSeasonTier": "SILVER",
"timeline": [],
"masteries": [],
"stats": {
"winner": false,
"champLevel": 19,
"item0": 1037,
"item1": 3078,
"item2": 3117,
"item3": 3035,
"item4": 3072,
"item5": 1038,
"item6": 3340,
"kills": 7,
"doubleKills": 1,
"tripleKills": 0,
"quadraKills": 0,
"pentaKills": 0,
"unrealKills": 0,
"largestKillingSpree": 3,
"deaths": 15,
"assists": 9,
"totalDamageDealt": 103191,
"totalDamageDealtToChampions": 22148,
"totalDamageTaken": 32924,
"largestCriticalStrike": 669,
"totalHeal": 2263,
"minionsKilled": 97,
"neutralMinionsKilled": 1,
"neutralMinionsKilledTeamJungle": 1,
"neutralMinionsKilledEnemyJungle": 0,
"goldEarned": 13923,
"goldSpent": 13273,
"combatPlayerScore": 0,
"objectivePlayerScore": 0,
"totalPlayerScore": 0,
"totalScoreRank": 0,
"magicDamageDealtToChampions": 6082,
"physicalDamageDealtToChampions": 15803,
"trueDamageDealtToChampions": 263,
"visionWardsBoughtInGame": 0,
"sightWardsBoughtInGame": 0,
"magicDamageDealt": 45997,
"physicalDamageDealt": 56651,
"trueDamageDealt": 543,
"magicDamageTaken": 25249,
"physicalDamageTaken": 7490,
"trueDamageTaken": 184,
"firstBloodKill": false,
"firstBloodAssist": false,
"firstTowerKill": false,
"firstTowerAssist": false,
"firstInhibitorKill": false,
"firstInhibitorAssist": false,
"inhibitorKills": 0,
"towerKills": 4,
"wardsPlaced": 2,
"wardsKilled": 0,
"largestMultiKill": 2,
"killingSprees": 1,
"totalUnitsHealed": 1,
"totalTimeCrowdControlDealt": 98
},
"participantId": 1,
"runes": []
},
... (9 more like that)
],
"participantIdentities": [],
"teams": [
{
"teamId": 100,
"winner": false,
"firstBlood": true,
"firstTower": false,
"firstInhibitor": true,
"firstBaron": false,
"firstDragon": true,
"towerKills": 6,
"inhibitorKills": 2,
"baronKills": 0,
"dragonKills": 3,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 120,
"pickTurn": 1
},
{
"championId": 37,
"pickTurn": 3
},
{
"championId": 13,
"pickTurn": 5
}
]
},
{
"teamId": 200,
"winner": true,
"firstBlood": false,
"firstTower": true,
"firstInhibitor": false,
"firstBaron": false,
"firstDragon": false,
"towerKills": 11,
"inhibitorKills": 4,
"baronKills": 0,
"dragonKills": 0,
"vilemawKills": 0,
"dominionVictoryScore": 0,
"bans": [
{
"championId": 28,
"pickTurn": 2
},
{
"championId": 38,
"pickTurn": 4
},
{
"championId": 63,
"pickTurn": 6
}
]
}
]
}
Expected output:
{
_id: { championId: Number, day: Number }
value: { banned: Number, firstBanned: Number }
}
After that, its supposed to merge with the results of a previous MapReduce operation, copying all the fields of documents with the same key (in the reduce function), but thats irrelevant now since the error happens before...

Resources