Workaround to read response from write - bluetooth

From https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-writevalue, I see that writeValue returns a DataView, but I keep getting null on my Chrome (Version 70.0.3538.77 (Official Build) (64-bit) on High Sierra).
What I do is as below, status from writeValue() is null, and value from readValue() is an empty DataView:
let status = await wifiChar.writeValue(encoder.encode(wifiValue));
console.log('status: ', status)
let value = await wifiChar.readValue();
console.log('value: ', value)

Related

request call giving me TypeError: Cannot read property 'statusCode' of undefined

I'm trying to use the OneDrive API to checkout a file (locking it by making it read-only) https://learn.microsoft.com/en-us/onedrive/developer/rest-api/api/driveitem_checkout?view=odsp-graph-online
My lockFile function below calls this api, and successfully locks the file. The problem is that I'm getting an error right after the call: TypeError: Cannot read property 'statusCode' of undefined
I've been stepping through this call with my debugger and the error is popping before I even try to call statusCode on the line below it. Looking at the OneDrive API, it says it only returns a status: 204. Could it be that the request package I'm using is expecting a statusCode somewhere under the hood? If so, how can I resolve this if I'm only getting a status back?
Also, while stepping through with my debugger I've noticed that the error pops up a second before I see the response returns and is set to IncomingMessage. I'm trying to look up docs explaining what that means, but I haven't been finding anything helpful.
lockFile(fileId, driveId, authorization, callback) {
const call = {
method: 'POST',
url: authorization.meta.serviceEndpointUri + '/drives/' + driveId + '/items/' + fileId + '/checkout',
headers: {
Authorization: 'Bearer ' + authorization.access_token
}
}
request(call, (err, response, body) => {
/////////////////
//I'M GETTING THE ERROR RIGHT HERE, BEFORE IT GETS TO THE NEXT LINE
/////////////////
if (err || (response && response.statusCode !== 204)) {
let statusCode = (response && response.statusCode) ? response.statusCode : 500;
statusCode = (statusCode === 204) ? 500 : statusCode;//We don't want to send a 204 id there isn't the right data
callback(StorageProviderError(this.name, statusCode, 1007, body));
}
return callback(null, response);
});
};
I can't comment (NOOB), my guess without running the code is that you are returning the function before code inside the if statement is finished executing.
try adding an else block and put the return there. I typically surround things in a promise or at the least a try catch block.

List element of a dataLayer with puppeteer

i'm doing a web scraping bot thanks to puppeteer, and i want to verify a field of a dataLayer on some url thanks to cloud functions on Google Cloud Plateform.
right now i'm using the await page.$('dataLayer') and it return a "true", so it find the dataLayer.
there is the dataLayer on my browser (not puppeteer)
my code:
exports.datalayer = async(page) => {
//verfify if there is a dataLayer
let dl = await page.$('dataLayer')
if(dl =! null){
console.log('DataLayer found')
//want to do something like that
for(let key in dl){
let value = dl[key]
console.log('key: ' + key + ' value: ' + value)
}
//or like that
dl.forEach(element => {
console.log(element)
});
}else{
console.log('error with the dataLayer')
}
}
In order to catch the OnetrustActiveGroups data.
when i do the forEach method i get this error:
and for the for method i get this error:
better use the page.evaluate('dataLayer')
then stringify it or use it as you want :)
and with the evaluate the for(let item in dl) works fine !

Getting response before firebase transaction done

I'm trying to retrieve all the child then when there's match display.
I print the value in the console and my code work well there after few second, but when I print it in the agent as a message it show not available before the response because it does not wait.
Here is my code:
function retrieveContact(agent) {
var query = admin.database().ref("/contacts").orderByKey();
query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var key = childSnapshot.key;
var childName = childSnapshot.child('name').val();
if (agent.parameters.name == childName) {
console.log('find ' + childName);
agent.add('The email address for ' + childName + ' is ' + childSnapshot.child('email').val());
}
// console.log('testMode'+childName);
}); //// .then
}); //// .once }
SO, how can I wait my response then let the agent show the result?
How can I include the promise concept in my code ?
You don't show your entire Handler function, but if you're doing async operations (such as reading from the firebase db) you must return the Promise. This is how the Handler Dispatcher knows to wait for the Promise to complete before returning a response to the user.
In your case, it is probably as simple as
return query.once("value")
// etc

Firebase functions returns RangeError at Function.MapValues

I've run into an issue with a firebase function, written in TypeScript for the Node.js environment. I have a function with https-endpoint where the client can send data that needs to be stored in the database. In order to know which objects already has been added to the database, it first reads a path ("lookup") that has a simplified registry of the object (lookup/:objectId/true). Then it makes the values that should be updated at the actual object path and updates these in the database.
The function is as follows:
export const scrapeAssignments = functions.https.onCall((data, context) => {
const htmlString = data.htmlString
// const htmlString = fs.readFileSync(testPath.join(__dirname, "./assignmentListExample.html"), { encoding: 'utf8' })
if (!(typeof htmlString === 'string') || htmlString.length === 0) {
throw new functions.https.HttpsError('invalid-argument', 'The function must be called with one argument "htmlString"');
}
const userId = getUserIdFromCallableContext(context)
console.log("userId", userId)
let newAssignments: ScrapedAssignment[] = []
try {
newAssignments = parseAssignment(htmlString)
} catch (e) {
const error = <Error>e
throw new functions.https.HttpsError('not-found', 'parsing error: ' + error.message)
}
return admin.database().ref("lookup").child(userId).child("assignments")
.once("value", lookupSnapshot => {
const oldAssignmentsLookup = lookupSnapshot.val() || {}
const newAssignmentsLookup = makeLookup(newAssignments)
// 1. Create update values for scraped assignment data
let scrapedAssignmentUpdateValues = newAssignments.reduce((prev, current) => {
const prefixed = prefixObject(current.id + "/", current)
return { ...prev, ...prefixed }
}, {})
// 2. Use the diff from the two lookups to find old assignments to delete
const removeAssignmentsValues = {}
Object.keys(oldAssignmentsLookup).forEach(assignmentId => {
if (isUndefined(newAssignmentsLookup[assignmentId]))
removeAssignmentsValues[assignmentId] = null
})
// 3. Add other user values to newly found assignments
Object.keys(newAssignmentsLookup).forEach(assignmentId => {
if (isUndefined(oldAssignmentsLookup[assignmentId])) {
const doneKey = assignmentId + "/done"
scrapedAssignmentUpdateValues[doneKey] = false
}
})
const combinedValues = { ...scrapedAssignmentUpdateValues, ...removeAssignmentsValues }
return admin.database().ref("userAssignments").child(userId).update(combinedValues)
}).catch(reason => {
throw new functions.https.HttpsError('internal', 'Database reason: ' + reason)
})
})
I see that the data is written to the right place and everything seems to go as expected, except that when I call the function from an iOS app, It returns an "Internal"-error
When I check the function logs in the cloud console, I see the following error:
assignment-scrapeAssignments uolk47opctna Unhandled error RangeError:
Maximum call stack size exceeded at Function.mapValues
(/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13395:23)
at encode
(/user_code/node_modules/firebase-functions/lib/providers/https.js:204:18)
at
/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
at
/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
at baseForOwn
(/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
at Function.mapValues
(/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
at encode
(/user_code/node_modules/firebase-functions/lib/providers/https.js:204:18)
at
/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13400:38
at
/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4925:15
at baseForOwn
(/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:3010:24)
at Function.mapValues
(/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13399:7)
All I can read out of this, is that it's an "RangeError: Maximum call stack size exceeded"-error, and something happens at Function.mapValues. As I can read from this SO question it seems to be an issue with a reading and writing to the same location at the same time. But I'm quite sure that I'm not doing that here.. Plus everything seems behave like it should, except for the actual error.
When combinedValues is updated, it is an object with ~300 key/value pairs, is that a problem?
Looks like your function run out of memory, every cloud function has allocated memory to its execution.
You can try to increase the stack size from its default value (256MB) up to 2GB by going to:
Functions-> Dashboard, then go to your problematic function and click on the right menu "Detailed usage stats":
then on your function details in google cloud dashboard click edit:
then increase the value of "memory allocated" to 2GB (or lower sufficient value):
note: you should keep in mind that when your data growth you may exceed the highest limit so consider this when querying in the cloud functions

Network adapter failing when using node.js

I'm having this super bizarre problem at work; I've made two small node.js programs that interact with each other via HTTP get and post requests. Program B monitors some text files and sends a post request to Program A anytime the files change (once a minute). After acknowledging that request, Program A then sends a post request to program B, which then writes another set of text files.
The computer that hosts program B, at some (unpredictable) point in the day, just stops getting proper network connection—we'd be unable to use the browser, unable to remote desktop, and the node program also can't communicate, logging with ECONNRESET errors. It can, however, ping other machines in the network and on the internet. We thought there was a problem with the network card so we actually switched the machine which runs Program B and we still have the same problem.
We've noticed this only happens when Node.js is running, and is actively sending https requests to and from program A. A restart is the only solution we've found that sets things back to normal.
Our next idea was to install Wireshark and see what's up. The first thing that we noticed is this on the 'info' field:
3000→53550 [RST, ACK] Seq=2 Ack=1 Win=0 Len=0
It happens once every minute, and seems to be from the machine hosting Program A. Is this normal behavior? (Wireshark highlights it in red) Network communication is still normal at this point.
Eventually, it zero's out a TCP window and then things get worse:
We started to see duplicate acknowledgements and lots of retransmissions being sent:
and then finally the TCP window being full, and then reset:
Network communication fails at this point (except being able to ping).
I'm totally lost. I don't know whether this is a problem with my programming, or with node's implementation of network tools, or whether it's a driver / hardware issue, or a kernel issue.
We're running Windows 7 on both machines. Node 4.4.1
Any help or advice on what this could be would be really appreciated.
EDIT
Here's the some code snippets regarding the sending and receiving of information in Program B (I'm using Express.js) .
Receiving:
app.post('/eton_call', function (req, res){
logger.info("POST REQUEST: eton_call") //using winston.js to log things
reqCalls_writer.write_file(req.body); //writes the text file in a certain format
res.sendStatus(201);
})
app.post('/USERPRUN_call', function (req, res){
logger.info("POST REQUEST: userprun_call")
userPrun_writer.write_file(req.body);
res.sendStatus(201);
})
Sending: (they all use this prototyped function. The argument, snapshot, is some JSON)
Eton_file_sync.prototype.send_snapshot = function(snapshot) {
logger.info('sending snapshot');
var post_options = {
host: config.fex_server.host,
port: config.fex_server.port,
path: this.post_uri,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': snapshot.length
}
};
var post_req = http.request(post_options, function(res) {
logger.info("STATUS: " + res.statusCode);
res.setEncoding('utf8');
res.on('data', function (chunk) {
logger.info('Response: ' + chunk);
});
});
post_req.on('error', function(e){
logger.error('Snapshot not sent. Please ensure connectivity to fex-server.js. This snapshot will be lost. Error Message: ' + e.message);
})
post_req.write(snapshot);
post_req.end();
}
Here's the code for writing files
Eton_asc_writer.prototype.write_file = function (data_arr){
logger.info("writing file");
var buffer_data = '';
data_arr.forEach(function (data_element, index, array){
for (prop in data_element){
_.find(this, function(template_element){//finds the template_element with the correct descriptions
return template_element.description == prop; //^
}).datum = data_element[prop];//copies over datum to template element
}
//finds the first then second then third.. nth field.
for (var field_order = 1; field_order < this.length; field_order++){
var current_field = _.find(this, function(template_element){
return template_element.field_order == field_order;
});
if (!current_field.datum && (current_field.datum != 0)){
current_field.datum = "";
}
var required_padding_amount = current_field.required_length - current_field.datum.toString().length;
assert(required_padding_amount >= 0, "invalid length on " + current_field.description);
//assert(current_field.type == typeof current_field.datum, "datum types don't match");
for (var padding = ''; padding.length < required_padding_amount;)
padding += ' ';
if (current_field.type == "string"){
current_field.padded_datum = current_field.datum + padding + ';';
}
else {
current_field.padded_datum = padding + current_field.datum + ';';
}
buffer_data += current_field.padded_datum;
}
buffer_data += '\r\n';//buffer newline
}, this.template_in_use);
//console.log(buffer_data);
write_buffer = new Buffer(buffer_data, 'utf8');
var file = fs.createWriteStream(this.filename);
file.write(write_buffer);
file.end();
}
For Program A, the only post requests that would be happening at the time come from this: (req_calls is an array of objects that share the same key/value pairs)
function exportReqCalls(req_calls){
if (req_calls.length == 0){
return;
}
exported_req_calls = JSON.stringify(req_calls);
var post_options = {
host: config.eton_agent.host,
port: config.eton_agent.port,
path: '/eton_call',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': exported_req_calls.length
}
};
var post_req = http.request(post_options, function(res) {
logger.info("STATUS: " + res.statusCode);
res.setEncoding('utf8');
res.on('data', function (chunk) {
//console.log('Response: ' + chunk);
});
});
post_req.on('error', function(e){
logger.error('ReqCall not sent. Please ensure connectivity to eton-agent.js. Error Message: ' + e.message);
});
post_req.write(exported_req_calls);
post_req.end();
}

Resources