Error from Azure IoT Hub library when sending a message - node.js

Im using the Node.JS libraries for Azure IoT Hub to send some telemetry data, and intermittently I get the following error thrown from the libraries.
Unhandled rejection TypeError: Cannot read property 'on' of undefined
at C:\Source\Messenger\app.js:156:17
at Amqp. (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:157:17)
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:54:19
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:84:17
at tryCatcher (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\util.js:11:23)
at Promise._settlePromiseFromHandler (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:489:31)
at Promise._settlePromise (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:546:18)
at Promise._settlePromise0 (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:591:10)
at Promise._settlePromises (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:670:18)
at Async._drainQueue (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:129:16)
at Async._drainQueues (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:139:10)
at Immediate.Async.drainQueues [as _onImmediate] (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:16:14)
At the moment im running my scripts through forever so it recovers when the error is generated.
Has anyone else had this issue and managed to resolve it ?
My code looks like as follows
azureClient = azureDevice.Client.fromConnectionString(connectionString, azureDevice.Amqp);
var message = new azureDevice.Message(JSON.stringify('TEST MESSAGE'));
azureClient.sendEvent(message, function (err) {
if (err != null) {
Configure();
}
});

For this issue, I recommend you can use the AMQPWS or HTTP transport to send and receive messages.
Please refer to my steps to achieve to send and receive the message:
Firstly, we should create a device and get the device id and SAS. After created the IOT hub on Azure new portal, I ran those command on node.js command line:
create IOT hub on new portal.
npm install -g iothub-explorer
iothub-explorer HostName=****.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=****/****= create mydevice --connection-string
I got the result as following:
Created device mydevice
-
deviceId: mydevice
generationId: 635881160181557968
etag: MA==
connectionState: Disconnected
status: enabled
statusReason: null
connectionStateUpdatedTime: 0001-01-01T00:00:00
statusUpdatedTime: 0001-01-01T00:00:00
lastActivityTime: 0001-01-01T00:00:00
cloudToDeviceMessageCount: 0
authentication:
SymmetricKey:
primaryKey: ****/****=
secondaryKey: ****/****=
-
connectionString: HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=
Secondly, I installed the SDK on node.js project, the folder structure is same as this picture:
Thirdly, I run this code on my project:
var device = require('azure-iot-device');
var connectionString = 'HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=';
var client = device.Client.fromConnectionString(connectionString,device.AmqpWS);
setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var data = JSON.stringify({ deviceId: 'mydevice', windSpeed: windSpeed });
var message = new device.Message(data);
message.properties.add('myproperty', 'myvalue');
console.log("Sending message: " + message.getData());
client.sendEvent(message, printResultFor('send'));
}, 1000);
client.getReceiver(function (err, receiver) {
receiver.on('message', function (msg) {
console.log('Id: ' + msg.properties.messageId + ' Body: ' + msg.body);
receiver.complete(msg, function () {
console.log('completed');
// receiver.reject(msg, function() {
// console.log('rejected');
// });
// receiver.abandon(msg, function() {
// console.log('abandoned');
// });
});
receiver.on('errorReceived', function (err) {
console.warn(err);
});
});
});
function printResultFor(op) {
return function printResult(err, res) {
if (err) console.log(op + ' error: ' + err.toString());
if (res) console.log(op + ' status: ' + res);
};
}
it works fine. Also if you used the "Http" transport, it also works fine.
You need use this code:
var client = device.Client.fromConnectionString(connectionString);
This is the reason why I recommend you use the AMQPWS, because of this code in "azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10-transport-ws":
if (this.uri.startsWith('wss')) {
var wsTransport = require('amqp10-transport-ws');
wsTransport.register(amqp10.TransportProvider);
}
If the URI is format with 'wss', it will be register the AMQP transport. But AMQP transport's format is like "amqp://". Hope this helps.

The Azure IoT Hub was by far a preview feature service on Azure. And the Azure IoT device SDK for Node.js is on the fast development.
I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay.
Appreciate your patience.

Related

How do I get around Internal Server Error when testing Azure Function

Does this Nodejs code look right? Is there anything missing?
const mysql = require('mysql');
const fs = require('fs');
var config =
{
host: 'mydemoserver.mysql.database.azure.com',
user: 'myadmin#mydemoserver',
password: 'your_password',
database: 'quickstartdb',
port: 3306,
ssl: {ca: fs.readFileSync("your_path_to_ca_cert_file_BaltimoreCyberTrustRoot.crt.pem")}
};
const conn = new mysql.createConnection(config);
conn.connect(
function (err) {
if (err) {
console.log("!!! Cannot connect !!! Error:");
throw err;
}
else {
console.log("Connection established.");
readData();
}
});
function readData(){
conn.query('SELECT * FROM inventory',
function (err, results, fields) {
if (err) throw err;
else console.log('Selected ' + results.length + ' row(s).');
for (i = 0; i < results.length; i++) {
console.log('Row: ' + JSON.stringify(results[i]));
}
console.log('Done.');
})
conn.end(
function (err) {
if (err) throw err;
else console.log('Closing connection.')
});
};
This is to go inside an Azure Function that reads data from a Azure for MySQL database.
When I run it inside the Kudu window by just typing node index.js it works
When I try and test it on there Azure Function Test Page it throws a Internal Server Error 500 with the following error message
Unable to determine function entry point. If multiple functions are exported, you must indicate the entry point, either by naming it 'run' or 'index', or by naming it explicitly via the 'entryPoint' metadata property.' Stack: Error: Worker was unable to load function ListBrands: 'Unable to determine function entry point. If multiple functions are exported, you must indicate the entry point, either by naming it 'run' or 'index', or by naming it explicitly via the 'entryPoint' metadata property.' at C:\Program Files (x86)\SiteExtensions\Functions\4.14.0\workers\node\dist\src\worker-bundle.js:2:13853 at t.LegacyFunctionLoader. (C:\Program Files (x86)\SiteExtensions\Functions\4.14.0\workers\node\dist\src\worker-bundle.js:2:14092) at Generator.next () at o (C:\Program Files (x86)\SiteExtensions\Functions\4.14.0\workers\node\dist\src\worker-bundle.js:2:12538) at processTicksAndRejections (node:internal/process/task_queues:96:5)
Thanks in advance
Todd

How to handle ESOCKETTIMEDOUT while getblobtostream() azure storage?

While trying to get all the blobs using getBlobToStream() following error is displayed.How can I handle it?
I also came across "ExponentialRetryPolicyFilter" but not sure how to use it.
So far did not find any code related to it.
blobService.listBlobsSegmentedWithPrefix(containerName, path, null, (err, data) => {
data.entries.forEach(entry => {
var options = {
rangeStart: 0,
rangeEnd: entry.contentLength
};
if (fs.existsSync(fileUploadPath)) {
var sourceFilePath = fileUploadPath + '/' + project.id + '/' + entry.name;
if (!fs.existsSync(sourceFilePath)) {
fs.mkdir(require('path').dirname(sourceFilePath), { recursive: true }, (err) => {
if (err) {
console.log("Failed to mkdir:" + err);
}
blobService.getBlobToStream(containerName, entry.name, fs.createWriteStream(sourceFilePath, { flags: 'a' }), options, (error, data) => {
if (error) {
console.log('getblobtostream error', error)
}
});
});
}
Error:
getblobtostream error Error: read ECONNRESET
at TLSWrap.onStreamRead (internal/stream_base_commons.js:209:20) {
errno: -4077,
code: 'ECONNRESET',
syscall: 'read'
}
getblobtostream error Error: ESOCKETTIMEDOUT
at ClientRequest.<anonymous> (D:\tiger3\Nexus-services\node_modules\request\request.js:816:19)
{
code: 'ESOCKETTIMEDOUT',
connect: false
}
ESOCKETTIMEDOUT is basically network error and it can happen due to poor or unstable network or due to continuous heavy usage. Try to add retry filter on client library side.
You can try use it before getBlobToStream to create blobservice object .
var azure = require('azure-storage');
var retryOperations = new azure.ExponentialRetryPolicyFilter();
var blobService = azure.createBlobService().withFilter(retryOperations)
See azure storage-nodejs ,use-blob-storage. GitHub
References:
ESOCKETTIMEDOUT error · Issue #604 · Azure/azure-storage-node ·
GitHub
Using BlobService.getBlobToStream from javascript client SDK · Issue
· GitHub

How to download outlook attachment through node js

I am using below code to download the Gmail attachments. In windows this is working fine but when I am trying to run this same code in my Linux machine it is giving me an error as below.
Also can anyone help how can I perform the same thing for office outlook. in that I am getting an authentication error
Error :
Downloading attachments for pmgtesting1#gmail.com since 2020-11-25 to files/...
[connection] Connected to host
<= '* OK Gimap ready for requests from 51.103.27.188 l25mb237269790wmj'
=> 'A0 CAPABILITY'
<= '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH'
<= 'A0 OK Thats all she wrote! l25mb237269790wmj'
=> 'A1 LOGIN "pmgtesting1#gmail.com" "pswd****"'
<= '* NO [WEBALERT https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbv-cVj07x6UiZjwizvTzmqYRNNyofoJ8yiGr960BU9t1OKkU83L43n5ocMP2SlhJ3MqWkb04Wj4ye1XxDbTSALJhCRkQ373HLB_tcH_yHBmmDycIiLGnX3NNETY0QakllRJFVjR] Web login required.'
<= 'A1 NO [ALERT] Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)'
[connection] Ended
[connection] Closed
disconnected from pmgtesting1#gmail.com
Error ----> {
latestTime: undefined,
lastSyncId: 0,
uidvalidity: undefined,
handledIds: [],
errors: [
Error: Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)
at Connection._resTagged (/home/textify/Mail-attachement/node_modules/imap/lib/Connection.js:1488:11)
at Parser.<anonymous> (/home/textify/Mail-attachement/node_modules/imap/lib/Connection.js:193:10)
at Parser.emit (events.js:314:20)
at Parser._resTagged (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:175:10)
at Parser._parse (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:139:16)
at Parser._tryread (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:82:15)
at TLSSocket.Parser._cbReadable (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:53:12)
at TLSSocket.emit (events.js:314:20)
at emitReadable_ (_stream_readable.js:558:12)
at processTicksAndRejections (internal/process/task_queues.js:83:21) {
type: 'no',
textCode: 'ALERT',
source: 'authentication'
}
]
}
NOTE : I have enabled the Less secure app connection
const downloadEmailAttachments = require('download-email-attachments');
const moment = require('moment');
const todaysDate = moment().format('YYYY-MM-DD');
var reTry = 1;
var paraObj = {
invalidChars: /\W/g,
account: `"****#gmail.com":Paswd******#imap.gmail.com:993`,
// all options and params
//besides account are optional
directory: './files',
filenameTemplate: '{filename}',
// filenameTemplate: '{day}-{filename}',
filenameFilter: /.txt?$/,
timeout: 10000,
log: { warn: console.warn, debug: console.info, error: console.error, info:
console.info },
since: todaysDate,
lastSyncIds: ['234', '234', '5345'], // ids already dowloaded and ignored, helpful
//because since is only supporting dates without time
attachmentHandler: function (attachmentData, callback, errorCB) {
console.log(attachmentData);
callback()
}
}
var onEnd = (result) => {
if (result.errors || result.error) {
console.log("Error ----> ", result);
if(reTry < 4 ) {
console.log('retrying....', reTry++)
return downloadEmailAttachments(paraObj, onEnd);
} else console.log('Failed to download attachment')
} else console.log("done ----> ");
}
downloadEmailAttachments(paraObj, onEnd);
const downloadEmailAttachments = require('download-email-attachments');
const moment = require('moment');
const todaysDate = moment().format('YYYY-MM-DD');
var reTry = 1;
var paraObj = {
invalidChars: /\W/g,
account: `"****#gmail.com":Paswd******#imap.gmail.com:993`,
// all options and params
//besides account are optional
directory: './files',
filenameTemplate: '{filename}',
// filenameTemplate: '{day}-{filename}',
filenameFilter: /.txt?$/,
timeout: 10000,
log: { warn: console.warn, debug: console.info, error: console.error, info:
console.info },
since: todaysDate,
lastSyncIds: ['234', '234', '5345'], // ids already dowloaded and ignored, helpful
//because since is only supporting dates without time
attachmentHandler: function (attachmentData, callback, errorCB) {
console.log(attachmentData);
callback()
}
}
var onEnd = (result) => {
if (result.errors || result.error) {
console.log("Error ----> ", result);
if(reTry < 4 ) {
console.log('retrying....', reTry++)
return downloadEmailAttachments(paraObj, onEnd);
} else console.log('Failed to download attachment')
} else console.log("done ----> ");
}
downloadEmailAttachments(paraObj, onEnd);
I got the answer just enable the 2-factor authentication in Gmail and then register your app and use the app password to fetch the email. Note: For the outlook part, I don't have the admin right to generate the app password if you have then this will also work for you Will update with the other solution as soon as I find them

Errors with publishing messages to Amazon Queue using available node js libraries

I am trying to publish messages to Amazon MQ from Node JS and none of the libraries I have tried so far seem to be working.
Library 1:
stomp-client
Code:
var Stomp = require('stomp-client');
var destination = '/topic/{new_topic}';
var client = new Stomp('{prefix}.amazonaws.com',
61614,
'{user}',
'{password}');
client.connect(function(sessionId) {
client.publish(destination, 'Oh herrow');
});
Error with first library:
Emitted 'error' event at:
at StompFrameEmitter.<anonymous> (project_path\node_modules\stomp-client\lib\client.js:236:10)
at StompFrameEmitter.emit (events.js:182:13)
[... lines matching original stack trace ...]
at Socket.Readable.push (_stream_readable.js:219:10)
Library 2:
stompit
Code:
const stompit = require('stompit');
var connectOptions = {
'host': '{prefix}.amazonaws.com',
'port': 61614,
'connectHeaders':{
'host': '/',
'login': '{user}',
'passcode': '{password}',
'heart-beat': '5000,5000'
}
};
stompit.connect(connectOptions, function(error, client) {
if (error) {
console.log('connect error ' + error.message);
return;
}
var sendHeaders = {
'destination': '/topic/{new_topic}',
'content-type': 'text/plain'
};
var frame = client.send(sendHeaders);
frame.write('hello');
frame.end();
});
Error with second library: connect error unexpected end of stream
I am not sure what else I can try but I seem to be stuck here as the error messages are not even verbose plus there isnt a lot of information on this issue online.
Only relevant article I found has no answer on Amazon forum:
https://forums.aws.amazon.com/thread.jspa?messageID=831730&tstart=0
What worked for me to solve this issue was to set ssl connection to true as follows:
const server_options = {
host,
port,
ssl: true,
connectHeaders: {
host: '/',
'accept-version': '1.1',
'heart-beat': '0,0', // no heart beat
login: user,
passcode: pass,
},
};
Port must be set to 61614 for stomp+ssl connection.

Unable to connect to Realm Object Server using NodeJs

I've installed Realm Object Server using the docker container method on a VM on the google cloud platform. The container is running and I am able to connect in a browser and see the ROS page. I am able to connect to it using Realm Studio and add a user.
I have a nodeJS app running locally on a Mac and I'm trying to use that to sign in and write to realm on the server. When I run the app I get an error and the user returned is an empty object. Not sure what I'm doing wrong.
I'm new to NodeJS.
Code:
var theRealm;
const serverUrl = "http://xx.xx.xx.xx:9080";
const username = "xxxx";
const password = "xxxx";
var token = "long-token-for-enterprise-trial";
Realm.Sync.setFeatureToken(token);
console.log("Will log in user");
Realm.Sync.User.login(serverUrl, username, password)
.then(user => {
``
// user is logged in
console.log("user is logged in " + util.inspect(user));
// do stuff ...
console.log("Will create config");
const config = {
schema:[
schema.interventionSchema,
schema.reportSchema
],
sync: {
user: user,
url: serverUrl
}
};
console.log("Will open realm with config: " + config);
const realm = Realm.open(config)
.then(realm => {
// use the realm instance here
console.log("Realm is active " + realm);
console.log("Will create Realm");
theRealm = new Realm({
path:'model/realm_db/theRealm.realm',
schema:[
schema.interventionSchema,
schema.reportSchema
]
});
console.log("Did create Realm: " + theRealm);
})
.catch(error => {
// Handle the error here if something went wrong
console.log("Error when opening Realm: " + error);
});
})
.catch(error => {
// an auth error has occurred
console.log("Error when logging in user: " + error);
});
Output:
Will log in user
Server is running...
user is logged in {}
Will create config
Will open realm with config: [object Object]
TypeError: Cannot read property 'token_data' of undefined
at performFetch.then.then (/pathToProject/node_modules/realm/lib/user-methods.js:203:49)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
TypeError: Cannot read property 'token_data' of undefined
at performFetch.then.then (/pathToProject/node_modules/realm/lib/user-methods.js:203:49)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
Error # user-methods.js:203:49
const tokenData = json.access_token.token_data;
json is:
{ user_token:
{ token: 'xxxxxxxx',
token_data:
{ app_id: 'io.realm.Auth',
identity: 'xxxxxxx',
salt: 'xxxxxxxx',
expires: 1522930743,
is_admin: false } } };
So json.access_token.token_data is undefined but json. user_token.token_data would not be.
I would suggest you to try the ROS connection with realm studio in that u can check logs as well which will help you to fix the error. If your still not able to fix then you can contact Realm support team even they helped me to fix the issue of ROS connection in Xamarin Forms using Docker.

Resources