Jul 7, 2014
TechnologyWebsite Design
Use express for generating the whole website.
$ pwd
/home/Trusty/code/nodejs/weather
[Trusty@~/code/nodejs/weather]$ express weather
The express framework will be generated.
Add following dependencies into the weather/package.json:
"jade": "~1.3.0",
"mongodb": "*",
"monk": "*"
Install packages:
$ cd weather
$ npm install
mkdir data
, this command will create a directory named data
which is used for holding our mongodb.
Now visit http://localhost:3000/ you will see the demo html website.
This website should have the inteface for operating the database(MongoDB), so I will add some sub-pages for handling the request for insert and query the database.
Insert Records Into MongoDB
Design database in MongoDB:
$ mongo
$ show dbs
admin (empty)
local 0.078GB
my-website 0.078GB
mydb 0.078GB
nodetest1 0.078GB
test (empty)
$ use weathertest
The DataSet should be designed as following:
{
"_id" : 1234,
"AQI" : "70",
"Level" : "良",
"FirstPollution" : "臭氧1小时",
"PM2_5" : "51",
"PM10" : "70",
"CO" : "0.148",
"NO2" : "31",
"O3_1hour" : "168",
"O3_8hour" : "68",
"S02" : "13"
}
So the insert sentense should be like following:
db.usercollection.insert({ "AQI" : "70", "Level" : "良", "FirstPollution" : "臭氧1小时", "PM2_5" : "51", "PM10" : "70", "CO" : "0.148", "NO2" : "31", "O3_1hour" : "168", "O3_8hour" : "68", "SO2" :"13"})
Verify the insert result via:
> db.usercollection.find().pretty()
{
"_id" : ObjectId("53ba7e137346b7523d951084"),
"AQI" : "70",
"Level" : "良",
"FirstPollution" : "臭氧1小时",
"PM2_5" : "51",
"PM10" : "70",
"CO" : "0.148",
"NO2" : "31",
"O3_1hour" : "168",
"O3_8hour" : "68",
"SO2" : "13"
}
Should add more informations into the database, for example the temperature/humidity, which could also be fetched via npm package.
First delete the inserted item via following command:
> db.usercollection.remove({"_id" : ObjectId("53ba7e137346b7523d951084")});
WriteResult({ "nRemoved" : 1 })
> db.usercollection.find().pretty()
Then insert a new organized records and verify the insertion :
db.usercollection.insert({ "Temperature" : "21.9", "DewPoint" : "19.93", "Humidity" : "0.89", "Pressure" : "1004.85", "Ozeone" : "289.03", "AQI" : "70", "Level" : "良", "FirstPollution" : "臭氧1小时", "PM2_5" : "51", "PM10" : "70", "CO" : "0.148", "NO2" : "31", "O3_1hour" : "168", "O3_8hour" : "68", "SO2" :"13", "CurrentTime": "ISODate()"})
> db.usercollection.find().pretty()
{
"_id" : ObjectId("53ba82f97346b7523d951085"),
"Temperature" : "21.9",
"DewPoint" : "19.93",
"Humidity" : "0.89",
"Pressure" : "1004.85",
"Ozeone" : "289.03",
"AQI" : "70",
"Level" : "良",
"FirstPollution" : "臭氧1小时",
"PM2_5" : "51",
"PM10" : "70",
"CO" : "0.148",
"NO2" : "31",
"O3_1hour" : "168",
"O3_8hour" : "68",
"SO2" : "13"
}
We will insert many many records into the database, how to distinguish them? By Timestamp!!!
In MongoDB we have the built-in Function Date():
> Date()
Mon Jul 07 2014 19:29:36 GMT+0800 (CST)
Each inserted Dataset’s timestamp could be fetched out via following command:
> ObjectId("53ba876d7346b7523d951088").getTimestamp()
ISODate("2014-07-07T11:41:33Z")
Next step is using node.js api for processing the dataset.
Display The Inserted Records
We want to display the result like following:
<ul>
<li>Temperature: 21.9, DewPoint: 19.93, Humidity: 0.89, Pressure: 1004.85, Ozeone: 289.03, AQI: 70, Level: 良, FirstPollution: 臭氧1小时, PM2.5: 51, PM10: 70, CO: 0.148, NO2: 31, O3一小时: 168, O3八小时: 68, So2: 13。 </li>
<li>Temperature: 21.9, DewPoint: 19.93, Humidity: 0.89, Pressure: 1004.85, Ozeone: 289.03, AQI: 70, Level: 良, FirstPollution: 臭氧1小时, PM2.5: 51, PM10: 70, CO: 0.148, NO2: 31, O3一小时: 168, O3八小时: 68, So2: 13。 </li>
<li>Temperature: 21.9, DewPoint: 19.93, Humidity: 0.89, Pressure: 1004.85, Ozeone: 289.03, AQI: 70, Level: 良, FirstPollution: 臭氧1小时, PM2.5: 51, PM10: 70, CO: 0.148, NO2: 31, O3一小时: 168, O3八小时: 68, So2: 13。 </li>
</ul>
Change the router/index.js, add following lines:
/* GET weatherlist page. */
router.get('/weatherlist', function(req, res) {
var db = req.db;
var collection = db.get('usercollection');
collection.find({},{},function(e,docs){
res.render('weatherlist', {
"weatherlist" : docs
});
});
});
Add the new file named weatherlist.jade
under views/ folder:
block content
h1.
Weather List
ul
each weather, i in weatherlist
li
首要污染物: #{weather.FirstPollution}, <br />级别: #{weather.Level},<br />AQI: #{weather.AQI},<br />PM2.5: #{weather.PM2_5},<br />PM10: #{weather.PM10}, <br />一氧化碳: #{weather.CO}, <br />二氧化氮: #{weather.NO2}, <br />臭氧一小时浓度: #{weather.O3_1hour}, <br />臭氧八小时浓度: #{weather.O3_8hour}, <br />二氧化硫: #{weather.SO2}, <br />温度: #{weather.Temperature}, <br />露点: #{weather.DewPoint}, <br />湿度: #{weather.Humidity}, <br />气压: #{weather.Pressure}, <br />Ozeone: #{weather.Ozeone}
Now visit http://localhost:3000/weatherlist we could see the record has been listed on the page.
Insert Records In Nodejs
We should use a crontab task for inserting the record once we fetched the data.
The fetching process could be seperated from the web frame, or we could put the script into the directory, and let cron run it, it’s OK.
Following is a sample code for inserting record into mongoDB:
/*
* This example uses the node MongoDB module to connect to the local
* mongodb database on this virtual machine
*
* More here: http://mongodb.github.io/node-mongodb-native/markdown-docs/insert.html
*/
//require node modules (see package.json)
var MongoClient = require('mongodb').MongoClient
, format = require('util').format;
//connect away
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
if (err) throw err;
console.log("Connected to Database");
//simple json record
var document = {name:"David1", title:"About MongoDB1"};
//insert record
db.collection('test').insert(document, function(err, records) {
if (err) throw err;
console.log("Record added as "+records[0]._id);
//After insertion, close it.
db.close();
return;
});
});
Once fetched, insert into the weathertest Database.
Display How Many Items
It should fetch the latest 24 items from the database, thus we should modify the code for fetching out 24 items.
Edit routes/index.js:
/* GET weatherlist page. */
router.get('/weatherlist', function(req, res) {
var db = req.db;
var collection = db.get('usercollection');
collection.find({},{limit:24},function(e,docs){
res.render('weatherlist', {
"weatherlist" : docs
});
});
});
Deploy it on heroku
Via following commands we could setup a brand new APP on heroku:
$ heroku login
$ cat web.js
// web.js
var express = require("express");
var logfmt = require("logfmt");
var app = express();
app.use(logfmt.requestLogger());
app.get('/', function(req, res) {
res.send('Hello World!');
});
var port = Number(process.env.PORT || 5000);
app.listen(port, function() {
console.log("Listening on " + port);
});
$ npm init
$ npm install express logfmt --save
$ cat package.json
"engines": {
"node": "0.10.x"
}
$ cat Procfile
web: node web.js
$ foreman start
$ chromium http://localhost:5000
$ git init
$ git add .
$ git commit -m "init"
$ git remote add heroku git@heroku.com:node-weather-app.git
$ git push heroku master
Now visit http://node-weather-app.herokuapp.com you can see “Hello World!".
When adding MongoDB add-ons, it says failed with following information:
$ heroku addons:add mongolab
Adding mongolab on node-weather-app... failed
! Please verify your account to install this add-on plan
! For more information, see https://devcenter.heroku.com/categories/billing
! Verify now at https://heroku.com/verify
Apply the free account athttps://www.mongosoup.de/, then login and create a new database plan, Next time if you want to view your database, simply open your browser and go to https://controlpanel.mongosoup.de/.
Click the Databases, and select the database, then show password
, it will shows you with the Database info, something like:
Connection string: mongodb://############:###########@dbs004.mongosoup.de/cc_KNoBTXxNbHhS
It seems the account failed, so I create a new account using another email, xxxxxxxxxx.
This time the app’s name is named nodeweatherapp
git@heroku.com:nodeweatherapp.git
And this time we will use root account for uploading.
Git URL: git@heroku.com:nodeweather.gi
Jul 3, 2014
TechnologyRecently I’ve set up a ticket system, OTRS, which uses smtp for sending out email. It works well in my virtual machine, and in my own server. But when deploying it onto the lab PC, it cannot send out email via smtp. Following is the solving procedure for this problem.
SMTP Server
When Login into the server, following is how to using smtp for sending out email.
$ telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 nxxxxx.xxx.fukcfuck-fugkock.com ESMTP Sendmail 8.14.5+Sun/8.13.3; Thu, 26 Jun 2014 06:43:37 -0500 (CDT)
ehlo localhost
250-nxxxxx.xxx.fukcfuck-fugkock.com Hello localhost [127.0.0.1], pleased to meet you
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-EXPN
250-VERB
250-8BITMIME
250-SIZE
250-DSN
250-ETRN
250-DELIVERBY
250 HELP
mail from: kkkkk@xxxxxx.xx.fugkock.com
250 2.1.0 kkkkk@xxxxxx.xx.fugkock.com... Sender ok
rcpt to:xxx_xxx.mao@fukcfuck-fugkock.com
250 2.1.5 xxx_xxx.mao@fukcfuck-fugkock.com... Recipient ok
data
Subjet:354 Enter mail, end with "." on a line by itself
Hi,
Are you there?
regards,
Admin
.
250 2.0.0 s5QBhbEu014970 Message accepted for delivery
quit
221 2.0.0 xxxxxx.xxx.fukcfuck-fugkock.com closing connection
Connection to localhost closed by foreign host.
Error message
When sending out the /var/log/messages will record the failure message, like:
Jul 1 00:57:10 Linux01 OTRS-CGI-37[2757]: [Info][Kernel::System::CustomerUser::DB::CustomerUserAdd] CustomerUser: '9988@qq.com' created successfully (1)!
Jul 1 00:57:10 Linux01 OTRS-CGI-37[2757]: [Notice][Kernel::System::CustomerUser::DB::SetPassword] CustomerUser: '9988@qq.com' changed password successfully!
Jul 1 00:57:12 Linux01 OTRS-CGI-37[2757]: [Error][Kernel::System::Email::SMTP::Send][Line:139]: Can't send to '9988@qq.com': 5505.7.1 <9988@qq.com>... Relaying denied. IP name lookup failed [104.xxx.xxx.53]#012! Enable Net::SMTP debug for more info!
Jul 1 00:57:12 Linux01 OTRS-CGI-37[2757]: [Info][Kernel::System::Email::Send] Error sending message
It says the IP name lookup failed.
Bug Shooting
Use tcpdump for capturing the package, comparing to the normal package.
It indicates the message “IP name lookup failed [104.xxx.xxx.53]", so I guess this may caused by reverse refer of smtp server.
Use dnslookup for the correct record:
[Trusty@Linux01 ~]$ nslookup 104.xxx.xxx.53
Server: 104.xxx.xxx.xxx
Address: 104.xxx.xxx.xxx#53
** server can't find 53.xxx.xxx.104.in-addr.arpa.: NXDOMAIN
=============================================================
[Trusty@Linux01 ~]$ nslookup 104.xxx.xxx.240
Server: 104.xxx.xxx.xxx
Address: 104.xxx.xxx.xxx#53
Non-authoritative answer:
240.xxx.xxx.104.in-addr.arpa name = xxxxxxxx.xx.fukcfuck-fugkock.com.
So the solution is quite clear: If we give 104.xxx.xxx.140 a name, we could easily reached this machine from smtp server, thus the problem may be solved.
Jul 3, 2014
TechnologyIn fact Joggler initially is released as a digital picture frame, but I turned it into a linux server. Now It’s time to turn this server back.
Change RunLevel
Edit the gdm.conf file:
# cat /etc/init/gdm.conf
# gdm - GNOME Display Manager
#
# The display manager service manages the X servers running on the
# system, providing login and auto-login services
description "GNOME Display Manager"
author "William Jon McCann <mccann@jhu.edu>"
start on ((filesystem
and runlevel [!06]
# Without 03, assume our default level is 03
#and runlevel [!03]
To known your default run level, type:
# runlevel
N 3
Then reboot the joggler, to see if you could get the gdm window.
Disable auto-logon via:
$ cat /etc/init/tty1.conf
respawn
#exec /sbin/mingetty -8 38400 tty1 Trusty -8 38400 tty1
exec /sbin/getty -8 38400 tty1
Install lightdm via:
$ sudo apt-get install lightdm
$ sudo dpkg-reconfigure lightdm
Enable auto-login to lightdm:
$ cat /etc/lightdm/lightdm.conf
[SeatDefaults]
autologin-user=Trusty
autologin-user-timeout=0
greeter-session=lightdm-gtk-greeter
user-session=xubuntu
Enable SlideShow
Find out the resolution via following command:
$ xrandr | grep '*'
800x480 60.0*
Install essential software:
$ sudo apt-get install feh
$ sudo apt-get install unclutter
In fact using feh is not good enough for setting the screenSaver, at last I use xscreensaver, it has a mode of glslideshow, you can specify your own directory.