IBM Bluemix IotFoundation : Iotfclient is offline. Retrying connection - node.js

I am trying to follow the IBM Bluemix course on Coursera.
My steup: A raspberry pi as a device (client) which is connected as a registered client to Watson IoT Platform. It's emitting a continuous stream of random numbers per second.
I have deployed my custom Nodejs app (code that is available on Coursera) on IBM Bluemix.
var express = require('express');
var app = express();
var Client = require('ibmiotf');
var appConfig;
var serverPort = process.env.VCAP_APP_PORT || 3000;
var serverHost = process.env.VCAP_APP_HOST || 'localhost';
if (process.env.VCAP_SERVICES) {
var env = JSON.parse(process.env.VCAP_SERVICES);
appConfig = {
'org' : env["iotf-service"][0].credentials.org,
'id' : 'dna-nodeserver',
'auth-key' : env["iotf-service"][0].credentials.apiKey,
'auth-token' : env["iotf-service"][0].credentials.apiToken
}
} else {
appConfig = require('./application.json');
}
var responseString = 'Hello Coursera';
var appClient = new Client.IotfApplication(appConfig);
app.get('/', function(req, res) {
res.send(responseString);
});
var server = app.listen(serverPort, serverHost, function() {
var host = server.address().address;
var port = server.address().port;
console.log('Listening at http://%s:%s', host, port);
appClient.connect();
appClient.on('connect', function() {
appClient.subscribeToDeviceEvents('raspberrypi');
});
appClient.on("error", function (err) {
console.log("Error : "+err);
});
appClient.on('deviceEvent', function(deviceType, deviceId, eventType, format, payload) {
responseString = "Device Event from :: "+deviceType+" : "+deviceId+" of event "+eventType+" with payload : "+payload;
console.log("Device Event from :: "+deviceType+" : "+deviceId+" of event "+eventType+" with payload : "+payload);
});
});
The problem that I am facing is shown is the screenshot below:
Error
Also, since I am receiving continuous events from the raspberry pi... the webpage (served by res.send(responseString)) should show the changes automatically ...without the need for me to manually refresh the page. But this does not seem to happen.
Any help would be appreciated. Thanks!

You probably have multiple applications listening to events. Stop the previous Node Red Application on Bluemix. Instead only run the Nodejs app shown above.

Old thread, but thanks to Alexei for pointing me in the right direction.
In my case the same behaviour testing a local version of an event broker when the production version is still running in IBM Cloud.
You can have multiple listeners in this way if you generate an additional API key, save both sets of credentials, and check a suitable environment variable to see which set to apply.
In my app, I wrap these in a function in node:
function getEventBrokerCredentials(siteCode) {
var codeToCredentials = {
'REMOTE_BROKER': {
'orgId': 'abcde',
'id': 'ThisIsABroker',
'apikey': '111111111111111',
'authtoken': '2222222222222'
},
'LOCAL_BROKER': {
'orgId': 'abcde',
'id': 'ThisIsALocalBroker',
'apikey': '3333333333333333',
'authtoken': '4444444444444'
}
};
return codeToCredentials[siteCode];
}
var brokerCredentials = getEventBrokerCredentials(process.env.BROKER_HOST || 'REMOTE_BROKER');
var appClient = new IOTClient.IotfApplication({
'org': brokerCredentials.orgId,
'id': brokerCredentials.id,
'auth-key': brokerCredentials.apikey,
'auth-token': brokerCredentials.authtoken
});
and then use
BROKER_HOST=LOCAL_BROKER nodemon
for local testing and development.
There are many variations on this theme of course.

Related

Change issue closing pattern for gitlab user account

I want to close an issue matching the file name pushed with Issue title (My source files are named with unique integers, e.g. 34521.cpp and there are corresponding issues on Gitlab e.g. Problem #34521).
How can I do so?
The default pattern is not suitable as I have 2000+ issues and I do not want to refer issues with the issue ID's each time. I want it to be automated. So I was checking the page :
Change the issue closing pattern.
It says I need to have access to the server where gitlab is installed. Does that mean I cannot change the issue closing pattern for Gitlab cloud's user account hosted at http://gitlab.com ?
You can't define a custom closing pattern on gitlab.com, only on your own hosted gitlab instance. But what you can do is to use webhooks to listen on push events on a remote server. You can then parse the commit messages yourself and take decision on closing issues. You can use Gitlab API to close issue on your server instance (with a hard coded access token)
This can be tested locally using an http tunnel like ngrok
The following nodejs script starts a server serving a /webhook endpoint. This webhook endpoint is called when any push occurs on your repo.
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const to = require('await-to-js').to;
const port = 3000;
const projectId = "4316159";
const accessToken = "YOUR_ACCESS_TOKEN";
const app = express();
app.use(bodyParser.json())
app.post('/webhook', async function(req, res) {
console.log("received push event");
let result, err, closeRes;
for (var i = 0; i < req.body.commits.length; i++) {
for (var j = 0; j < req.body.commits[i].added.length; j++) {
filenameWithoutExt = req.body.commits[i].added[j].split('.').slice(0, -1).join('.');
[err, result] = await to(axios({
url: `https://gitlab.com/api/v4/projects/${projectId}/issues?search=#${filenameWithoutExt}`,
method: 'GET',
headers: {
"PRIVATE-TOKEN": accessToken
}
}));
if (err) {
console.log(err);
} else {
if (result.data.length !== 0) {
//close those issues
for (item in result.data) {
console.log(`closing issue #${result.data[item].iid} with title ${result.data[item].title}`);
[err, closeRes] = await to(axios({
url: `https://gitlab.com/api/v4/projects/${projectId}/issues/${result.data[item].iid}?state_event=close`,
method: 'PUT',
headers: {
"PRIVATE-TOKEN": accessToken
}
}));
if (err) {
console.log(err);
} else {
console.log(`closing status : ${closeRes.status}`);
}
}
} else {
console.log("no issue were found");
}
}
}
}
res.sendStatus(200);
});
app.listen(port, () => console.log(`listening on port ${port}!`))
In the above you need to change the access token value & projectId. Also note that above code will check only added file, you can modify it to include updated or deleted file matching your requirements.
Launch ngrok on port 3000 ngrok http 3000 & copy the given url in integrations sections of your repo :
Now when you add any file it will check for the filename without extension and search all issue with within title #filename_without_extension and close it right away

NodeJS SOAP server

I am new to SOAP and I need to develop a very simple web service in nodejs using SOAP for my college work. I was studying how to do it and the hardest thing to me is to create the wsdl and integrate the soap library to make it work.
I couldn't find any tutorial to create the wsdl or to create the whole SOAP web service in Node. So, what I need is to learn how to do these things.
My work is pretty simple, I just need to have a method that return the top ten students from my MySQL database. Anyone knows any tutorial or content that can help me? I already tried to create the wsdl using Java but didn't work and already made some code for the soap method that needs to be executed.
My server.js:
var express = require('express');
var soap = require('soap');
var mysql = require('mysql');
var xml = require('fs').readFileSync('topten.wsdl', 'utf8');
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: ''
});
var TopTenService = require('./src/services/TopTen')(connection);
var server = express();
server.listen(5488, () => {
soap.listen(server, '/wsdl', TopTenService, xml);
console.log("Servidor Startado!");
});
My TopTen.js:
module.exports = (connection) => {
var topTen = {
TopTen: {
TopTenPort: {
getTopTen = () => {
connection.query('SELECT * FROM `alunos` ORDER BY acertos DESC LIMIT 10', (error, results, fields) => {
if(error){
console.log(error);
}else{
console.log(results);
}
});
}
}
}
};
}
At server.js that line that is reading the file topten.wsdl doesn't work since I don't have that file. I really need some guidance here.. Please, help me!

Alexa Skill works locally but not when testing in the skill developer portal

I am running an Node.js mqtt subscriber server on my raspberry pi that listens for published events by my lambda aws code.The publish event is triggered via an Alexa Skill event.
Example;
"Alexa, tell TV to change to channel 10" - This intent is then recognised by my Lambda code as a ChannelNumberIntent intent which then publishes the correct message with the channel number to my mqtt server on my Raspi. Raspi then does the changing channel logic.
I've run this all locally using the alexa-app-server and it works completely fine. Response from Alexa works and mqtt server receives the correct digits/message packet.
The problem arises when I test using the Alexa skill in the developer skill portal on the test tab. It runs fine, returns a response from the lambda saying message received but the mqtt subscriber never receives the channel digits/message packet? I believe somewhere after hours of puzzling my lambda code is messed up. Here is my code;
LAMBDA AWS CODE
'use strict';
module.change_code = 1;
var Alexa = require('alexa-app');
var skill = new Alexa.app('tvRemote');
var awsIot = require('aws-iot-device-sdk');
var deviceName = "tvRemote";
var _ = require('lodash');
var path = require('path');
var host = "randomletters.iot.us-east-1.amazonaws.com";
//App id is the skill being used.
var app_id = "amzn1.ask.skill.more random letters";
var thingShadows = awsIot.thingShadow({
keyPath: path.join(__dirname, '/Raspi.private.key'),
certPath: path.join(__dirname, '/Raspi.cert.pem'),
caPath: path.join(__dirname, '/root-CA.crt'),
clientId: deviceName,
region: "us-east-1",
});
var reprompt = 'I didn\'t hear a channel, tell me a channel number or name to change to that channel';
skill.launch(function (request, response) {
var prompt = 'To change channel, tell me a channel number.';
response.say(prompt).reprompt(reprompt).shouldEndSession(true);
});
skill.intent('ChannelNumberIntent', {
'slots': {
'CHANNELNUMBER': 'CHANNELID'
},
'utterances': ['{|Change|put} {|the|on} {|channel} {|to} {-|CHANNELNUMBER}']
},
function (request, response) {
var channelNumber = request.slot('CHANNELNUMBER');
if (_.isEmpty(channelNumber)) {
var prompt = 'I didn\'t hear a channel code. Tell me a channel code.';
response.say(prompt).shouldEndSession(true);
return true;
} else {
thingShadows.publish('lambda/channelNumber', channelNumber, function () {
var prompt1 = 'Okay.';
response.say(prompt1).shouldEndSession(false);
return true;
});
return true;
}
}
);
module.exports = skill;
MQTT SERVER
'use strict'
var mqtt = require('mqtt')
var fs = require('fs')
var path = require('path')
var KEY = fs.readFileSync(path.join(__dirname, '/Raspi.private.key'))
var CERT = fs.readFileSync(path.join(__dirname, '/Raspi.cert.pem'))
var TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/root-CA.crt'))
var PORT = Corretportnumber
var HOST = 'RASPIHOSTWORDSASDFSDF.iot.us-east-1.amazonaws.com'
var options = {
port: PORT,
host: HOST,
key: KEY,
cert: CERT,
rejectUnauthorized: true,
// The CA list will be used to determine if server is authorized
ca: TRUSTED_CA_LIST
}
var client = mqtt.connect('mqtts://' + HOST, options)
client.subscribe('lambda/channelNumber')
client.on('connect', function () {
console.log('Connected')
})
client.on('message', function (topic, message) {
if (topic === 'lambda/channelNumber') {
// logic.changeChannelCode(message);
console.log(message.toString());
}
})
Obviously hid host and port numbers for reasons

Long running Node.js service to continuously make http requests

I'm beginning work on my first Node.js application and running into memory leak issues that i cannot pin down. I want the app to act as service in a way that continually runs and polls and endpoint. I think I may be missing something here. The idea of the project is to have a node application continuously make http requests to an Arduino board i have connected to my network with a web server on it. The networked board responds to the requests with some JSON or XML representing the state of the sensors attached to it. The idea of the node app is to log then emit sensor changes that will eventually be consumed by another electron project.
The node app is currently broken into a couple modules:
proxy: make the http calls to the different endpoints on arduino web server:
var http = require('http'),
KeepAliveAgent = require('keep-alive-agent');
var controllerRequestOpts = {};
function send(path, cb){
var response = '';
//build the request
var request = controllerRequestOpts;
request.path = path;
//make the call to the controller
http.get(request, function(res){
res.on('data', function(chunk){
response += chunk;
});
res.on('end', function(){
cb(null, response);
});
})
.on('error',function(e){
cb(e, null);
});
}
module.exports = function(controllerOptions){
controllerOptions.port = controllerOptions.port || 2222;
controllerRequestOpts = controllerOptions;
controllerRequestOpts.agent = new KeepAliveAgent();
return{
//JSON
queryJson: function(cb){
send('/json', cb);
},
//XML
queryXml: function(cb){
send('/xml', cb);
}
//Additional endpoints
}
}
runner: Loop forever with the interval provided making the proxy calls ot the arduino
var proxy = require('proxy');
var Watcher = require('./watcher');
var timer;
var toUpdate;
function initProxy(controllerParams){
proxy = proxy(controllerParams);
Watcher = new Watcher();
}
function startListening(startOptions){
var query;
//determine the query and callback functions based off configuration
query = startOptions.queryType === 'json'
? proxy.queryJson
: proxy.queryXml;
toUpdate = startOptions.queryType === 'json'
? Watcher.updateLatestJson
: Watcher.updateLatestXml;
//Start running and making requests every 15 seconds
timer = setInterval(function(){
query(handleResponse);
},startOptions.queryInterval);
}
function handleResponse(err, resp){
if(err){
console.log('ERROR: ' + err);
}
else{
toUpdate.call(Watcher, resp);
}
}
function stopListening(){
clearInterval(timer);
process.exit();
}
var runner = {
connect: function(controllerParams){
initProxy(controllerParams);
},
start: function(startOptions){
startListening(startOptions);
return Watcher;
},
stop: function(){
stopListening();
}
};
module.exports = runner;
I have a "Watcher" module which is just a constructor function that emits the changes back to the calling app which looks like:
var runner = require('./index');
var controllerSettings = {
hostname: '192.168.1.150',
port:2222
}
var startOptions = {
queryType: 'json',
queryInterval: 15000
}
runner.connect(controllerSettings);
var watcher = runner.start(startOptions);
watcher.on('P1Changed', printParams)
Everything is working as expected but as the app runs over time the memory usage for node process constantly increases. I'm wondering if i'm using either the http module incorrectly or if the runner shouldn't be doing a setInterval perhaps. Is there a standard way to run this kind of app as a 'service' and not so much as a 'server'
Continuously send multiple HTTP requests will cause node to create huge TLSWrap objects that the GC will not be able to clear for several minutes.
If you wish to send data to the same host(s) over and over again, you need to open a TCP connection (stream) rather than use HTTP requests that have huge overhead.

Unable to return JSON from REST API with RESTIFY

I'm new to Node.js. I'm trying to create a web server that will 1) serve up static html web pages and 2) provide a basic JSON / REST API. I've been told by my management that I must use RESTIFY (I don't know why). Currently, I have the following:
var restify = require('restify');
var fs = require('fs');
var mime = require('mime');
var ecstatic = require('ecstatic');
var ws = restify.createServer({
name: 'site',
version: '0.2.0'
});
ws.use(restify.acceptParser(server.acceptable));
ws.use(restify.queryParser());
ws.use(restify.bodyParser());
ws.use(ecstatic({ root: __dirname + '/' }));
ws.get('/rest/customers', findCustomers);
ws.get('/', ecstatic({ root:__dirname }));
ws.get(/^\/([a-zA-0-9_\.~-]+\/(.*)/, ecstatic({ root:__dirname }));
server.listen(90, function() {
console.log('%s running on %s', server.name, server.url);
});
function findCustomers() {
var customers = [
{ name: 'Felix Jones', gender:'M' },
{ name: 'Sam Wilson', gender:'M' },
{ name: 'Bridget Fonda', gender:'F'}
];
return customers;
}
After I start the web server, and I try to visit http://localhost:90/rest/customers/ in my browser, the request is made. However, it just sits there and I never seem to get a response. I'm using Fiddler to monitor the traffic and the result stays as '-' for a long time.
How can I return some JSON from this type of REST call?
Thank you
At 2017, the modern way to do this is:
server.get('/rest/customer', (req,res) => {
let customer = {
data: 'sample value'
};
res.json(customer);
});
never worked with ecstatic but i don't think you need a file server for static content since you run restify and return json.
you are not getting a response because you don't terminate with res.send
the following code looks ok
ws.get('/rest/customers', findCustomers);
but try to change the findCustomers function like this
function findCustomers(req,res,next) {
var customers = [
{ name: 'Felix Jones', gender:'M' },
{ name: 'Sam Wilson', gender:'M' },
{ name: 'Bridget Fonda', gender:'F'}
];
res.send(200,JSON.stringify(customers));
}

Resources