I have been using the code from github sandeepmistry/node-robosmart. Specifically I am doing this:
var async = require('async');
var RoboSmart = require('./index');
var found =0;
RoboSmart.discover(function(roboSmart) {
async.series([
function(callback) {
console.log('connect');
roboSmart.connect(callback);
},
function(callback) {
console.log('discoverServicesAndCharacteristics');
roboSmart.discoverServicesAndCharacteristics(callback);
},
function(callback) {
roboSmart.getLightName(function(lightName) {
console.log('light name = ' + lightName);
if(lightName = 'XXXX'){
found=1;
console.log(found);
}
callback();
});
},
function(callback) {
console.log('disconnect');
roboSmart.disconnect(callback);
}
],
function() {
process.exit(0);
});
});
The code works great and I am able to do other stuff. What I am having trouble with is using the RoboSmart.discoverAll(timeout, callback(devices)); // Returns array of devices discovered within command.
When I use this code:
var async = require('async');
var RoboSmart = require('./index');
var found =0;
RoboSmart.discoverAll(2000,function(devices) {
async.series([
function(callback) {
}
],
function() {
process.exit(0);
});
});
~
It Hangs. Can someone help me with using this function?
Related
I am creating a chess engine using nodejs in lambda but due to asynchronous call it showing timeout error on lambda every time. This is just partial part of the function. It is working fine on local nodejs console but not on the lambda. Please someone suggest something as I am new to this.
var chessjs = require('./chess');
var engine = require('uci');
var uciengine = new engine(process.env['LAMBDA_TASK_ROOT'] + '/stockfish');
var fs = require("fs");
var match;
function moveEngine() {
var curfen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
var depth = '20';
uciengine.runProcess().then(
() => {
console.log("Started.");
return uciengine.uciCommand();
}
).then(
() => {
console.log("Is Ready?");
return uciengine.isReadyCommand();
}
).then(
() => {
console.log("New game.");
return uciengine.uciNewGameCommand();
}
).then(
() => {
console.log("Setting position.");
return uciengine.positionCommand(curfen);
}
).then(
() => {
console.log('Starting position set');
console.log('Starting analysis');
return uciengine.depthLimitedGoCommand(depth, (info) => {
});
}
).then((bestmove) => {
console.log('Bestmove: ');
console.log(bestmove);
return uciengine.quitCommand();
}).then(() => {
console.log('Stopped');
response.sessionAttributes = {};
context.succeed(response);
}).done();
}
async call code
var chessjs = require('./chess');
var engine = require('uci');
var async= require('async');
var uciengine = new engine('/var/task/stockfish');
var fs = require("fs");
var match;
function moveEngine() {
var curfen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
var depth = '20';
async.auto({
runProcess: function(next, results) {
uciengine.runProcess(next,results);
},
checkUiEngineReady:['runProcess',function(next,results) {
uciengine.checkUiEngineReady(next,results);
}],
newGameCommand:['checkUiEngineReady',function(next,results) {
uciengine.newGameCommand(next,results);
}],
position:['newGameCommand',function(next,results) {
uciengine.positionCommand(curfen,next,results);
}],
godepth:['position',function(next,results) {
uciengine.depthLimitedGoCommand(depth,next,results);
}]
}, function(err, response) {
if (err) {
next(err);
} else {
console.log(response);
uciengine.quitCommand();
context.succeed(response);
}
});
}
moveEngine();
async call is giving the same error like before and i think it is probably wrong.
You can handle the Async call in Lambda using async npm module which is a utility module to handle asynchronous programming in Nodejs.
You can install the async module with npm install --save async.
async.auto function will be useful to manage the above call.
Here is an example through which you can manage your code.
async.auto({
runProcess: function(next, results) {
runProcess(next,results);
},
checkUiEngineReady:['runProcess',function(next,results) {
checkUiEngineReady(next,results);
}],
newGameCommand:['checkUiEngineReady',function(next,results) {
newGameCommand(next,results);
}]
}, function(err, response) {
if (err) {
next(err);
} else {
context.succeed(response);
}
});
Thanks
I have an action where I need to update MongoDB entry including _id field, which requires deleting old entry and making a new one, here is server side:
exports.update = function(req, res, next){
var outcome = [];
outcome.previousId = req.params.id;
outcome.newId = req.body.name;
var getPreviousRecord = function(callback) {
req.app.db.models.AccountGroup
.findOne({ _id: req.params.id })
.lean()
.exec(function(err, accountGroups) {
if (err) {
return callback(err, null);
}
outcome.accountGroups = accountGroups;
return callback(null, 'done');
});
};
var makeNewRecord = function(callback) {
var permissions = outcome.accountGroups.permissions;
var fieldsToSet = {
_id: outcome.newId.toLowerCase(),
name: outcome.newId,
permissions: permissions
};
req.app.db.models.AccountGroup
.create(fieldsToSet, function(err, record) {
if (err) {
return callback(err, null);
}
outcome.record = record;
return callback(null, 'done');
});
};
var deletePreviousRecord = function() {
req.app.db.models.AccountGroup
.findByIdAndRemove(outcome.previousId)
.exec(function(err) {
if (err) {
return next(err);
}
res.redirect('admin/account-groups/' + outcome.newId + '/');
});
};
var asyncFinally = function(err) {
if (err) {
return next(err);
}
};
require('async').series([getPreviousRecord, makeNewRecord, deletePreviousRecord], asyncFinally);
};
It works fine, but I can't make this work normally on the front-end, it returns me both old route and a new route, for example:
PUT /admin/account-groups/customers22/admin/account-groups/Customers2233/ 404 213.749 ms - 31
where customers22 is old _id and customers2233 is new _id. If I navigate from another page to new entry it gets route normally.
On client side:
(function() {
'use strict';
app = app || {};
app.Details = Backbone.Model.extend({
idAttribute: '_id',
defaults: {
success: false,
errors: [],
errfor: {},
name: ''
},
url: function() {
return '/admin/account-groups/'+ app.mainView.model.id +'/';
},
parse: function(response) {
if (response.accountGroup) {
app.mainView.model.set(response.accountGroup);
delete response.accountGroup;
}
return response;
}
});
app.DetailsView = Backbone.View.extend({
el: '#details',
events: {
'click .btn-update': 'update'
},
template: Handlebars.compile( $('#tmpl-details').html() ),
initialize: function() {
this.model = new app.Details();
this.syncUp();
this.listenTo(app.mainView.model, 'change', this.syncUp);
this.listenTo(this.model, 'sync', this.render);
this.render();
},
syncUp: function() {
this.model.set({
_id: app.mainView.model.id,
name: app.mainView.model.get('name')
});
},
render: function() {
this.$el.html(this.template( this.model.attributes ));
for (var key in this.model.attributes) {
if (this.model.attributes.hasOwnProperty(key)) {
this.$el.find('[name="'+ key +'"]').val(this.model.attributes[key]);
}
}
},
update: function() {
this.model.save({
name: this.$el.find('[name="name"]').val()
});
}
});
app.MainView = Backbone.View.extend({
el: '.page .container',
initialize: function() {
app.mainView = this;
this.model = new app.AccountGroup( JSON.parse( unescape($('#data-record').html()) ) );
// ...
app.detailsView = new app.DetailsView();
}
});
$(document).ready(function() {
app.mainView = new app.MainView();
});
}());
It probably requires to trigger both model.save and model.destroy or prevent URL being used. Any advice on how to do it is appreciated, thank you.
Edit
Just a typo mistake here that is not related to the question, recklessly checking routes, see as cancelled
I believe the problem is here:
res.redirect('admin/account-groups/' + outcome.newId + '/');
That's a relative path so it'll be appended onto the current URL. I suspect you want something like this:
res.redirect('/admin/account-groups/' + outcome.newId + '/');
I am trying to make an api endpoint for data coming from dynamoDB. I believe that I have everything connected but when I run postman to check the api (api/db) it doesn't recognize the functions from the db.js in the db.js (for routes). I have run a test on api/test and am getting the information back. Here is the code from both files:
1. This scans the database and I'm trying to export it to another file.
var AWS = require('aws-sdk');
var params = {
TableName : "iotbuttonsn",
//KeyConditionExpression: "serialNumber =:serialNumber",
//ExpressionAttributeValues: {
// ":serialNumber":"*"
//},
ScanIndexForward: false,
Limit: 3,
Select: 'ALL_ATTRIBUTES'
};
AWS.config.update({
region: "us-east-1",
endpoint: "https://dynamodb.us-east-1.amazonaws.com"
});
var docClient = new AWS.DynamoDB.DocumentClient();
var getDatabase = (function(){
return {
scanDB: function(){
docClient.scan(params, onScan);
var onScan = function(err, data){
if (err) {
console.log(err.message);
} else {
console.log('scan success');
len = data.Items.length;
for (n=0; n<len; n++) {
clickTypes[n] = data.Items[n].payload.clickType;
serialNums[n] = data.Items[n].serialNumber;
}
}
};
},
clickTypes: [],
serialNums: []
};
})();
module.exports = getDatabase;
2. This is where I'm trying to input but db.scanDB() isn't working:
var router = require('express').Router();
var db = require('../routes/db.js');
router.get('/', function(req, res){
db.scanDB();
buttons =
[
iot_buttonOne = {
serialNum: db.serialNum[0],
clickType: db.clickTypes[0]
},
iot_buttonTwo = {
serialNum: db.serialNum[1],
clickType: db.clickTypes[1]
}
]
.then(
function scanSuccess(data){
res.json(data);
},
function scanError(err){
res.send(500, err.message);
}
);
});
module.exports = router;
Change your db.scan() function to properly return an asynchronous result:
// db.js
module.exports = {
scanDB: function(cb){
docClient.scan(params, function(err, data) {
var clickTypes = [], serialNums = [];
if (err) {
console.log(err.message);
cb(err);
} else {
console.log('scan success');
len = data.Items.length;
for (n=0; n<len; n++) {
clickTypes[n] = data.Items[n].payload.clickType;
serialNums[n] = data.Items[n].serialNumber;
}
cb(null, {clickTypes, serialNums});
}
});
}
};
Then, when you use it:
var db = require('../routes/db.js');
db.scanDB(function(err, data) {
if (!err) {
// data.clickTypes
// data.serialNums
} else {
// process error
}
});
It really does not good to put the scanDB result on the DB object the way you were doing because there was no way for the caller to know when the asynchronous operation was done. So, since you have to provide some notification for the caller when the async operation is done (either via callback or promise), you may as well just pass the results there too.
Also, the .then() handler in your router.get(...) handler does not belong there. I don't know why it's there at all as there are no promises involved in the code you show. Perhaps a cut/paste error when creating the question?
Note, I removed the IIFE from your getDatabase() definition since there was no benefit to it other than a little more complicated code.
I'm having a small issue, playing around with module patterns. I'm trying to attach an eventemitter to my library, but it doesn't seem to work and I get :
cmd.on('message',function(msg){
^
TypeError: undefined is not a function
My lib looks like :
var util = require('util');
var EventEmitter = require("events").EventEmitter;
var TestLib = function() {
var self = this;
function sendRandom(cb){
self.emit('message','whatever');
cb(null,0);
}
return {
init: function(cb) {
console.log('init');
cb(null);
},
run: function(params,cb){
console.log('running ',params);
sendRandom(function(err,res){
if(err){
cb(new Error(err));
}else{
cb(null,res);
}
});
},
close: function(cb) {}
};
};
util.inherits(TestLib, EventEmitter);
module.exports = TestLib;
And I call it as such :
var cmd = require(__dirname+'/bin/testlib.js')();
cmd.on('message',function(msg){
log(msg);
});
cmd.init(function(err){
if(err){
log(err);
}else{
cmd.run(line,function(err,res){
if(err){
log(err);
}else{
log(res);
}
});
}
});
I'm sure I'm overlooking something simple, but what?
see whether the example below helps you.
testLib.js
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function TestLib(ms) {
var self = this;
EventEmitter.call(this);
this.random = function() {
//emitting 'random' event randomly
var ms = Math.random() * 100000 % 3000;
console.log('emitting random event in ' + ms + ' milliseconds');
setTimeout(function() {
self.emit('random', ms);
self.random();
}, ms);
return self;
}
}
util.inherits(TestLib, EventEmitter);
module.exports = TestLib;
test.js
var TestLib = require('./testLib');
new TestLib()
.random()
.on('random', function(ms) {
console.log('random event emitted after ' + ms + ' milliseconds');
});
to run it, execute node test.js
So I have this basic CRUD Todo app that I've made with AngularJS. I then thought I wanted to spice it up with some Socket.IO to make it a real time web app. However, I'm having some problems getting it to work correctly.
Setup:
Yeoman (bower+grunt)
AngularJS
RequireJS
NodeJS + MongoDB
Socket.IO
My 'grunt server' runs on localhost:9000 whereas my NodeJS/MongoDB/Socket.IO server runs on localhost:4711
What works with Socket.IO at the moment is creating and deleting a todo, but I can't seem to figure out how to update my todos. Something I thought would be quite easy.
Here is the codez.
Socket.js:
var io = require('socket.io');
exports.initialize = function(server) {
io = io.listen(server);
io.sockets.on('connection', function(socket) {
socket.on('message', function(message) {
message = JSON.parse(message);
socket.get('deletedTodo', function(err, nickname) {
socket.broadcast.send(JSON.stringify(message));
socket.send(JSON.stringify(message));
});
});
socket.on('delete_todo', function(data) {
socket.set('deletedTodo', data.title, function() {
socket.emit('todo_delete', data);
socket.broadcast.emit('todoDeleted', data);
});
});
socket.on('update_todo', function(data) {
socket.broadcast.emit('todoUpdated', data);
})
});
}
And here is my client side codez.
Services.js:
/*global define*/
define(['angular'], function(angular) {
'use strict';
return angular.module('services', [])
.factory('Todo', function($resource) {
//var baseUrl = 'http://designit-todo.eu01.aws.af.cm/api/todos/:id';
var baseUrl = 'http://localhost:port/api/todos/:id';
return $resource(baseUrl,
{port: ':4711', id: '#_id'}, {
'update': {method:'PUT'},
'delete': {method:'DELETE', isArray: true}
});
})
.factory('socket', function($rootScope) {
var socket = io.connect('http://localhost:4711');
return {
on: function(eventName, callback) {
socket.on(eventName, function() {
var args = arguments;
$rootScope.$apply(function() {
callback.apply(socket, args);
})
});
},
emit: function(eventName, data, callback) {
socket.emit(eventName, data, function() {
var args = arguments;
$rootScope.$apply(function() {
if (callback) {
callback.apply(socket, args);
}
});
});
},
send: function(eventName, data, callback) {
socket.send(eventName, data, function() {
var args = arguments;
$rootScope.$apply(function() {
if (callback) {
callback.apply(socket, args);
}
});
});
}
}
});
});
Controllers.js:
/*global define*/
define(['angular', 'services/services'], function(angular) {
'use strict';
return angular.module('controllers', ['services'])
.controller('Todos', ['$scope', '$resource', 'Todo', '$location', 'socket', function($scope, $resource, Todo, $location, socket) {
// Grab all todos.
$scope.todos = Todo.query();
socket.on('message', function(data) {
// Grab all todos when new added via socket.
$scope.todos = Todo.query();
$scope.todos.push(data);
});
// Complete/update todo.
$scope.todoCompleted = function(todo) {
todo.$update();
socket.emit('update_todo', todo);
}
socket.on('todoUpdated', function(todo) {
// Update on all connected clients.
console.log(todo);
});
$scope.removeTodo = function(todo) {
var index = $scope.todos.indexOf(todo);
socket.emit("delete_todo", JSON.stringify(index));
$scope.todos.splice(index, 1);
todo.$remove();
}
socket.on('todoDeleted', function(index) {
$scope.todos.splice(index, 1);
});
}])
.controller('Single', ['$scope', '$resource', '$routeParams', 'Todo', '$timeout', '$location', function($scope, $resource, $routeParams, Todo, $timeout, $location) {
// Grab just a single todo
$scope.todo = Todo.get({ id: $routeParams.id });
// Throttle the update PUT request
var saveTimeout;
$scope.save = function() {
$timeout.cancel(saveTimeout);
saveTimeout = $timeout(function() {
// Save the todo and then update the scope
$scope.todo.$update(function(updated_todo) {
$scope.todo = updated_todo;
});
}, 1000);
};
}])
.controller('Add', ['$scope', '$resource', 'Todo', '$location', 'socket', function($scope, $resource, Todo, $location, socket) {
$scope.todo = new Todo({});
$scope.save = function() {
if ($scope.todo.title) {
$scope.todo.$save(function(data) {
console.log(data);
socket.send(JSON.stringify(data));
$location.path('/');
});
}
}
}]);
});
So my problem is within this piece of code:
// Complete/update todo.
$scope.todoCompleted = function(todo) {
todo.$update();
socket.emit('update_todo', todo);
}
socket.on('todoUpdated', function(todo) {
// Update on all connected clients.
console.log(todo);
});
When I console.log(todo), I get the todo, but I'm able to do a "todo.$update" on it. I've also tried something like:
socket.on('todoUpdated', function(todo) {
var thisTodo = Todo.get({id: todo._id});
console.log(thisTodo);
});
But as soon as I try to do thisTodo.$update() I get an error:
PUT http://localhost:4711/api/todos 404 (Not Found) :4711/api/todos:1
What am I doing wrong? And please correct me if I'm doing anything wrong within my code. I'm still fairly new to AngularJS and Socket.IO.
I found another solution, but not sure if it's the right way to do it:
socket.on('todoUpdated', function(updated_todo) {
for (var i in $scope.todos) {
if ($scope.todos[i]._id == updated_todo._id) {
$scope.todos[i] = updated_todo;
}
}
});
So in the Todos controller I have the $scope.todos which holds all todos. I then loop through all these, find a match on the id and sets the found todo to the newly updated todo.
If there's a better way to do it, please do tell me :)