I have the following node.js code which reads a shapefile based on code from (https://github.com/mbostock/shapefile)
var shp=require('shapefile');
var path="polygons.shp"
var encoding="utf8"
function readRecords(path, encoding) {
return function() {
var callback = this.callback;
shp.read(path, encoding, function(error, header, records) {
callback(error, records);
}); }; };
var rs = readRecords(path,encoding)
console.log(rs)
when I execute the above code I get : undefined
any idea of how do I iterate over such object?
You need to read the header before you move into reading the records. This bit of code logs the entire shapefile to the console:
var shapefile = require( 'shapefile' ),
reader = shapefile.reader( 'polygons' );
var logger = function( error, record ) {
console.log( record );
if( record !== shapefile.end ) reader.readRecord( logger );
}
reader.readHeader( logger );
Related
I am working on a project where I want to follow two separate twitter accounts, and for a specific function to be called when each account tweets. I am using the Twitter API, Node.js and a NPM Module called Twit.
I have it working no problem when one account tweets but not for both of them:
I believe my issue may be here:
var stream = T.stream('statuses/filter', { follow: ( userID1 , userID2 ) });
If I have follow set to just one User it works fine, however with two it will only work with one. Furthermore, it only works with the second in the list so if its: userID1, user ID2 only userID2 will work. If its userID2, userID1 only userID1 will work.
Full code/logic here:
//SetUp info
var Twit = require('twit'); // NPM twit package
var config = require('./config'); // the config file to allow me access Auth Keys etc
var T = new Twit(config);//run config file
//end of setup
var userID1 = 'XXXXXXXXXXX1'; //TwitterAccount1
var userID2 = 'XXXXXXXXXXX2'; //TwitterAccount2
//these two lines set up the twitter API
var stream = T.stream('statuses/filter', { follow: ( userID1 , userID2 ) }); // here seems to be my issue?
stream.on('tweet', function (tweet) {
if (tweet.user.id == userID1 ) { // is tweet.user.id matches UserID1
DoStuff_1(); //call this function
} else if (tweet.user.id == userID2 ) { // if tweet.user.id matches UserID2
DoStuff_2(); // call this function instead
}
});
//Function for userID1
function DoStuff_1(){
console.log("Doing Stuff 1");
}
//Function for userID2
function DoStuff_2(){
console.log("Doing Stuff 2");
}
Any suggestions greatly appreciated!
You can do it all with some stream; simply make an array with the user ids and join them in the follow parameter like below:
var userId = ['XXXXXXXXXXX1','XXXXXXXXXXX2'];
var stream = T.stream('statuses/filter', { follow: userId.join(',') });
By establishing a separate stream for the Second user account it seems to work:
//SetUp info
var Twit = require('twit'); // NPM twit package
var config = require('./config'); // the config file to allow me access Auth Keys etc
var T = new Twit(config);//run config file
//end of setup
var userID1 = 'XXXXXXXXXXX1'; //TwitterAccount1
//these two lines set up the twitter API
var stream = T.stream('statuses/filter', { follow: ( userID1 ) }); // here seems to be my issue?
stream.on('tweet', function (tweet) {
if (tweet.user.id == userID1 ) { // is tweet.user.id matches UserID1
DoStuff_1(); //call this function
}
});
var userID2 = 'XXXXXXXXXXX2'; //TwitterAccount2
//Separate stream for UserID2
var stream = T.stream('statuses/filter', { follow: ( userID2 ) }); // here seems to be my issue?
stream.on('tweet', function (tweet) {
if (tweet.user.id == userID2 ) { // if tweet.user.id matches UserID2
DoStuff_2(); // call this function instead
}
});
//Function for userID1
function DoStuff_1(){
console.log("Doing Stuff 1");
}
//Function for userID2
function DoStuff_2(){
console.log("Doing Stuff 2");
}
Actually working on an automaton project (based on Arduino <-> Serial <-> Raspberry), I seem to be kind of stuck on the serial interface.
Basically, I'm using Express to read/write on some parameter on the arduino by URL in that kind of syntax (http://localhost:3000/parameter/6 or http://localhost:3000/parameter/6/set?value=10).
Since I'm willing to get a simple/short result (as an API), I decided to render a simple json object on each request, there is also no way for me to use post-rendering scripts/frameworks like Socket.io/jQuery/... for this purpose (I'd probably often call those URLs from curl/wget/[other html parsers]).
Now the thing is that there is no problem to write on the port, but for the reading, I'd like to wait for the buffer to be returned from serialport.on('data', function(buffer) { ... }) before rendering the page.
As serialport.on('data', ... ) does seem to be called only once per request, the only way I found for the moment is to redirect to the same page until the buffer has been read, which seem kind of a nasty way of getting things done, also it is incomplete ...
Here's a bit of code to get an idea of the actual logic :
Library :
// -> lib/serial.js - LIBRARY
var SerialPort = require("serialport");
var data = {'state': 0};
var serialPort = new SerialPort(port, {
baudrate: 115200,
parser: SerialPort.parsers.readline('\r\n'),
});
serialPort.on('open', function() {
console.log('Serial port Open');
serialPort.on('data', function(buffer) { data.buffer = buffer, data.state = 1 });
});
function readConfig(cmd, paramNb) {
var cmd = String.fromCharCode(cmd);
var param = String.fromCharCode(paramNb);
if (serialPort.isOpen() == true) {
serialPort.write(cmd + param + '\n', function(err) {
if (err) {
return console.log('Error on write: ', err.message);
}
console.log('message written');
});
}
return data;
};
function writeConfig(cmd, paramNb, value) {
var cmd = String.fromCharCode(cmd);
var param = String.fromCharCode(paramNb);
var value = String.fromCharCode(value);
if (serialPort.isOpen() == true) {
serialPort.write(cmd + param + value + '\n', function(err) {
if (err) {
return console.log('Error on write: ', err.message);
}
console.log('message written');
});
}
};
exports.readConfig = readConfig;
exports.writeConfig = writeConfig;
Route :
// -> parameter.js - ROUTE
var express = require('express');
var router = express.Router();
var serial = require('../../lib/serial');
var sleep = require('sleep');
/* SET Parameter. */
router.get('/:id/set', function(req, res) {
var id = req.params.id;
var value = req.query.value;
serial.writeConfig('b', id, value);
res.json({'result': value, 'id': id});
});
/* GET Parameter. */
router.get('/:id', function(req, res) {
var id = req.params.id;
var buffer = serial.readConfig('a', id);
if (buffer.state != 0) {
res.json({'result': buffer});
}
else {
sleep.usleep(100000);
res.redirect('/api/parameter/' + id); // <- Nasty Bulls**t
}
});
module.exports = router;
The first idea I came up with was to find a synchronous way to read the port so I can call something like this (pseudo-code) :
while (buffer == '') { var buffer = serial.read; }
res.json({buffer});
Anyway thanks everyone.
I have a connector.js file which using which I want to export dbResult object.
(function(){
var Massive = require("massive");
var connectionString = "postgres://postgres:postgres#localhost/postgres";
var db = Massive.connectSync({connectionString : connectionString});
var dbResult ;
db.query("Select * from company", function (err, data) {
dbResult = data;
console.log(data);
});
})(module.exports);
Now in Another file I am trying to get the dbResult and display the data:
var express = require("express");
var app = express();
var connectorObject = require("./Connector.js");
var Massive = require("massive");
app.get("/api/Steves",function(req,res){
res.set("Content-Type","application/json");
res.send(connectorObject.dbResult);
});
app.listen(3000);
console.log("Server Started on port 3000...");
But when I start the URL , not able to see any response .
Am I missing anything here.
What you want to do, is return a function that can be evaluated later for the result:
var Massive = require("massive");
var connectionString = "postgres://postgres:postgres#localhost/postgres";
var db = Massive.connectSync({connectionString : connectionString});
module.exports.getCompanies = function(callback) {
db.query("Select * from company", callback);
}
Then you can access it from your other files as:
var connector = require('./Connector');
connector.getCompanies(function( err, data ) {
if ( err ) return console.error( err );
console.log( data );
});
I've been able to successfully write binary data (an image) to MongoDB in Node.js. However I can't find clear documentation on how to read it back.
Here's how I'm writing the image to MongoDB:
var imageFile = req.files.myFile;
var imageData = fs.readFileSync(imageFile.path);
var imageBson = {};
imageBson.image = new db.bson_serializer.Binary(imageData);
imageBson.imageType = imageFile.type;
db.collection('images').insert(imageBson, {safe: true},function(err, data) {
I'd appreciate any pointers on reading the image from Mongo using Node. I'm assuming there's a function like "db.bson_deserializer...". Thanks!
Found the answer:
var imageFile = req.files.myFile;
fs.exists(imageFile.path, function(exists) {
if(exists)
{
console.log("File uploaded: " + util.inspect(imageFile));
fs.readFile(imageFile.path, function(err, imageData) {
if (err) {
res.end("Error reading your file on the server!");
}else{
//when saving an object with an image's byte array
var imageBson = {};
//var imageData = fs.readFileSync(imageFile.path);
imageBson.image = new req.mongo.Binary(imageData);
imageBson.imageType = imageFile.mimetype;
console.log("imageBson: " + util.inspect(imageBson));
req.imagesCollection.insert(imageBson, {safe: true},function(err, bsonData) {
if (err) {
res.end({ msg:'Error saving your file to the database!' });
}else{
fs.unlink(imageFile.path); // Deletes the file from the local disk
var imageBson = bsonData[0];
var imageId = imageBson._id;
res.redirect('images/' + imageId);
}
});
}
});
} else {
res.end("Oddly your file was uploaded but doesn't seem to exist!\n" + util.inspect(imageFile));
}
});
The MongoDB part isn't complicated. Once a Buffer is in the model, just let the db save it. MongoDB converts that into BinData. 80% of this code is just getting an image into and out of a PNG file.
People say don't store images in MongoDB, but icons/thumbs are tiny. Having said that, it might be a good idea to have an icons collection and only store them once using a hash of the image data as the _id.
model class example
class MyModel {
_icon: Buffer
get icon(): Buffer {
return this._icon
}
set icon(value: Buffer) {
this._icon = value
}
}
image helper
static async loadImage(url: string) {
var files = require('../lib/files')
var buffer = await files.urlContents(url, true)
return buffer
}
static async saveImage(image: Buffer, path: string) {
var files = require('../lib/files')
files.write(path, image.buffer)
return path
}
files helper
function urlResponse(url, binary) {
var request = require("request")
if (binary)
request = request.defaults({ encoding: null })
return new Promise(function (resolve, reject) {
request(url, function (error, res, body) {
if (error || res.statusCode !== 200 || body.includes('Incomplete response received from application'))
resolve({ statusCode: res?.statusCode !== 200 ? (res?.statusCode || 500) : 500 });
else
resolve(res);
});
});
}
async function urlContents(url, binary) {
var res = await urlResponse(url, binary)
if (binary)
return Buffer.from(res.body)
else
return res.body
}
function write(fileName, contents) {
fs.writeFileSync(fileName, contents)
}
mongodb helper
// ...saving
myModel.icon = loadImage('http://some.site.com/image.png')
collection.insertOne(myModel)
// ..getting
myModel = collection.findOne(query) // now myModel contains icon
saveImage(myModel.icon, '/home/toddmo/pictures/wow.png')
I'm currently looking into building a small REST based service to which I can POST some data into a mongoose db and GET the data back.
Here's my main.js file:
var http = require("http");
var DAO = require("./DAO");
var express = require("express");
var util = require('util');
var app = express();
app.use(express.bodyParser());
app.post('/postIsles',function(req,res){
DAO[req.method](req.body);
res.send("body" + req.body.name);
});
app.get('/getIsles',function(req,res){
var isleVar = DAO[req.method](req);
res.send(isleVar);
});
app.listen("3000");
console.log("\nApp available at http://127.0.0.1:3000\n");
And DAO.js:
var mongoose = require('mongoose');
//Connect to database
mongoose.connect( 'mongodb://127.0.0.1:27017/library_database' );
//Schemas
var Isle = new mongoose.Schema({
name: String,
description: String,
lastStocked: Date
});
//Models
var IsleModel = mongoose.model( 'Isle', Isle );
function POST(request) {
var name = request.name;
var description = request.description;
var lastStocked = request.lastStocked;
console.log("POST REQ +" + request);
var isle = new IsleModel({
name: name,
description: description,
lastStocked: lastStocked
});
isle.save( function( err ) {
if( !err ) {
return console.log( 'created' );
} else {
return console.log( err );
}
});
}
function GET(request) {
return IsleModel.find( function( err, islesT ) {
if( !err ) {
console.log("isles :"+islesT);
return islesT;
} else {
return console.log( err );
}
});
}
exports.POST = POST;
exports.GET = GET;
When I try to run the GET, I get the following error:
TypeError: Converting circular structure to JSON
at Object.stringify (native)
I'm a bit unsure how to overcome this.
Remember when using Node.js: any operation that involves IO will be asynchronous.
Model#find is an asynchronous method, so isleVar is not set to the result you're expecting. Your result will only be available inside of the anonymous function that you pass into IsleModel.find
To fix your GET method, you'll need to modify your code to take into account the asynchronicity of the DB request and only send the response once your app has had a chance to retrieve data.
Below, is an example of one possible solution to fix /getIsles:
In main.js, modify your get route to pass in res (so it can be handled asynchronously)
app.get('/getIsles',function(req,res){
return DAO[req.method](req, res);
});
In DAO.js, have response send the data inside of your callback to IsleModel.find
function GET(request, response) {
IsleModel.find( function( err, islesT ) {
if( !err ) {
console.log("isles :"+islesT);
response.send(islesT);
} else {
return console.log( err );
}
});
}